# Satu API key untuk banyak chain: beralih ke chain lain dalam contoh kode

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

## 1. Satu API key untuk semua chain yang didukung

API key yang sama berlaku di semua chain yang didukung untuk JSON-RPC, serta untuk Data API di chain yang menyediakannya. API key dimiliki oleh akun Anda dan tidak terikat pada chain tertentu; Anda tidak perlu membuat API key terpisah untuk setiap jaringan.

Kredit dan batas laju digunakan bersama di semua jaringan serta antara JSON-RPC API dan Data API; keduanya tidak dibagi per jaringan. Untuk aturan penagihan terperinci, lihat [halaman Harga](https://blockvectra.com/id/pricing/).

* **Saldo bersama**: Top up berbayar dan kredit gratis berlaku di semua chain. Panggilan pada chain mana pun menggunakan saldo akun yang sama.
* **Batas laju bersama**: Laju pengisian ulang Compute Unit (CU) dan kapasitas burst berlaku di semua chain untuk API key tertentu. Batas panggilan per detik paket gratis digunakan bersama di semua chain yang didukung, bukan dibagi per chain.
* **Peningkatan setelah top up**: Setelah top up, Anda tidak lagi dibatasi oleh batas panggilan per detik paket gratis; setiap API key tetap tunduk pada batas laju CU dan burst, sebagaimana dijelaskan dalam [dokumentasi JSON-RPC](https://docs.blockvectra.com/id/api/json-rpc/#method-policy).

## 2. Struktur URL dan parameter `{chain}`

Setiap permintaan yang tercakup dalam suatu chain menentukan jaringan tujuannya pada jalur URL menggunakan `{chain}`. Parameter `{chain}` adalah slug pengenal chain dalam huruf kecil (misalnya `robinhood_mainnet`).

| Layanan             | Autentikasi                     | Templat URL                  | Keterangan                                                     |
| ------------------- | ------------------------------- | ---------------------------- | -------------------------------------------------------------- |
| JSON-RPC            | API key dalam jalur URL         | `POST /v1/{chain}/{api_key}` | Bentuk paling sederhana, cocok untuk curl dan klien HTTP       |
| JSON-RPC            | API key dalam header permintaan | `POST /v1/{chain}`           | Kirim API key melalui header permintaan `x-api-key: {api_key}` |
| Data API            | Rute REST                       | `GET /v1/data/{chain}/…`     | Kirim API key melalui header permintaan `x-api-key: {api_key}` |
| Daftar chain publik | Tanpa autentikasi               | `GET /v1/chains`             | Daftar publik chain dan fakta statis (tidak ditagih)           |
| Status publik       | Tanpa autentikasi               | `GET /v1/status`             | Status layanan dan head chain saat ini (tidak ditagih)         |

`GET /v1/chains` melaporkan flag `jsonrpc` dan `data` untuk setiap chain. Gunakan URL JSON-RPC untuk chain yang menyediakan JSON-RPC, dan `GET /v1/data/{chain}/…` ketika flag `data` bernilai `true` (Data API hanya melayani chain tersebut).

> **Tips**: Saat mengirim API key melalui header permintaan, buat URL berakhir dengan nama chain, **tanpa** garis miring di akhir. JSON-RPC hanya dilayani di `/v1/{chain}` dan `/v1/{chain}/{api_key}`. Permintaan dengan garis miring di akhir (seperti `/v1/{chain}/`) atau tanpa segmen chain mengembalikan HTTP 404 dengan body kosong. Permintaan ke `{chain}` yang tidak dikenal mengembalikan HTTP 404 dengan `error.data.reason: "unknown_chain"` (tidak ditagih).

## 3. Penemuan chain dan kemampuannya secara terprogram

Chain yang didukung beserta kemampuannya disediakan secara dinamis. Jangan menanamkan daftar chain statis dalam aplikasi Anda. Temukan jaringan yang tersedia dan kemampuannya saat runtime:

### Temukan fakta statis melalui `GET /v1/chains`

Endpoint publik ini tidak memerlukan autentikasi dan tidak ditagih, serta mengembalikan semua chain yang tersedia untuk publik:

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

Contoh respons:

```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
    }
  ]
}
```

Referensi bidang:

* `chain`: Slug pengenal chain (digunakan untuk `{chain}` dalam URL)
* `name`: Nama tampilan yang dapat dibaca manusia
* `chain_id`: Chain ID EIP-155 (bilangan bulat desimal)
* `jsonrpc`: Apakah JSON-RPC diaktifkan
* `data`: Apakah Data API diaktifkan
* `methods`: Kebijakan metode JSON-RPC untuk chain, termasuk `allow` (metode yang diizinkan) dan `deny` (metode yang secara eksplisit ditolak)
* `max_logs_block_range`: Rentang blok maksimum yang diizinkan dalam satu permintaan `eth_getLogs`
* `state_window_blocks`: Ukuran jendela state historis dalam blok; `null` jika tidak dibatasi

### Periksa kesehatan operasional melalui `GET /v1/status`

Endpoint publik ini tidak memerlukan autentikasi dan tidak ditagih, serta mengembalikan kesiapan layanan dan informasi head chain:

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

Contoh respons:

```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
      }
    }
  ]
}
```

Referensi bidang:

* `gateway.status`: Status layanan (`ok` atau `degraded`)
* `chains[].data_features`: Kemampuan yang disediakan Data API untuk chain ini
* `chains[].status`: Status operasional node (`ok` atau `unavailable`)
* `chains[].head`: Head blok terbaru (`block`, `time`, `lag_seconds`)

## 4. Perbedaan antar-chain yang perlu diperhatikan

Saat beralih antar-chain, tinjau bidang yang disediakan dalam `GET /v1/chains`:

1. **Izin dan kebijakan metode (`methods.allow` / `methods.deny`)**: Metode JSON-RPC yang tersedia berbeda menurut jaringan sesuai kebijakan metodenya. Permintaan metode yang tidak diizinkan mengembalikan HTTP 200 dengan kode error JSON-RPC `-32601` (`method not available`, tidak ditagih).
2. **Rentang blok log (`max_logs_block_range`)**: Rentang blok maksimum untuk kueri `eth_getLogs` berbeda menurut chain. Melampaui batas chain mengembalikan HTTP 200 dengan kode error JSON-RPC `-32602` (`eth_getLogs block range too large`, tidak ditagih).
3. **Jendela retensi state (`state_window_blocks`)**: Chain dengan riwayat lengkap mengembalikan `null`. Pada chain yang memangkas state, kueri state historis di luar jendela mengembalikan HTTP 200 dengan kode error JSON-RPC `-32011` (`historical state is not available beyond the most recent <N> blocks`, tidak ditagih).
4. **Fitur dan cakupan Data API (`data` / `data_features`)**: Chain yang menyediakan suatu kumpulan data tercantum di halaman [Chain yang Didukung](https://docs.blockvectra.com/id/chains/). Kueri kumpulan data yang tidak didukung oleh suatu chain, atau blok sebelum cakupan indeksnya, mengembalikan HTTP `422` (`error.code` `no_coverage`, tidak ditagih). Ketika layanan tidak tersedia sementara — misalnya saat chain sibuk — permintaan mengembalikan HTTP `503` dengan header `Retry-After` (tidak ditagih).

## 5. Contoh kode

Templat awal lengkap: [blockvectra/multichain-viem](https://github.com/blockvectra/multichain-viem)

Kode yang persis sama berjalan di berbagai chain dengan memperbarui variabel chain (atau membacanya dari `GET /v1/chains`), lalu mengueri `eth_blockNumber` melalui JSON-RPC dan kesegaran kumpulan data melalui 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"))
```


### Contoh respons

Respons berhasil JSON-RPC `eth_blockNumber` (ditagih sesuai bobot CU metode):

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

Respons berhasil Data API `GET /v1/data/{chain}/status/freshness` (ditagih dalam CU, hanya respons berhasil 2xx yang ditagih):

```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"
  }
}
```

## Langkah berikutnya

* [Jelajahi direktori kumpulan data](https://blockvectra.com/id/data/) untuk melihat semua kumpulan data yang diindeks BlockVectra.
* [Lihat paket gratis dan harga](https://blockvectra.com/id/pricing/#free) untuk memeriksa apa saja yang tercakup dalam akun Anda.
* [Masuk ke konsol](https://console.blockvectra.com/login/?next=%2Fkeys%2F) untuk membuat API key.
