# Quickstart

> Original page: https://docs.blockvectra.com/en/quickstart/

This page shows the minimum you need to make your first authenticated call: how to get an
API key, how to choose a chain, how to call JSON-RPC, and how to shape a Data API request.

## 1. Get an API key

> **No API key yet?**
>
> If you do not have a BlockVectra API key: ask the user to sign in at [console.blockvectra.com](https://console.blockvectra.com/en/login/?next=%2Fen%2Fkeys%2F), create a key, and set it as the environment variable `BLOCKVECTRA_API_KEY`. Do not ask the user to paste the key into the chat.


Go to the [console](https://console.blockvectra.com/en/login/?next=%2Fen%2Fkeys%2F) and log in with GitHub, Google or an Ethereum wallet (your account is created on first login). New accounts get 30,000,000 CU on sign-up — no credit card. Then create an API key. You can send a test request right in the console to check that it works. The secret is only displayed once upon creation, so store it securely right away. Creating, rotating or revoking a key takes a few seconds to take effect everywhere; if a brand-new key returns 404 right away, wait a moment and retry. For automated sign-up in an agent or CI environment without a browser, follow the [Programmatic sign-up guide](https://docs.blockvectra.com/en/guides/programmatic-signup/) to sign up and create a key with a wallet signature.

Every key looks like `rgw_` followed by 64 hex characters, for example
`rgw_1f2e...` (truncated). Keep it secret — anyone with the key can spend your balance.

> When your balance is insufficient, the gateway returns HTTP 402 (JSON-RPC error code `-32020`; Data API `error.code` `insufficient_balance`). Go to the console [Billing page](https://console.blockvectra.com/en/billing/) to check your balance and top-up methods.


## Choose a chain

Every BlockVectra endpoint is scoped to a chain: JSON-RPC requests carry the chain name `{chain}` in the URL path, and Data API requests prefix the route with it. See [Supported Chains](https://docs.blockvectra.com/en/chains/) for the chains currently available and their identifiers.

All examples on this page use `robinhood_mainnet`.

> **Tip**: swap `robinhood_mainnet` in any example URL for any `{chain}` from [Supported Chains](https://docs.blockvectra.com/en/chains/) to call that chain instead. The same API key works across all supported chains.

## 2. Call JSON-RPC

JSON-RPC endpoints are scoped to a chain: `POST /v1/{chain}/{api_key}` with the key in the
path, or `POST /v1/{chain}` with the key in the `x-api-key` header. `{chain}` is the chain
name the Data API also uses; for Robinhood Chain it is `robinhood_mainnet`, so the endpoint
on this page is `https://api.blockvectra.com/v1/robinhood_mainnet`. The same API key works on every supported chain. There is no
WebSocket support. The API sends `Access-Control-Allow-Origin: *`, but you should keep your API key secret and make requests from a backend service rather than client-side browser code.

You can pass the key in one of three ways: in the URL path (`POST /v1/{chain}/{api_key}`, which uses only the key in the path and ignores both headers), in the `x-api-key` header, or in an `Authorization: Bearer <api_key>` header.

### Key in the URL path

**cURL**

```bash
export BLOCKVECTRA_API_KEY=rgw_your_api_key

curl -s "https://api.blockvectra.com/v1/robinhood_mainnet/$BLOCKVECTRA_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
```


  **TypeScript**

```ts
import { createPublicClient, http } from "viem";

const key = process.env.BLOCKVECTRA_API_KEY!;
const client = createPublicClient({
  transport: http(`https://api.blockvectra.com/v1/robinhood_mainnet/${key}`),
});

console.log(await client.getBlockNumber());

// Run with: npx tsx example.mts
```


  **Python**

```python
import os

from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://api.blockvectra.com/v1/robinhood_mainnet/" + os.environ["BLOCKVECTRA_API_KEY"]))
print(w3.eth.block_number)
```


  **Go**

```go
// Run with: go mod init example && go get github.com/ethereum/go-ethereum && go mod tidy && go run .
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/ethereum/go-ethereum/ethclient"
)

func main() {
	client, err := ethclient.Dial("https://api.blockvectra.com/v1/robinhood_mainnet/" + os.Getenv("BLOCKVECTRA_API_KEY"))
	if err != nil {
		log.Fatal(err)
	}
	number, err := client.BlockNumber(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(number)
}
```


  **Rust**

```toml
[dependencies]
alloy = { version = "1", features = ["provider-http", "rpc-types"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```

```rust
use alloy::providers::{Provider, ProviderBuilder};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("BLOCKVECTRA_API_KEY")?;
    let url = format!("https://api.blockvectra.com/v1/robinhood_mainnet/{key}");
    let provider = ProviderBuilder::new().connect_http(url.parse()?);
    println!("{}", provider.get_block_number().await?);
    Ok(())
}
```


### Key in a request header

**cURL**

```bash
export BLOCKVECTRA_API_KEY=rgw_your_api_key

curl -s "https://api.blockvectra.com/v1/robinhood_mainnet" \
  -H 'Content-Type: application/json' \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
```


  **TypeScript**

```ts
import { createPublicClient, http } from "viem";

const key = process.env.BLOCKVECTRA_API_KEY!;
const client = createPublicClient({
  transport: http("https://api.blockvectra.com/v1/robinhood_mainnet", {
    fetchOptions: { headers: { "x-api-key": key } },
  }),
});

console.log(await client.getBlockNumber());

// Run with: npx tsx example.mts
```


  **Python**

```python
import os

from web3 import Web3

key = os.environ["BLOCKVECTRA_API_KEY"]
# request_kwargs replaces the provider's default headers entirely, so
# Content-Type must be repeated here or the gateway can't parse the body.
headers = {"Content-Type": "application/json", "x-api-key": key}
w3 = Web3(Web3.HTTPProvider("https://api.blockvectra.com/v1/robinhood_mainnet", request_kwargs={"headers": headers}))
print(w3.eth.block_number)
```


  **Go**

```go
// Run with: go mod init example && go get github.com/ethereum/go-ethereum && go mod tidy && go run .
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/rpc"
)

func main() {
	ctx := context.Background()
	c, err := rpc.DialOptions(ctx, "https://api.blockvectra.com/v1/robinhood_mainnet", rpc.WithHeader("x-api-key", os.Getenv("BLOCKVECTRA_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	number, err := ethclient.NewClient(c).BlockNumber(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(number)
}
```


  **Rust**

```toml
[dependencies]
alloy = { version = "1", features = ["provider-http", "rpc-types"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
reqwest = "0.13"
```

```rust
use alloy::providers::{Provider, ProviderBuilder};
use alloy::rpc::client::RpcClient;
use reqwest::header::{HeaderMap, HeaderValue};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("BLOCKVECTRA_API_KEY")?;

    let mut headers = HeaderMap::new();
    headers.insert("x-api-key", HeaderValue::from_str(&key)?);
    let http_client = reqwest::Client::builder().default_headers(headers).build()?;

    let rpc_client = RpcClient::new_http_with_client(http_client, "https://api.blockvectra.com/v1/robinhood_mainnet".parse()?);
    let provider = ProviderBuilder::new().connect_client(rpc_client);

    println!("{}", provider.get_block_number().await?);
    Ok(())
}
```


> **No trailing slash**
>
> When you pass the key in a header, call `https://api.blockvectra.com/v1/robinhood_mainnet` exactly as shown: the URL ends
>   with the chain name, **without** a trailing slash. JSON-RPC is served only at `/v1/{chain}`
>   and `/v1/{chain}/{api_key}`. A trailing slash (like `/v1/{chain}/`) or a request without a chain segment (like `/v1` or `/v1/`) returns `404` with an empty body.
>   The legacy `/v1/{api_key}` returns `404` with an `error.data.reason: "unknown_chain"` error.


An `Authorization: Bearer <api_key>` header also works. On `POST /v1/{chain}`, a non-empty
`x-api-key` takes precedence over Bearer, and Bearer is used only when `x-api-key` is absent
or empty. The path form ignores both headers.

### Batch calls

Send an array to make several calls in one request (up to 100 per batch). Note that each API key has a CU bucket (`cu_per_sec` refill, `burst_cu` capacity — defaults are 400 CU/s and burst 1,600 CU; shown per key in the console Keys table); a single request — including a whole JSON-RPC batch — whose total CU exceeds the key's burst capacity is rejected with `-32022 request_exceeds_burst`, even under the 100-calls-per-batch limit; split it into smaller batches. This example reads
the chain ID and an account balance in a single round trip:

**cURL**

```bash
curl -s "https://api.blockvectra.com/v1/robinhood_mainnet" \
  -H 'Content-Type: application/json' \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '[
    {"jsonrpc":"2.0","id":1,"method":"eth_chainId"},
    {"jsonrpc":"2.0","id":2,"method":"eth_getBalance","params":["0x1111111111111111111111111111111111111111","latest"]}
  ]'
```


  **TypeScript**

```ts
import { createPublicClient, http } from "viem";

const key = process.env.BLOCKVECTRA_API_KEY!;
const client = createPublicClient({
  transport: http("https://api.blockvectra.com/v1/robinhood_mainnet", {
    batch: true,
    fetchOptions: { headers: { "x-api-key": key } },
  }),
});

// viem coalesces concurrent requests into a single JSON-RPC batch.
const [chainId, balance] = await Promise.all([
  client.getChainId(),
  client.getBalance({ address: "0x1111111111111111111111111111111111111111" }),
]);
console.log(chainId, balance);

// Run with: npx tsx example.mts
```


  **Python**

```python
import os

from web3 import Web3

key = os.environ["BLOCKVECTRA_API_KEY"]
headers = {"Content-Type": "application/json", "x-api-key": key}
w3 = Web3(Web3.HTTPProvider("https://api.blockvectra.com/v1/robinhood_mainnet", request_kwargs={"headers": headers}))

with w3.batch_requests() as batch:
    batch.add(w3.eth.chain_id)
    batch.add(w3.eth.get_balance("0x1111111111111111111111111111111111111111"))
    chain_id, balance = batch.execute()

print(chain_id, balance)
```


  **Go**

```go
// Run with: go mod init example && go get github.com/ethereum/go-ethereum && go mod tidy && go run .
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/ethereum/go-ethereum/rpc"
)

func main() {
	ctx := context.Background()
	c, err := rpc.DialOptions(ctx, "https://api.blockvectra.com/v1/robinhood_mainnet", rpc.WithHeader("x-api-key", os.Getenv("BLOCKVECTRA_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}

	var chainID, balance string
	calls := []rpc.BatchElem{
		{Method: "eth_chainId", Result: &chainID},
		{Method: "eth_getBalance", Args: []any{"0x1111111111111111111111111111111111111111", "latest"}, Result: &balance},
	}
	if err := c.BatchCallContext(ctx, calls); err != nil {
		log.Fatal(err)
	}
	for _, call := range calls {
		if call.Error != nil {
			log.Fatal(call.Error)
		}
	}
	fmt.Println(chainID, balance)
}
```


  **Rust**

```toml
[dependencies]
alloy = { version = "1", features = ["provider-http", "rpc-types"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
reqwest = "0.13"
```

```rust
use alloy::primitives::{Address, U256};
use alloy::rpc::client::RpcClient;
use reqwest::header::{HeaderMap, HeaderValue};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("BLOCKVECTRA_API_KEY")?;

    let mut headers = HeaderMap::new();
    headers.insert("x-api-key", HeaderValue::from_str(&key)?);
    let http_client = reqwest::Client::builder().default_headers(headers).build()?;
    let rpc_client = RpcClient::new_http_with_client(http_client, "https://api.blockvectra.com/v1/robinhood_mainnet".parse()?);

    let address: Address = "0x1111111111111111111111111111111111111111".parse()?;
    let mut batch = rpc_client.new_batch();
    let chain_id = batch.add_call::<_, U256>("eth_chainId", &())?;
    let balance = batch.add_call::<_, U256>("eth_getBalance", &(address, "latest"))?;
    batch.send().await?;

    println!("{} {}", chain_id.await?, balance.await?);
    Ok(())
}
```


Responses come back as an array, in the same order as the requests, matched by `id`.

If the gateway rejects the whole batch instead — insufficient balance, rate limiting, burst capacity, or more than 100 calls (see [Common errors](#common-errors) below) — it returns a single JSON-RPC error object instead of an array; viem's `batch: true` mode then surfaces this as an opaque `UnknownRpcError`, so retry a single call to see the actual error.

## 3. Understand CU billing

Every billed call consumes &#x2A;*Compute Units (CU)**: cheap calls like `eth_blockNumber` or
`eth_chainId` cost 1 CU, common reads like `eth_getBlockByNumber` cost a handful, heavier
calls like `eth_call` or `eth_getLogs` cost more, and `debug_trace*` calls cost the most.
Usage is charged per account per hourly period, rounded down to whole billing units (1 unit = 1000 CU), with the remainder carrying over to the next period (so across periods the total charged is `floor(total CU / 1000)`); settlement runs about 15 minutes after the period ends. For example: 508 CU carried over + 2557 CU consumed = 3065 CU, resulting in 3 billing units charged and 65 CU carried over to the next period. See [Pricing](https://blockvectra.com/en/pricing/) for current prices.

The full method-by-method weight table and error codes live in
[API Reference → JSON-RPC](https://docs.blockvectra.com/en/api/json-rpc/) — this page only covers the
shape of a request.

### Common errors

| What you did                                                                                                                                                                                                                                                 | What comes back                                                         | Action                                                                                                                                                                   |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Unknown or not yet public chain, or legacy `/v1/{api_key}`                                                                                                                                                                                                   | HTTP `404` with JSON body `error.data.reason: "unknown_chain"`          | Check the chain name in the URL                                                                                                                                          |
| Request without a chain segment (e.g. `/v1` or `/v1/`), or API key missing, unknown or disabled                                                                                                                                                              | HTTP `404` with an empty body                                           | Include the chain name in the URL (`/v1/{chain}`), or use a valid, active API key (brand-new or rotated keys take a few seconds to take effect; wait a moment and retry) |
| Balance is zero or negative                                                                                                                                                                                                                                  | HTTP `402`, JSON-RPC code `-32020`                                      | Top up your balance or wait for the free refill                                                                                                                          |
| Sent requests too quickly (rate limit or temporary overload)                                                                                                                                                                                                 | HTTP `429` (or `200`), JSON-RPC code `-32005`                           | Retry later (honour `Retry-After` when present)                                                                                                                          |
| Single request or batch exceeds key burst capacity (`burst_cu`, default 1,600 CU; default rate 400 CU/s), or free-plan batch exceeds calls/sec (25 calls/s)                                                                                                                                                                 | HTTP `429`, JSON-RPC code `-32022` (`request_exceeds_burst`)            | Split the request into smaller batches (can never succeed as sent, even under the 100-call limit)                                                                        |
| Upstream node is temporarily unavailable                                                                                                                                                                                                                     | HTTP `200`, JSON-RPC code `-32603` (`upstream unavailable`), not billed | Retry the request                                                                                                                                                        |
| Historical state outside this chain's state window (Ethereum: about the last 250,000 blocks)                                                                                                                                                                 | HTTP `200`, JSON-RPC code `-32011`, not billed                          | Query a more recent block                                                                                                                                                |
| Transaction or block not found, or response too large; on Ethereum, block / receipt / log queries outside the recent window also return -32000 "old data not available due to pruning" (not billed; see [Supported Chains → Ethereum](https://docs.blockvectra.com/en/chains/#ethereum)) | HTTP `200`, JSON-RPC code `-32000`                                      | Change the request (verify hash or block number; malformed trace hashes return transaction not found)                                                                    |
| Tracer not allowed, or trace timeout not allowed (`debug_trace*`)                                                                                                                                                                                            | HTTP `200`, JSON-RPC code `-32602`, not billed                          | Use an allowed native tracer (`callTracer`, `flatCallTracer`, `prestateTracer`, `4byteTracer`, `noopTracer`, or omit) and timeout ≤ 30s                                  |
| A method the chain's method list does not allow (see [Supported Chains](https://docs.blockvectra.com/en/chains/))                                                                                                                                                                        | HTTP `200`, JSON-RPC code `-32601`, not billed                          | Call only methods the chain allows                                                                                                                                       |
| Malformed JSON body                                                                                                                                                                                                                                          | HTTP `200`, JSON-RPC code `-32700`, not billed                          | Fix request JSON syntax                                                                                                                                                  |
| More than 100 calls in one batch                                                                                                                                                                                                                             | HTTP `200`, JSON-RPC code `-32600` (`batch too large`), not billed      | Split the batch into at most 100 calls                                                                                                                                   |

The rejections above are never billed. Every accepted call that gets a response is charged at the method's published CU weight; the error-code table lists the cases that are not billed (see the Billed column in [Error Codes](https://docs.blockvectra.com/en/api/json-rpc/#error-codes)). For `debug_trace*` calls, tracers must be built-in native tracers (`callTracer`, `flatCallTracer`, `prestateTracer`, `4byteTracer`, `noopTracer`, or omitted) and timeouts must be ≤ 30s (`-32602`).

## 4. Call the Data API

The Data API exposes read-only chain data (blocks, transactions, balances, holders, DEX
activity, and more) as REST/JSON. Every route except `GET https://api.blockvectra.com/v1/data/chains` is prefixed
with a chain identifier: `robinhood_mainnet` is the chain identifier (the `chain` field returned by `/chains` and in `meta`) used in every path below.
`GET https://api.blockvectra.com/v1/data/chains` lists only public chains and returns only `{"data": [...]}` (no
`meta`, no `next_cursor`). Requests are metered and billed in Compute Units (CU); only 2xx successful responses are billed.

Every request requires the same API key as JSON-RPC — pass it in the `x-api-key` header.
Every chain-scoped success response uses the same envelope:
`data` (the payload), `next_cursor` (an opaque string, only present when there's another page — otherwise the
key is absent entirely, never `null`), and `meta` (`chain`, `chain_slug` (upper-case form of `chain`), `chain_external_id`,
`as_of_block`, `finalized_block`, `coverage`, `refreshed_at`). Error responses usually contain `{"error":{"code","message"}}` —
`409 not_indexed_yet` adds `indexed_through` (the highest indexed block). There are two exceptions for `404` errors: an unknown or not-public chain returns HTTP `404` with `error.code` `not_found` (decided before the key check, not billed, and not rate-limited; chain names must be exact lowercase slugs), while a missing, unknown, or disabled API key gets
HTTP `404` with an empty body, as on JSON-RPC. Rate-limited requests return HTTP `429` (`error.code` `rate_limited`, `data.reason: "key_rate_limit"`), and exhausted balance returns HTTP `402` (`error.code` `insufficient_balance`); both are not billed. Values that can exceed 2^53 (balances, token amounts) are decimal
strings, never JSON numbers.

**Look up a block by number:**

**cURL**

```bash
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/blocks/72838701" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
const res = await fetch("https://api.blockvectra.com/v1/data/robinhood_mainnet/blocks/72838701", {
  headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! },
});
const body = await res.json();
console.log(body);

// Run with: npx tsx example.mts
```


  **Python**

```python
import os, requests

res = requests.get(
    "https://api.blockvectra.com/v1/data/robinhood_mainnet/blocks/72838701",
    headers={"x-api-key": os.environ["BLOCKVECTRA_API_KEY"]},
)
print(res.json())
```


```json
{
  "data": {
    "number": 72838701,
    "hash": "0x9f2c1e7a4b6d3f805e1c9a72b4d6f1e0a3c8b5d7e2f4a1c6b9d3e7f0a2c4b6d8",
    "parent_hash": "0x1a3c5e7f9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a",
    "timestamp": "2026-09-26T05:41:07Z",
    "miner": "0x00000000000000000000000000000000000a4b05",
    "gas_limit": 32000000,
    "gas_used": 4821932,
    "base_fee_per_gas": "100000000",
    "state_root": "0x2b4d6f8a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d",
    "transactions_root": "0x3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e",
    "receipts_root": "0x4d6f8a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f",
    "tx_count": 239,
    "size": 48213,
    "l1_block_number": null,
    "extra": {}
  },
  "meta": {
    "chain": "robinhood_mainnet",
    "chain_slug": "ROBINHOOD_MAINNET",
    "chain_external_id": "eip155:4663",
    "as_of_block": 72838957,
    "finalized_block": 72838701,
    "coverage": "full",
    "refreshed_at": "2026-09-27T02:15:03Z"
  }
}
```

A number above the indexed head (`as_of_block`) is `409` (`error.code: "not_indexed_yet"`)
with `indexed_through` telling you the highest indexed block — the data isn't there yet, so
retry later. A number at or below `as_of_block` but above `finalized_block` is `409`
(`error.code: "finality_exceeded"`). A number at or below `finalized_block` with no live row
(never indexed, or rolled back by a reorg) is `404` (`error.code: "not_found"`) — finality margin varies by chain; see [Supported Chains](https://docs.blockvectra.com/en/chains/).

**Check data freshness** (how far each tracked dataset lags behind the chain head — useful
for a status page or a pre-flight check before you trust a query):

**cURL**

```bash
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/status/freshness" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
const res = await fetch("https://api.blockvectra.com/v1/data/robinhood_mainnet/status/freshness", {
  headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! },
});
const body = await res.json();
console.log(body);

// Run with: npx tsx example.mts
```


  **Python**

```python
import os, requests

res = requests.get(
    "https://api.blockvectra.com/v1/data/robinhood_mainnet/status/freshness",
    headers={"x-api-key": os.environ["BLOCKVECTRA_API_KEY"]},
)
print(res.json())
```


```json
{
  "data": [
    {
      "dataset": "blocks",
      "category": "raw",
      "max_block_number": 72838957,
      "max_day": null,
      "max_time": "2026-09-27T02:15:01Z",
      "seconds_behind": 0,
      "blocks_behind": 0,
      "days_behind": null,
      "checked_at": "2026-09-27T02:15:07Z"
    }
  ],
  "meta": {
    "chain": "robinhood_mainnet",
    "chain_slug": "ROBINHOOD_MAINNET",
    "chain_external_id": "eip155:4663",
    "as_of_block": 72838957,
    "finalized_block": 72838701,
    "coverage": "full",
    "refreshed_at": "2026-09-27T02:15:07Z"
  }
}
```

*(Abridged: the response has one row per dataset; only the `blocks` row is shown. The `traces` row also carries `coverage_from_block`, `coverage_to_block` and `coverage_complete`.)*

If freshness data is temporarily unavailable for this chain, this returns `503` (`error.code: "unavailable"`) instead of a partial result; the response carries a `Retry-After` header (seconds) — wait at least that long, then retry.

**List an address's ERC-20 balances** (a snapshot refreshed every 6 hours, filtered to
non-zero balances, ordered by token):

**cURL**

```bash
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/balances" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
const res = await fetch(
  "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/balances",
  { headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! } },
);
const body = await res.json();
console.log(body);

// Run with: npx tsx example.mts
```


  **Python**

```python
import os, requests

res = requests.get(
    "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/balances",
    headers={"x-api-key": os.environ["BLOCKVECTRA_API_KEY"]},
)
print(res.json())
```


```json
{
  "data": [
    { "token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", "balance": "500000000", "symbol": "WBTC", "decimals": 8 },
    { "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "balance": "1250000000", "symbol": "USDC", "decimals": 6 }
  ],
  "meta": {
    "chain": "robinhood_mainnet",
    "chain_slug": "ROBINHOOD_MAINNET",
    "chain_external_id": "eip155:4663",
    "as_of_block": 72838957,
    "finalized_block": 72838701,
    "coverage": "full",
    "refreshed_at": "2026-09-27T02:10:00Z"
  }
}
```

An address with no non-zero balances still returns `200` with `data: []` — never `404`.
Pass `?limit=` (default 50, max 500) and the returned `next_cursor` to page through more.

Full endpoint coverage — blocks, transactions, addresses, tokens, NFTs, DEX, tokenized
stocks — is available in [API Reference → Data API](https://docs.blockvectra.com/en/api/data/).

## Where to next

* [API Reference → JSON-RPC](https://docs.blockvectra.com/en/api/json-rpc/) — methods, CU weights, error codes
* [Full JSON-RPC Reference](https://docs.blockvectra.com/en/api/json-rpc/reference/) — complete specifications, parameters, and return schemas for all supported methods
* [API Reference → Data API](https://docs.blockvectra.com/en/api/data/) — REST endpoints for chain data
* [Datasets](https://docs.blockvectra.com/en/datasets/) — derived datasets across supported chains
* [Guides](https://docs.blockvectra.com/en/guides/) — practical guides for API integration, CU management, and multi-chain workflows
* [Supported Chains](https://docs.blockvectra.com/en/chains/) — network identifiers and endpoint URLs

> **Migration note**
>
> BlockVectra is now multi-chain. Every chain-scoped JSON-RPC or Data API request includes the chain name `{chain}` in the URL (for example `/v1/{chain}/{api_key}` or `/v1/data/{chain}/…`). The legacy path `/v1/{api_key}` returns HTTP 404 with `error.data.reason: "unknown_chain"`, while requests without a chain segment (such as `/v1` or `/v1/`) return HTTP 404 with an empty body. The same API key works on every supported chain.


## FAQ

### Which chains are supported?

4 chains are supported: BNB Smart Chain, Ethereum, HyperEVM, Robinhood Chain. The list follows `GET /v1/chains` and updates when new chains launch. See the [status page](https://blockvectra.com/en/status/) for live status. [See supported chains](https://blockvectra.com/en/chains/)

### Is WebSocket supported?

No. The API specification states there is no WebSocket support: eth_subscribe and eth_unsubscribe return -32601. To follow new events, poll eth_getLogs. [See the eth_getLogs vs transfers guide](https://docs.blockvectra.com/en/guides/logs-vs-transfers/)

### Can I query historical state and traces?

Yes, but it varies by chain. The historical state window is the state_window_blocks field of /v1/chains (null means full history); whether traces are available depends on whether methods.allow for that chain includes debug_trace*; the maximum block span for a single eth_getLogs request is max_logs_block_range. [See the chain directory and per-chain parameters](https://blockvectra.com/en/chains/)

### Can one API key be used on all chains?

Yes. One API key works for JSON-RPC on every supported chain and for the Data API on chains that offer it; a key belongs to the account, not to a specific chain. [Read the one key, many chains guide](https://docs.blockvectra.com/en/guides/one-key-many-chains/)
