# Una API key, muchas cadenas: adaptar un ejemplo a otra cadena

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

## 1. Una API key para todas las cadenas compatibles

La misma API key funciona en todas las cadenas compatibles con JSON-RPC, y con la Data API en las cadenas donde está disponible. Las API keys pertenecen a tu cuenta y no están vinculadas a una cadena específica; no necesitas generar API keys distintas para cada red.

Los créditos y los límites de frecuencia se comparten entre todas las redes y entre la API JSON-RPC y la Data API; no se dividen por red. Consulta las reglas de facturación detalladas en la [página de precios](https://blockvectra.com/es/pricing/).

* **Saldo compartido**: Las recargas de pago y los créditos gratuitos se pueden usar en todas las cadenas. Las llamadas en cualquier cadena consumen el mismo saldo de la cuenta.
* **Límites de frecuencia compartidos**: Las tasas de reposición y las capacidades de ráfaga en Compute Units (CU) se aplican a todas las cadenas para una API key determinada. Los límites de llamadas por segundo del Plan gratuito se comparten entre todas las cadenas compatibles, en lugar de dividirse por cadena.
* **Paso a capacidad de pago**: Tras una recarga, el límite de llamadas por segundo del Plan gratuito deja de aplicarse; cada API key sigue sujeta a los límites de frecuencia y ráfaga en CU, tal como se describe en la [documentación de JSON-RPC](https://docs.blockvectra.com/es/api/json-rpc/#method-policy).

## 2. Estructura de las URL y parámetro `{chain}`

Cada solicitud dirigida a una cadena especifica su red de destino en la ruta de la URL mediante `{chain}`. El parámetro `{chain}` es el identificador slug de la cadena en minúsculas (por ejemplo, `robinhood_mainnet`).

| Servicio                 | Autenticación                          | Plantilla de URL             | Descripción                                                                   |
| ------------------------ | -------------------------------------- | ---------------------------- | ----------------------------------------------------------------------------- |
| JSON-RPC                 | API key en la ruta de la URL           | `POST /v1/{chain}/{api_key}` | La forma más sencilla, adecuada para curl y clientes HTTP                     |
| JSON-RPC                 | API key en la cabecera de la solicitud | `POST /v1/{chain}`           | Envía la API key mediante la cabecera de solicitud `x-api-key: {api_key}`     |
| Data API                 | Rutas REST                             | `GET /v1/data/{chain}/…`     | Envía la API key mediante la cabecera de solicitud `x-api-key: {api_key}`     |
| Lista pública de cadenas | Sin autenticación                      | `GET /v1/chains`             | Lista pública de cadenas y datos estáticos (sin facturación)                  |
| Estado público           | Sin autenticación                      | `GET /v1/status`             | Estado actual del servicio y últimos bloques de las cadenas (sin facturación) |

`GET /v1/chains` indica una bandera `jsonrpc` y otra `data` para cada cadena. Usa las URL de JSON-RPC cuando la cadena ofrezca JSON-RPC, y `GET /v1/data/{chain}/…` cuando su bandera `data` sea `true` (la Data API solo sirve esas cadenas).

> **Consejo**: Al enviar tu API key mediante cabeceras de solicitud, haz que la URL termine con el nombre de la cadena, **sin** barra final. JSON-RPC se ofrece exclusivamente en `/v1/{chain}` y `/v1/{chain}/{api_key}`. Las solicitudes con barra final (como `/v1/{chain}/`) o sin el segmento de cadena devuelven HTTP 404 con el cuerpo vacío. Las solicitudes a un `{chain}` desconocido devuelven HTTP 404 con `error.data.reason: "unknown_chain"` (sin facturación).

## 3. Descubrimiento de cadenas y capacidades mediante código

Las cadenas compatibles y sus capacidades se publican dinámicamente. No fijes una lista estática de cadenas en tu aplicación. Descubre las redes disponibles y sus capacidades en tiempo de ejecución:

### Descubre datos estáticos con `GET /v1/chains`

Este endpoint público no requiere autenticación ni se factura, y devuelve todas las cadenas disponibles públicamente:

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

Ejemplo de respuesta:

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

Referencia de campos:

* `chain`: Identificador slug de la cadena (se usa como `{chain}` en las URL)
* `name`: Nombre legible para mostrar
* `chain_id`: Chain ID EIP-155 (entero decimal)
* `jsonrpc`: Indica si JSON-RPC está habilitado
* `data`: Indica si la Data API está habilitada
* `methods`: Política de métodos JSON-RPC de la cadena, con `allow` (métodos permitidos) y `deny` (métodos denegados explícitamente)
* `max_logs_block_range`: Rango máximo de bloques permitido en una sola solicitud `eth_getLogs`
* `state_window_blocks`: Tamaño de la ventana de estado histórico en bloques; `null` cuando no hay restricciones

### Comprueba el estado operativo con `GET /v1/status`

Este endpoint público no requiere autenticación ni se factura, y devuelve información sobre la disponibilidad del servicio y los últimos bloques de las cadenas:

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

Ejemplo de respuesta:

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

Referencia de campos:

* `gateway.status`: Estado del servicio (`ok` o `degraded`)
* `chains[].data_features`: Capacidades que ofrece la Data API para esta cadena
* `chains[].status`: Estado operativo del nodo (`ok` o `unavailable`)
* `chains[].head`: Último bloque (`block`, `time`, `lag_seconds`)

## 4. Diferencias entre cadenas que debes tener en cuenta

Al cambiar de cadena, revisa los campos de `GET /v1/chains`:

1. **Permisos y política de métodos (`methods.allow` / `methods.deny`)**: Los métodos JSON-RPC disponibles varían según la red y su política de métodos. Solicitar un método no permitido devuelve HTTP 200 con el código de error JSON-RPC `-32601` (`method not available`, sin facturación).
2. **Rango de bloques para logs (`max_logs_block_range`)**: Los rangos máximos de bloques de las consultas `eth_getLogs` varían por cadena. Superar el límite de la cadena devuelve HTTP 200 con el código de error JSON-RPC `-32602` (`eth_getLogs block range too large`, sin facturación).
3. **Ventana de conservación del estado (`state_window_blocks`)**: Las cadenas con historial completo devuelven `null`. En las cadenas que podan el estado, las consultas de estado histórico fuera de la ventana devuelven HTTP 200 con el código de error JSON-RPC `-32011` (`historical state is not available beyond the most recent <N> blocks`, sin facturación).
4. **Funciones y cobertura de la Data API (`data` / `data_features`)**: Las cadenas que ofrecen un conjunto de datos aparecen en la página de [cadenas compatibles](https://docs.blockvectra.com/es/chains/). Consultar un conjunto de datos que una cadena no admite, o un bloque anterior a su cobertura indexada, devuelve HTTP `422` (`error.code` `no_coverage`, sin facturación). Si el servicio no está disponible temporalmente —por ejemplo, cuando una cadena está ocupada—, las solicitudes devuelven HTTP `503` con una cabecera `Retry-After` (sin facturación).

## 5. Ejemplos de código

Plantilla inicial completa: [blockvectra/multichain-viem](https://github.com/blockvectra/multichain-viem)

El mismo código funciona en distintas cadenas actualizando la variable de cadena (o leyéndola de `GET /v1/chains`), y consulta `eth_blockNumber` mediante JSON-RPC y la actualización del conjunto de datos mediante la 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"))
```


### Ejemplos de respuestas

Respuesta correcta de JSON-RPC `eth_blockNumber` (facturada según el peso en CU del método):

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

Respuesta correcta de la Data API `GET /v1/data/{chain}/status/freshness` (facturada en CU; solo se facturan las respuestas correctas 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"
  }
}
```

## Próximos pasos

* [Explora el directorio de conjuntos de datos](https://blockvectra.com/es/data/) para ver todos los conjuntos de datos que indexa BlockVectra.
* [Consulta el Plan gratuito y los precios](https://blockvectra.com/es/pricing/#free) para comprobar qué incluye tu cuenta.
* [Inicia sesión en la consola](https://console.blockvectra.com/login/?next=%2Fkeys%2F) para crear una API key.
