# Один ключ, багато мереж: перемикання прикладу на іншу мережу

> Source: https://docs.blockvectra.com/uk/guides/one-key-many-chains/

## 1. Один ключ для всіх підтримуваних мереж

Один і той самий API key працює в усіх підтримуваних мережах для JSON-RPC, а також для Data API в тих мережах, де він доступний. Ключі належать вашому акаунту й не прив'язані до конкретної мережі; немає потреби створювати окремі API key для кожної мережі.

Кредити та обмеження швидкості є спільними для всіх мереж, а також для JSON-RPC API та Data API; вони не розділяються за мережами. Детальні правила тарифікації див. на [сторінці цін](https://blockvectra.com/en/pricing/).

* **Об'єднаний баланс**: платні поповнення та безкоштовні кредити діють у всіх мережах. Виклики в будь-якій мережі списуються з одного балансу акаунта.
* **Об'єднані ліміти швидкості**: швидкість поповнення обчислювальних одиниць (CU) та пікова місткість діють у всіх мережах для даного ключа. Ліміти викликів на секунду в безкоштовному плані об'єднуються для всіх підтримуваних мереж, а не розділяються для кожної окремо.
* **Шлях оновлення**: після поповнення балансу ви більше не обмежені лімітом викликів на секунду безкоштовного плану; кожен ключ залишається підпорядкованим лімітам швидкості CU та пікової місткості, як описано в [документації JSON-RPC](https://docs.blockvectra.com/en/api/json-rpc/#method-policy).

## 2. Структура URL та параметр `{chain}`

Кожен запит у межах мережі вказує свою цільову мережу в шляху URL за допомогою `{chain}`. Параметр `{chain}` — це ідентифікатор-слаг мережі малими літерами (наприклад, `robinhood_mainnet`).

| Сервіс                 | Автентифікація          | Шаблон URL                   | Опис                                                           |
| ---------------------- | ----------------------- | ---------------------------- | -------------------------------------------------------------- |
| JSON-RPC               | Ключ у шляху URL        | `POST /v1/{chain}/{api_key}` | Найпростіша форма, зручна для curl та HTTP-клієнтів            |
| JSON-RPC               | Ключ у заголовку запиту | `POST /v1/{chain}`           | Передавайте ключ через заголовок запиту `x-api-key: {api_key}` |
| Data API               | Маршрути REST           | `GET /v1/data/{chain}/…`     | Передавайте ключ через заголовок запиту `x-api-key: {api_key}` |
| Публічний список мереж | Без автентифікації      | `GET /v1/chains`             | Публічний список мереж та статичні дані (не тарифікується)     |
| Публічний статус       | Без автентифікації      | `GET /v1/status`             | Поточний статус сервісу та голови ланцюгів (не тарифікується)  |

`GET /v1/chains` повертає прапорці `jsonrpc` та `data` для кожної мережі. Звертайтеся до мережі за URL-адресами JSON-RPC, коли вона підтримує JSON-RPC, і за `GET /v1/data/{chain}/…`, коли її прапорець `data` має значення `true` (Data API обслуговує лише ці мережі).

> **Порада**: під час передачі ключа через заголовки запиту формуйте URL так, щоб він закінчувався назвою мережі **без** завершального слеша. JSON-RPC обслуговується виключно за адресами `/v1/{chain}` та `/v1/{chain}/{api_key}`. Запити із завершальним слешем (наприклад, `/v1/{chain}/`) або з відсутнім сегментом мережі повертають HTTP 404 з порожнім тілом. Запити до невідомої мережі `{chain}` повертають HTTP 404 з `error.data.reason: "unknown_chain"` (не тарифікується).

## 3. Програмне виявлення мереж та їхніх можливостей

Підтримувані мережі та їхні можливості надаються динамічно. Не хардкодьте статичний список мереж у вашому застосунку. Натомість виявляйте доступні мережі та їхні можливості під час виконання:

### Отримання статичних даних через `GET /v1/chains`

Цей публічний ендпоінт не потребує автентифікації та не тарифікується, повертаючи всі загальнодоступні мережі:

```http
GET /v1/chains
```

Приклад відповіді:

```json
{
  "chains": [
    {
      "chain": "robinhood_mainnet", "name": "Robinhood Chain", "chain_id": 4663,
      "jsonrpc": true,
      "data": true,
      "methods": {
        "allow": ["eth_blockNumber", "eth_call", "eth_chainId", "debug_traceTransaction"],
        "deny": ["eth_newFilter", "eth_newBlockFilter", "eth_newPendingTransactionFilter", "eth_getFilterLogs", "eth_getFilterChanges", "eth_uninstallFilter", "eth_subscribe", "eth_unsubscribe"]
      },
      "max_logs_block_range": 1000,
      "state_window_blocks": 900
    }
  ]
}
```

Опис полів:

* `chain`: слаг-ідентифікатор мережі (використовується для `{chain}` в URL)
* `name`: зрозуміла для людини назва, що відображається
* `chain_id`: ID ланцюга за EIP-155 (десяткове ціле число)
* `jsonrpc`: чи ввімкнено JSON-RPC
* `data`: чи ввімкнено Data API
* `methods`: політика методів JSON-RPC для цієї мережі, включаючи `allow` (дозволені методи) та `deny` (явно заборонені методи)
* `max_logs_block_range`: максимальний діапазон блоків, дозволений в одному запиті `eth_getLogs`
* `state_window_blocks`: розмір вікна історичного стану в блоках; `null`, якщо без обмежень

### Перевірка працездатності через `GET /v1/status`

Цей публічний ендпоінт не потребує автентифікації та не тарифікується, повертаючи інформацію про готовність сервісу та голови ланцюгів:

```http
GET /v1/status
```

Приклад відповіді:

```json
{
  "checked_at": "2026-09-28T12:00:00Z",
  "gateway": {
    "status": "ok"
  },
  "chains": [
    {
      "chain": "robinhood_mainnet", "name": "Robinhood Chain", "chain_id": 4663,
      "jsonrpc": true,
      "data": true,
      "data_features": ["blocks", "transactions", "address_transactions", "transfers", "token_metadata", "freshness"],
      "status": "ok",
      "head": {
        "block": 73017329,
        "time": "2026-09-28T11:59:58Z",
        "lag_seconds": 2
      }
    }
  ]
}
```

Опис полів:

* `gateway.status`: статус сервісу (`ok` або `degraded`)
* `chains[].data_features`: можливості, що надаються Data API для цієї мережі
* `chains[].status`: робочий статус вузла (`ok` або `unavailable`)
* `chains[].head`: остання голова блоку (`block`, `time`, `lag_seconds`)

## 4. Відмінності між мережами, про які слід пам'ятати

Під час перемикання між мережами переглядайте поля, надані в `GET /v1/chains`:

1. **Дозвіл та політика методів (`methods.allow` / `methods.deny`)**: доступні методи JSON-RPC відрізняються залежно від мережі відповідно до їхньої політики методів. Запит забороненого методу повертає HTTP 200 із кодом помилки JSON-RPC `-32601` (`method not available`, не тарифікується).
2. **Діапазон блоків журналів (`max_logs_block_range`)**: максимальні діапазони блоків для запитів `eth_getLogs` відрізняються залежно від мережі. Перевищення ліміту мережі повертає HTTP 200 із кодом помилки JSON-RPC `-32602` (`eth_getLogs block range too large`, не тарифікується).
3. **Вікно збереження стану (`state_window_blocks`)**: мережі з повною історією повертають `null`. У мережах із прунінгом стану запити історичного стану за межами вікна повертають HTTP 200 із кодом помилки JSON-RPC `-32011` (`historical state is not available beyond the most recent <N> blocks`, не тарифікується).
4. **Можливості та покриття Data API (`data` / `data_features`)**: мережі, які надають датасет, перелічені на сторінці [Підтримувані мережі](https://docs.blockvectra.com/en/chains/). Запит датасету, який мережа не підтримує, або блоку до початку її індексованого покриття, повертає HTTP `422` (`error.code` `no_coverage`, не тарифікується). Коли сервіс тимчасово недоступний — наприклад, коли мережа перевантажена — запити повертають HTTP `503` із заголовком `Retry-After` (не тарифікується).

## 5. Приклади коду

Повний стартовий шаблон: [blockvectra/multichain-viem](https://github.com/blockvectra/multichain-viem)

Один і той самий код працює в різних мережах шляхом оновлення змінної мережі (або зчитування її з `GET /v1/chains`), надсилання запиту `eth_blockNumber` через JSON-RPC та перевірки свіжості датасету через Data API:

**cURL**

```bash
export BLOCKVECTRA_API_KEY="rgw_your_api_key"

# Change the chain variable to target another chain from Supported Chains
CHAIN="robinhood_mainnet"

# 1. JSON-RPC: Query eth_blockNumber (POST /v1/{chain}, key in the x-api-key header).
RPC_URL="https://api.blockvectra.com/v1/$CHAIN"
curl -s "$RPC_URL" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'

# 2. Data API: Query dataset freshness (GET /v1/data/{chain}/status/freshness)
curl -s "https://api.blockvectra.com/v1/data/$CHAIN/status/freshness" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
// Change this variable to target another chain, or read it dynamically from GET /v1/chains
const chain = "robinhood_mainnet";
const apiKey = process.env.BLOCKVECTRA_API_KEY!;

// 1. JSON-RPC: Call eth_blockNumber (POST /v1/{chain})
const rpcUrl = `https://api.blockvectra.com/v1/${chain}`;
const rpcResponse = await fetch(rpcUrl, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": apiKey,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "eth_blockNumber",
    params: [],
  }),
});
const rpcResult = await rpcResponse.json();
console.log(`[${chain}] JSON-RPC blockNumber:`, rpcResult.result);

// 2. Data API: Query freshness (GET /v1/data/{chain}/status/freshness)
const dataUrl = `https://api.blockvectra.com/v1/data/${chain}/status/freshness`;
const dataResponse = await fetch(dataUrl, {
  headers: {
    "x-api-key": apiKey,
  },
});
const dataResult = await dataResponse.json();
console.log(`[${chain}] Data API freshness:`, dataResult.data);
```


  **Python**

```python
import os
import requests

# Change this variable to target another chain, or read it dynamically from GET /v1/chains
chain = "robinhood_mainnet"
api_key = os.environ["BLOCKVECTRA_API_KEY"]

# 1. JSON-RPC: Call eth_blockNumber (POST /v1/{chain})
rpc_url = f"https://api.blockvectra.com/v1/{chain}"
headers = {
    "Content-Type": "application/json",
    "x-api-key": api_key,
}
rpc_payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_blockNumber",
    "params": [],
}
rpc_resp = requests.post(rpc_url, json=rpc_payload, headers=headers)
print(f"[{chain}] JSON-RPC blockNumber:", rpc_resp.json().get("result"))

# 2. Data API: Query freshness (GET /v1/data/{chain}/status/freshness)
data_url = f"https://api.blockvectra.com/v1/data/{chain}/status/freshness"
data_resp = requests.get(data_url, headers={"x-api-key": api_key})
print(f"[{chain}] Data API freshness:", data_resp.json().get("data"))
```


### Приклади відповідей

Успішна відповідь JSON-RPC `eth_blockNumber` (тарифікується за вагою CU цього методу):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x45a27f1"
}
```

Успішна відповідь Data API `GET /v1/data/{chain}/status/freshness` (тарифікується в CU, тарифікуються лише успішні відповіді 2xx):

```json
{
  "data": [
    {
      "dataset": "blocks",
      "category": "raw",
      "max_block_number": 72313256,
      "max_day": null,
      "max_time": "2026-09-28T03:41:07Z",
      "seconds_behind": 0,
      "blocks_behind": null,
      "days_behind": null,
      "checked_at": "2026-09-28T03:41:10Z"
    },
    {
      "dataset": "traces",
      "category": "raw",
      "max_block_number": 72313256,
      "max_day": null,
      "max_time": "2026-09-28T03:41:07Z",
      "seconds_behind": 0,
      "blocks_behind": null,
      "days_behind": null,
      "coverage_from_block": 72050949,
      "coverage_to_block": 72313256,
      "coverage_complete": true,
      "checked_at": "2026-09-28T03:41:10Z"
    },
    {
      "dataset": "dex_prices",
      "category": "derived",
      "max_block_number": null,
      "max_day": "2026-09-27",
      "max_time": "2026-09-27T00:00:00Z",
      "seconds_behind": 99667,
      "blocks_behind": null,
      "days_behind": 1,
      "checked_at": "2026-09-28T03:41:10Z"
    }
  ],
  "meta": {
    "chain": "robinhood_mainnet",
    "chain_slug": "ROBINHOOD_MAINNET",
    "chain_external_id": "eip155:4663",
    "as_of_block": 72313256,
    "safe_block": 72313100,
    "finalized_block": 72313000,
    "coverage": "full",
    "refreshed_at": "2026-09-28T03:41:10Z"
  }
}
```

## Наступні кроки

* [Перегляньте каталог датасетів](https://blockvectra.com/en/data/), щоб побачити всі набори даних, які індексує BlockVectra.
* [Ознайомтеся з безкоштовним планом і тарифами](https://blockvectra.com/en/pricing/#free), щоб дізнатися, що включено у ваш акаунт.
* [Увійдіть до консолі](https://console.blockvectra.com/login/?next=%2Fkeys%2F), щоб створити API key.
