> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/mahdiyari/hive-tx/llms.txt
> Use this file to discover all available pages before exploring further.

# API Calls

> Complete guide to making RPC and REST API calls to Hive blockchain nodes

The hive-tx library provides three methods for querying the Hive blockchain: `callRPC`, `callREST`, and `callWithQuorum`. This guide shows you how to use each one effectively.

## RPC API Calls

Use `callRPC` to call JSON-RPC 2.0 methods on Hive nodes.

### Basic RPC Calls

```typescript theme={null}
import { callRPC } from 'hive-tx'

// Get account information
const accounts = await callRPC('condenser_api.get_accounts', [['alice', 'bob']])
console.log(accounts[0].name) // 'alice'
console.log(accounts[0].balance) // '1000.000 HIVE'

// Get dynamic global properties
const props = await callRPC('condenser_api.get_dynamic_global_properties', [])
console.log('Head block:', props.head_block_number)
console.log('Total HIVE:', props.current_supply)

// Get post content
const post = await callRPC('condenser_api.get_content', ['alice', 'my-post-permlink'])
console.log('Title:', post.title)
console.log('Body:', post.body)
console.log('Upvotes:', post.net_votes)
```

### Common RPC Methods

<CardGroup cols={2}>
  <Card title="Account APIs">
    ```typescript theme={null}
    // Get accounts
    callRPC('condenser_api.get_accounts', [['alice']])

    // Get account history
    callRPC('condenser_api.get_account_history', [
      'alice',
      -1,    // start (most recent)
      1000   // limit
    ])

    // Get followers
    callRPC('condenser_api.get_followers', [
      'alice',
      '',      // start follower
      'blog',  // type
      100      // limit
    ])
    ```
  </Card>

  <Card title="Content APIs">
    ```typescript theme={null}
    // Get post
    callRPC('condenser_api.get_content', [
      'author',
      'permlink'
    ])

    // Get discussions (feed)
    callRPC('condenser_api.get_discussions_by_blog', [{
      tag: 'alice',
      limit: 20
    }])

    // Get active votes
    callRPC('condenser_api.get_active_votes', [
      'author',
      'permlink'
    ])
    ```
  </Card>

  <Card title="Blockchain APIs">
    ```typescript theme={null}
    // Get block
    callRPC('condenser_api.get_block', [12345678])

    // Get block header
    callRPC('condenser_api.get_block_header', [12345678])

    // Get config
    callRPC('condenser_api.get_config', [])
    ```
  </Card>

  <Card title="Witness APIs">
    ```typescript theme={null}
    // Get witnesses
    callRPC('condenser_api.get_witnesses', [['witness1']])

    // Get witness by account
    callRPC('condenser_api.get_witness_by_account', [
      'witness1'
    ])

    // Get witness schedule
    callRPC('condenser_api.get_witness_schedule', [])
    ```
  </Card>
</CardGroup>

### Custom Timeout and Retry

```typescript theme={null}
import { callRPC } from 'hive-tx'

// Default: 4000ms timeout, 3 retries
const data1 = await callRPC('condenser_api.get_accounts', [['alice']])

// Custom timeout (10 seconds)
const data2 = await callRPC(
  'condenser_api.get_content',
  ['author', 'permlink'],
  10_000  // 10 second timeout
)

// Custom retry count (8 attempts)
const data3 = await callRPC(
  'condenser_api.get_dynamic_global_properties',
  [],
  4000,  // timeout
  8      // retry attempts
)
```

<Note>
  The library automatically switches to the next node in the list on failure and retries the request.
</Note>

### Error Handling

```typescript theme={null}
import { callRPC, RPCError } from 'hive-tx'

try {
  const accounts = await callRPC('condenser_api.get_accounts', [['nonexistent']])
  
  if (accounts.length === 0) {
    console.log('Account not found')
  }
  
} catch (error) {
  if (error instanceof RPCError) {
    console.error('RPC Error:', error.message)
    console.error('Error code:', error.code)
    console.error('Error data:', error.data)
  } else {
    console.error('Network or other error:', error)
  }
}
```

## REST API Calls

Use `callREST` for type-safe REST API calls to specialized Hive APIs.

### Available REST APIs

* `balance` - Account balance and history
* `hafah` - HAF Account History
* `hafbe` - HAF Block Explorer
* `hivemind` - Social layer (follows, communities)
* `hivesense` - Analytics and statistics
* `reputation` - Account reputation
* `nft-tracker` - NFT tracking
* `hafsql` - SQL queries
* `status` - Node status

### Balance API

```typescript theme={null}
import { callREST } from 'hive-tx'

// Get account balances
const balances = await callREST(
  'balance',
  '/accounts/{account-name}/balances',
  { 'account-name': 'alice' }
)
console.log('HIVE balance:', balances.hive)
console.log('HBD balance:', balances.hbd)

// Get aggregated history
const history = await callREST(
  'balance',
  '/accounts/{account-name}/aggregated-history',
  {
    'account-name': 'alice',
    'coin-type': 'HBD',
    'from-block': 0,
    'to-block': 10000000
  }
)
```

### Status API

```typescript theme={null}
import { callREST } from 'hive-tx'

// Get node status
const status = await callREST('status', '/status')
console.log('Node version:', status.version)
console.log('Head block:', status.head_block_num)
console.log('Synced:', status.sync_status)
```

### Path and Query Parameters

```typescript theme={null}
import { callREST } from 'hive-tx'

// Path parameters are replaced in the URL
const data1 = await callREST(
  'balance',
  '/accounts/{account-name}/balances',
  { 'account-name': 'alice' }  // Replaces {account-name} in path
)

// Remaining parameters become query strings
const data2 = await callREST(
  'balance',
  '/accounts/{account-name}/aggregated-history',
  {
    'account-name': 'alice',    // Path parameter
    'coin-type': 'HIVE',        // Query parameter: ?coin-type=HIVE
    'from-block': 0,            // Query parameter: &from-block=0
    'to-block': 1000000         // Query parameter: &to-block=1000000
  }
)
```

### Custom Timeout and Retry

```typescript theme={null}
import { callREST } from 'hive-tx'

// With custom timeout and retry
const data = await callREST(
  'status',
  '/status',
  undefined,  // no parameters
  10_000,     // 10 second timeout
  5           // 5 retry attempts
)
```

### REST Error Handling

```typescript theme={null}
import { callREST } from 'hive-tx'

try {
  const balances = await callREST(
    'balance',
    '/accounts/{account-name}/balances',
    { 'account-name': 'alice' }
  )
  
} catch (error) {
  if (error.message.includes('HTTP 404')) {
    console.error('Endpoint not found or wrong parameters')
  } else {
    console.error('Request failed:', error.message)
  }
}
```

<Warning>
  REST API 404 errors often indicate incorrect parameters rather than missing data. Double-check your path and query parameters.
</Warning>

## Quorum Calls for Critical Operations

Use `callWithQuorum` for critical operations that require consensus from multiple nodes:

```typescript theme={null}
import { callWithQuorum } from 'hive-tx'

// Get account balance with 2-node consensus (default)
const accounts = await callWithQuorum(
  'condenser_api.get_accounts',
  [['alice']]
)

// Require 3-node consensus for critical operation
const props = await callWithQuorum(
  'condenser_api.get_dynamic_global_properties',
  [],
  3  // quorum size
)
```

### How Quorum Works

From call.ts:267-309:

1. Calls random nodes in parallel batches
2. Compares results using JSON.stringify
3. Returns the first result that appears in at least `quorum` responses
4. Automatically tries additional nodes if consensus not reached

```typescript theme={null}
// Example: Check if account exists with high confidence
import { callWithQuorum } from 'hive-tx'

try {
  const accounts = await callWithQuorum(
    'condenser_api.get_accounts',
    [['alice']],
    3  // require 3 nodes to agree
  )
  
  if (accounts.length > 0) {
    console.log('Account exists (confirmed by 3 nodes)')
  }
  
} catch (error) {
  if (error.message.includes("Couldn't reach quorum")) {
    console.error('Could not get consensus from nodes')
  } else if (error.message.includes('No more nodes available')) {
    console.error('All nodes failed')
  }
}
```

<Tip>
  Use quorum calls for:

  * Account balance checks before large transfers
  * Verifying witness votes
  * Confirming proposal data
  * Any operation where data accuracy is critical
</Tip>

<Warning>
  Quorum calls are slower because they query multiple nodes. Use them only when you need guaranteed data accuracy.
</Warning>

## Configuring Nodes

Configure RPC and REST nodes globally:

```typescript theme={null}
import { config } from 'hive-tx'

// Configure RPC nodes
config.nodes = [
  'https://api.hive.blog',
  'https://api.deathwing.me',
  'https://api.openhive.network'
]

// Configure REST nodes
config.restNodes = [
  'https://rest.hive.blog',
  'https://rest.api.openhive.network'
]

// Configure timeout (milliseconds)
config.timeout = 10_000  // 10 seconds

// Configure retry attempts
config.retry = 5
```

<Note>
  The library automatically cycles through nodes on failure. Configure multiple nodes for high availability.
</Note>

## Complete Examples

### Check Account Balance Before Transfer

```typescript theme={null}
import { callRPC, Transaction, PrivateKey } from 'hive-tx'

async function safeTransfer(
  from: string,
  to: string,
  amount: string,
  privateKey: PrivateKey
) {
  // Get account info
  const accounts = await callRPC('condenser_api.get_accounts', [[from]])
  
  if (accounts.length === 0) {
    throw new Error('Account not found')
  }
  
  // Parse balance
  const balance = parseFloat(accounts[0].balance.split(' ')[0])
  const transferAmount = parseFloat(amount.split(' ')[0])
  
  if (balance < transferAmount) {
    throw new Error(`Insufficient balance: ${balance} HIVE`)
  }
  
  // Create and broadcast transaction
  const tx = new Transaction()
  await tx.addOperation('transfer', {
    from,
    to,
    amount,
    memo: ''
  })
  
  tx.sign(privateKey)
  return await tx.broadcast(true)
}

// Usage
const key = PrivateKey.fromLogin('alice', 'password', 'active')
const result = await safeTransfer('alice', 'bob', '10.000 HIVE', key)
console.log('Transfer successful:', result.tx_id)
```

### Get Post with Full Details

```typescript theme={null}
import { callRPC } from 'hive-tx'

async function getPostDetails(author: string, permlink: string) {
  // Get post content
  const post = await callRPC('condenser_api.get_content', [author, permlink])
  
  // Get active votes
  const votes = await callRPC('condenser_api.get_active_votes', [author, permlink])
  
  return {
    title: post.title,
    body: post.body,
    created: post.created,
    author: post.author,
    permlink: post.permlink,
    upvotes: votes.filter((v: any) => v.percent > 0).length,
    downvotes: votes.filter((v: any) => v.percent < 0).length,
    payout: post.pending_payout_value,
    replies: post.children
  }
}

// Usage
const details = await getPostDetails('alice', 'my-first-post')
console.log(details)
```

### Monitor New Blocks

```typescript theme={null}
import { callRPC } from 'hive-tx'

async function watchBlocks(callback: (block: any) => void) {
  let lastBlock = 0
  
  setInterval(async () => {
    try {
      const props = await callRPC('condenser_api.get_dynamic_global_properties', [])
      const currentBlock = props.head_block_number
      
      if (currentBlock > lastBlock && lastBlock > 0) {
        // Get new blocks
        for (let i = lastBlock + 1; i <= currentBlock; i++) {
          const block = await callRPC('condenser_api.get_block', [i])
          callback(block)
        }
      }
      
      lastBlock = currentBlock
    } catch (error) {
      console.error('Error fetching blocks:', error)
    }
  }, 3000)  // Check every 3 seconds
}

// Usage
watchBlocks((block) => {
  console.log('New block:', block.block_id)
  console.log('Transactions:', block.transactions.length)
})
```

## Next Steps

* Learn about [Creating Transactions](/guides/creating-transactions)
* Set up [Memo Encryption](/guides/memo-encryption) for private messages
* Explore [Multi-signature](/guides/multi-signature) transactions
