# 1 つのキーで複数チェーン：サンプルコードを別のチェーンに切り替える

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

## 1. One key across all supported chains

同じ API key が、JSON-RPC についてはサポートされているすべてのチェーンで機能し、Data API については利用可能なチェーンで機能します。キーはアカウントに属しており、特定のチェーンにバインドされていません。ネットワークごとに個別の API key を生成する必要はありません。

クレジットとレート制限はすべてのネットワーク間、および JSON-RPC API と Data API 間で共有され、ネットワークごとに分割されることはありません。詳細な課金ルールについては、[料金ページ](https://blockvectra.com/en/pricing/)を参照してください。

* **合算される残高**：有料チャージと無料クレジットはすべてのチェーンに適用されます。どのチェーンでの呼び出しも同じアカウント残高から差し引かれます。
* **合算されるレート制限**：特定のキーに対して、Compute Unit（CU）の補充レートとバースト容量がすべてのチェーンに適用されます。無料プランの 1 秒あたりのコール数制限は、チェーンごとに分割されるのではなく、サポートされているすべてのチェーンで合算されます。
* **アップグレードパス**：チャージ後は、無料プランの 1 秒あたりのコール数制限に縛られなくなります。[JSON-RPC ドキュメント](https://docs.blockvectra.com/en/api/json-rpc/#method-policy)に記載されているように、各キーは引き続き CU レートおよびバースト制限の対象となります。

## 2. URL structure and the `{chain}` parameter

チェーンを対象とするすべてのリクエストは、URL パス内で `{chain}` を使用して対象ネットワークを指定します。`{chain}` パラメータは、チェーンの小文字スラッグ識別子です（例：`robinhood_mainnet`）。

| Service   | Authentication | URL template                 | Description                              |
| --------- | -------------- | ---------------------------- | ---------------------------------------- |
| 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` フラグを報告します。JSON-RPC を提供しているチェーンには JSON-RPC URL を使用し、`data` フラグが `true` のチェーンには `GET /v1/data/{chain}/…` を使用します（Data API はこれらのチェーンのみを提供します）。

> **Tip**: リクエストヘッダー経由でキーを渡す場合は、末尾にスラッシュを**付けずに**、チェーン名で終わるように URL をフォーマットしてください。JSON-RPC は `/v1/{chain}` および `/v1/{chain}/{api_key}` でのみ提供されます。末尾にスラッシュがあるリクエスト（`/v1/{chain}/` など）やチェーンセグメントが不足しているリクエストは、空のボディで HTTP 404 を返します。不明な `{chain}` へのリクエストは、`error.data.reason: "unknown_chain"` 付きの HTTP 404 を返します（課金対象外）。

## 3. Programmatic chain discovery and capabilities

サポートされているチェーンとその機能は動的に提供されます。アプリケーションにチェーンの静的リストをハードコードしないでください。代わりに、実行時に入手可能なネットワークとその機能を検出してください：

### Discover static facts via `GET /v1/chains`

この公開エンドポイントは未認証で課金されず、公開されているすべてのチェーンを返します：

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

Example response:

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

Field reference:

* `chain`: チェーン識別子スラッグ（URL 内の `{chain}` に使用）
* `name`: 可読な表示名
* `chain_id`: EIP-155 チェーン ID（10 進数の整数）
* `jsonrpc`: JSON-RPC が有効かどうか
* `data`: Data API が有効かどうか
* `methods`: `allow`（許可されたメソッド）と `deny`（明示的に拒否されたメソッド）を含む、チェーンの JSON-RPC メソッドポリシー
* `max_logs_block_range`: 単一の `eth_getLogs` リクエストで許可される最大ブロック範囲
* `state_window_blocks`: ブロック単位の過去の状態ウィンドウサイズ（制限がない場合は `null`）

### Check operational health via `GET /v1/status`

この公開エンドポイントは未認証で課金されず、サービスの準備状況とチェーンヘッド情報を返します：

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

Example response:

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

Field reference:

* `gateway.status`: サービスステータス（`ok` または `degraded`）
* `chains[].data_features`: このチェーンに対して Data API が提供する機能
* `chains[].status`: ノードの稼働ステータス（`ok` または `unavailable`）
* `chains[].head`: 最新のブロックヘッド（`block`、`time`、`lag_seconds`）

## 4. Per-chain differences to keep in mind

チェーンを切り替える際は、`GET /v1/chains` で提供されるフィールドを確認してください：

1. **Method allowance and policy (`methods.allow` / `methods.deny`)**: 利用可能な JSON-RPC メソッドは、メソッドポリシーに応じてネットワークごとに異なります。許可されていないメソッドをリクエストすると、JSON-RPC エラーコード `-32601`（`method not available`、課金対象外）を含む HTTP 200 が返されます。
2. **Log block range (`max_logs_block_range`)**: `eth_getLogs` クエリの最大ブロック範囲はチェーンによって異なります。チェーンの上限を超えると、JSON-RPC エラーコード `-32602`（`eth_getLogs block range too large`、課金対象外）を含む HTTP 200 が返されます。
3. **State retention window (`state_window_blocks`)**: 全履歴を保持するチェーンは `null` を返します。状態プルーニングを行うチェーンでは、ウィンドウ外の過去の状態クエリに対して JSON-RPC エラーコード `-32011`（`historical state is not available beyond the most recent <N> blocks`、課金対象外）を含む HTTP 200 が返されます。
4. **Data API features and coverage (`data` / `data_features`)**: データセットを提供するチェーンは[対応チェーン](https://docs.blockvectra.com/en/chains/)ページに記載されています。チェーンが対応していないデータセットや、インデックス作成の対象範囲前のブロックを照会すると、HTTP `422`（`error.code` `no_coverage`、課金対象外）が返されます。チェーンがビジー状態など、サービスが一時的に利用できない場合、リクエストは `Retry-After` ヘッダー付きの HTTP `503` を返します（課金対象外）。

## 5. Code examples

完全なスターターテンプレート：[blockvectra/multichain-viem](https://github.com/blockvectra/multichain-viem)

チェーン変数を更新する（または `GET /v1/chains` から読み取る）ことで、まったく同じコードが異なるチェーン間で実行され、JSON-RPC 経由で `eth_blockNumber` を、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"))
```


### Example responses

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

## Next steps

* [データセットディレクトリを見る](https://blockvectra.com/en/data/)と、BlockVectra がインデックスしているすべてのデータセットを確認できます。
* [無料プランと料金を見る](https://blockvectra.com/en/pricing/#free)と、アカウントに含まれる内容を確認できます。
* [コンソールにログイン](https://console.blockvectra.com/login/?next=%2Fkeys%2F)して、API key を作成してください。
