# Suscripciones WebSocket

> Source: https://docs.blockvectra.com/es/guides/websocket-subscriptions/

BlockVectra ofrece conexiones WebSocket seguras (`wss://`) para recibir suscripciones a eventos de Ethereum en tiempo real junto con solicitudes JSON-RPC estándar.

## Elegir WebSocket, Webhook o sondeo

Usa WebSocket para recibir `newHeads` y `logs` filtrados en directo cuando tu aplicación pueda mantener una conexión. Usa la [Blockchain Webhook API](https://docs.blockvectra.com/es/guides/webhook-push/) para recibir la actividad de las billeteras observadas en un endpoint HTTPS, con [verificación de firmas sobre el cuerpo sin procesar](https://docs.blockvectra.com/es/guides/webhook-push/#verify-signatures), reintentos y reenvío de coincidencias conservadas. Usa el [sondeo HTTP](https://docs.blockvectra.com/es/guides/stablecoin-payments/) para supervisar pagos ERC-20 periódicamente y recuperar logs históricos. La guía de stablecoins también muestra un [receptor Webhook de USDT / USDC](https://docs.blockvectra.com/es/guides/stablecoin-payments/#receive-payments-with-webhooks). Para comparar la arquitectura en cuanto a cadenas compatibles, requisitos del receptor y ventajas e inconvenientes de recuperación para desarrolladores y agentes de IA, consulta la [guía para elegir Webhooks, WebSocket o sondeo RPC](https://docs.blockvectra.com/es/guides/webhook-vs-websocket/).

La compatibilidad con WebSocket se indica en `ws` y `subscriptions` de `GET /v1/chains`; la compatibilidad con Push se indica en la lista autenticada `GET /v1/push/chains`. Una cadena sin WebSocket puede seguir usando Webhooks de direcciones si aparece en esa lista.

Las desconexiones de WebSocket requieren volver a suscribirse y recuperar los datos faltantes; no emiten los eventos de control Push `subscription.gap` ni `chain.reorg`. En los Webhooks, un intervalo sin datos requiere un escaneo de rango; un aviso de reorganización requiere marcar o descartar los eventos sustituidos antes de conservar los eventos canónicos que se vuelven a entregar automáticamente. El [reenvío de Push](https://docs.blockvectra.com/es/guides/webhook-push/#delivery-retries-and-replay) vuelve a enviar las coincidencias conservadas, no los datos anteriores a la incorporación de una dirección o cadena ni los del período en que la suscripción estuvo desconectada. Revisa las [reglas de facturación](https://docs.blockvectra.com/en/guides/billing-rules/) y la [referencia de errores](https://docs.blockvectra.com/es/errors/) al implementar la recuperación.

## Cadenas disponibles

Puedes comprobar si las suscripciones WebSocket están activas en una red leyendo `ws` (booleano) y `subscriptions` (matriz de tipos compatibles) en `GET /v1/chains`.

La siguiente tabla muestra las redes en las que WebSocket está habilitado:

| Cadena | Endpoint WebSocket (clave en la ruta) |
| --- | --- |
| Robinhood Chain | `wss://api.blockvectra.com/v1/robinhood_mainnet/{api_key}` |
| Robinhood Chain Testnet | `wss://api.blockvectra.com/v1/robinhood_testnet/{api_key}` |

## Conexión y autenticación

Los clientes establecen una conexión WebSocket segura con TLS (`wss://`). La API key puede proporcionarse de dos formas:

* **API key en la ruta**: `wss://api.blockvectra.com/v1/{chain}/{api_key}`
* **API key en la cabecera**: `wss://api.blockvectra.com/v1/{chain}` con la cabecera `x-api-key: {api_key}` o `Authorization: Bearer {api_key}` durante la negociación HTTP Upgrade.

Si hay una API key en la ruta, se usa esa API key y se ignoran ambas cabeceras de autenticación. Sin API key en la ruta, un `x-api-key` no vacío tiene prioridad sobre `Authorization: Bearer`. Las API WebSocket del navegador no pueden establecer estas cabeceras; usa la URL con API key en la ruta.

### Comprobaciones de admisión durante la negociación

La negociación puede fallar por:

* **Autenticación**: La ausencia de API key devuelve HTTP 401 ([`missing_api_key`](https://docs.blockvectra.com/es/errors/#missing_api_key)); una API key desconocida, deshabilitada o revocada devuelve HTTP 401 ([`invalid_api_key`](https://docs.blockvectra.com/es/errors/#invalid_api_key)); si la autenticación no está disponible temporalmente, la respuesta es HTTP 503 ([`auth_unavailable`](https://docs.blockvectra.com/es/errors/#auth_unavailable)).
* **Saldo de la cuenta**: Una cuenta con saldo de prepago cero o negativo devuelve HTTP 402 ([`balance_exhausted`](https://docs.blockvectra.com/es/errors/#balance_exhausted)); si no se puede confirmar el estado de facturación, la respuesta es HTTP 503 ([`billing_unavailable`](https://docs.blockvectra.com/es/errors/#billing_unavailable)).
* **Límites de conexión**: Superar el límite por API key (20 conexiones) o por cuenta (50 conexiones) devuelve HTTP 429 ([`ws_connection_limit`](https://docs.blockvectra.com/es/errors/#ws_connection_limit)).
* **Disponibilidad de la cadena**: Solicitar una cadena desconocida o no servida devuelve HTTP 404 ([`unknown_chain`](https://docs.blockvectra.com/es/errors/#unknown_chain)).
* **Capacidad del servidor**: Cuando el servidor está ocupado o sobrecargado, la negociación devuelve HTTP 503 ([`overloaded`](https://docs.blockvectra.com/es/errors/#overloaded)) con una cabecera `Retry-After`.

Una vez conectados, los clientes pueden enviar solicitudes JSON-RPC 2.0 estándar (como `eth_blockNumber` o `eth_call`) y métodos de control de suscripciones como tramas de texto UTF-8.

## Reglas de facturación

* Establecer una conexión, mantener abierta una conexión inactiva y los mensajes de mantenimiento ping/pong no se facturan.
* Las llamadas correctas a `eth_subscribe` y `eth_unsubscribe` se facturan, incluida una cancelación que devuelva `false`; las llamadas fallidas no se facturan. Las llamadas JSON-RPC ordinarias siguen las [reglas de facturación de JSON-RPC](https://docs.blockvectra.com/en/guides/billing-rules/).
* Las notificaciones `newHeads` se contabilizan una vez por hash de bloque y por conexión, independientemente de cuántas suscripciones `newHeads` tenga la conexión.
* Las notificaciones `logs` se contabilizan una vez por suscripción, hash de bloque y fase con logs coincidentes; los bloques sin coincidencias no se facturan. Varios logs coincidentes en el mismo bloque y fase no multiplican el cargo. Las suscripciones independientes se contabilizan por separado, incluso si sus filtros se solapan. Los logs de reorganización (`removed: true`) forman una unidad aparte; un bloque de sustitución a la misma altura tiene otro hash y constituye otra unidad.
* Las notificaciones solo se facturan después de enviarse correctamente al búfer de envío del socket; las notificaciones en cola o descartadas que no se enviaron no se facturan. Las notificaciones encoladas antes de una respuesta `eth_unsubscribe` cuentan si se envían. Los mensajes WebSocket no incluyen cabeceras HTTP de facturación; consulta el uso de la cuenta para conocer las CU medidas.

## Métodos de suscripción

La API implementa la interfaz estándar pub/sub de Ethereum: `eth_subscribe` y `eth_unsubscribe`.

### `newHeads`

Emite un objeto de cabecera de bloque nuevo cada vez que se añade un bloque al extremo de la cadena.

* **Solicitud de suscripción**:
  ```json
  {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
  ```
* **Respuesta de suscripción**: Devuelve un identificador hexadecimal opaco de suscripción:
  ```json
  {"jsonrpc":"2.0","id":1,"result":"0x1"}
  ```
* **Trama de notificación Push**:
  ```json
  {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{"number":"0x1b4","hash":"0x..."}}}
  ```

### `logs`

Emite logs de eventos que coinciden con los criterios de filtro especificados.

* **Requisito del filtro**: Cada filtro de suscripción `logs` **debe** especificar un `address` (una dirección de contrato o una matriz de direcciones) o un `topic0` (la primera posición de tema, no nula). Un filtro que no especifique ninguno (como `{}` o `{"topics":[null,"0x..."]}`) se rechaza con el código de error `-32602` ([`logs_filter_required`](https://docs.blockvectra.com/es/errors/#logs_filter_required)).

* **Límites del filtro**: Como máximo 100 direcciones; como máximo 4 posiciones de temas con hasta 16 hashes candidatos por posición.

* **Capacidad de filtros**: Si los filtros de logs activos alcanzan la capacidad máxima, la suscripción devuelve el código de error `-32022` ([`ws_filter_capacity`](https://docs.blockvectra.com/es/errors/#ws_filter_capacity)).

* **Reorganizaciones de la cadena**: Si se elimina un bloque por una reorganización de la cadena, las notificaciones de los logs eliminados llevan `"removed": true`.

* **Solicitud de suscripción**:
  ```json
  {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}
  ```

### `eth_unsubscribe`

Termina una suscripción activa mediante su identificador.

* **Solicitud de cancelación de suscripción**:
  ```json
  {"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
  ```
* **Respuesta de cancelación de suscripción**:
  ```json
  {"jsonrpc":"2.0","id":3,"result":true}
  ```

## Ejemplos ejecutables

**viem v2 (TypeScript)**

Conéctate con [viem](https://viem.sh) v2 mediante `createPublicClient` y el transporte `webSocket`. Sustituye `{chain}` por el identificador de la cadena de destino y `{api_key}` por tu API key:

```ts
import { createPublicClient, webSocket } from 'viem';

const apiKey = process.env.BLOCKVECTRA_API_KEY || '{api_key}';
const url = `wss://api.blockvectra.com/v1/robinhood_mainnet/${apiKey}`;

const client = createPublicClient({
  transport: webSocket(url),
});

// 1. Subscribe to new block headers (newHeads)
const unwatchBlocks = client.watchBlocks({
  onBlock: (block) => {
    console.log('New block header received:', block.number, block.hash);
  },
  onError: (error) => {
    console.error('watchBlocks error:', error);
  },
});

// 2. Subscribe to contract event logs (filter requires address or topic0)
const unwatchEvents = client.watchEvent({
  address: '0x1234567890123456789012345678901234567890',
  onLogs: (logs) => {
    console.log('Matching logs received:', logs);
  },
  onError: (error) => {
    console.error('watchEvent error:', error);
  },
});
```


  **Command line (websocat / wscat)**

Conéctate con herramientas de línea de comandos como `websocat` o `wscat` y envía tramas JSON-RPC sin procesar:

```bash
# Connect with path-based API key using websocat
websocat "wss://api.blockvectra.com/v1/{chain}/{api_key}"

# Alternatively, pass the key via request header
websocat -H="x-api-key: {api_key}" "wss://api.blockvectra.com/v1/{chain}"

# Or connect using wscat
wscat -c "wss://api.blockvectra.com/v1/{chain}/{api_key}"
```

Envía los comandos de suscripción en la sesión interactiva:

```json
{"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
{"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}
{"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
```


## Códigos de cierre y acciones del cliente

Cuando el servidor termina una sesión WebSocket, envía una trama Close con un código de cierre específico y un motivo breve. La siguiente tabla enumera los códigos de cierre que emite el servidor y las acciones recomendadas:

|         Código de cierre | Cadena de motivo                 | Descripción                                                                                                                                                                                            | Se puede reintentar | Acción del cliente                                                                                                                                                                                                                                                                     |
| -----------------------: | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-----------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [1001](https://docs.blockvectra.com/es/errors/#1001) | `idle`                           | Conexión inactiva sin suscripciones ni mensajes durante 3600 segundos (1 hora)                                                                                                                         |          Sí         | Vuelve a conectarte según sea necesario.                                                                                                                                                                                                                                               |
| [1003](https://docs.blockvectra.com/es/errors/#1003) | `binary frames are not accepted` | Se recibió una trama WebSocket binaria; solo se admiten tramas de texto UTF-8                                                                                                                          |          No         | No vuelvas a conectarte automáticamente. Actualiza el cliente para enviar tramas de texto.                                                                                                                                                                                             |
| [1009](https://docs.blockvectra.com/es/errors/#1009) | `message too large`              | La carga útil entrante superó 1 MiB                                                                                                                                                                    |          No         | No vuelvas a conectarte automáticamente. Divide las solicitudes grandes o reduce el tamaño de la carga útil.                                                                                                                                                                           |
| [1012](https://docs.blockvectra.com/es/errors/#1012) | `service restart`                | El servidor se está reiniciando o la sesión alcanzó su duración máxima (24 horas)                                                                                                                      |          Sí         | Vuelve a conectarte con esperas aleatorias entre reintentos, restablece las suscripciones y recupera los datos faltantes.                                                                                                                                                              |
| [1013](https://docs.blockvectra.com/es/errors/#1013) | `chain unavailable`              | Cadena no disponible                                                                                                                                                                                   |          Sí         | Vuelve a conectarte con espera exponencial y aleatoriedad completa, restablece las suscripciones y recupera los datos faltantes.                                                                                                                                                       |
| [1013](https://docs.blockvectra.com/es/errors/#1013) | `overloaded`                     | Servidor temporalmente sobrecargado                                                                                                                                                                    |          Sí         | Vuelve a conectarte con espera exponencial y aleatoriedad completa, restablece las suscripciones y recupera los datos faltantes.                                                                                                                                                       |
| [4402](https://docs.blockvectra.com/es/errors/#4402) | `insufficient balance`           | Saldo de la cuenta agotado                                                                                                                                                                             |          No         | No vuelvas a conectarte automáticamente. [Recarga tu saldo y después vuelve a conectarte](https://docs.blockvectra.com/en/guides/billing-rules/).                                                                                                                                                                  |
| [4404](https://docs.blockvectra.com/es/errors/#4404) | `invalid api key`                | API key desconocida, deshabilitada o revocada                                                                                                                                                          |          No         | No vuelvas a conectarte automáticamente. Verifica o rota la API key en la consola antes de volver a conectarte.                                                                                                                                                                        |
| [4408](https://docs.blockvectra.com/es/errors/#4408) | `slow consumer`                  | El servidor cierra una sesión cuya cola de notificaciones Push supera 512 KiB y descarta las notificaciones pendientes; los clientes pueden no recibir una trama de cierre (el navegador informa 1006) |          Sí         | Trata las desconexiones inesperadas (sin trama de cierre recibida, el navegador informa 1006) como 4408: vuelve a conectarte con esperas entre reintentos, restablece las suscripciones y recupera los datos descartados con `eth_getLogs`; reduce las suscripciones o lee más rápido. |
| [4429](https://docs.blockvectra.com/es/errors/#4429) | `push rate exceeded`             | La frecuencia de notificaciones superó 1,000 notificaciones Push/segundo                                                                                                                               |          Sí         | Reduce las suscripciones o restringe los filtros; vuelve a conectarte con esperas entre reintentos, suscríbete de nuevo y recupera los datos faltantes.                                                                                                                                |
| [4503](https://docs.blockvectra.com/es/errors/#4503) | `billing unavailable`            | Facturación temporalmente no disponible                                                                                                                                                                |          Sí         | Estado transitorio; vuelve a conectarte con espera exponencial y aleatoriedad completa.                                                                                                                                                                                                |

## Reconexión y espera exponencial

Para evitar avalanchas de reconexiones sincronizadas cuando se interrumpen las conexiones, los clientes deben implementar esperas exponenciales con aleatoriedad completa:

* **Fórmula de espera**: Antes del intento de reconexión n-ésimo (n = 0, 1, 2, ...), espera una duración elegida uniformemente al azar:
  ```
  delay = random(0, min(20s, 0.5s * 2^n))
  ```
* **Reinicia el contador**: Reinicia el contador de reintentos n a 0 solo después de mantener una conexión estable e ininterrumpida durante al menos `60 seconds`.
* **Código de cierre 1012**: Introduce una espera inicial aleatoria antes del primer intento de reconexión para evitar picos de reconexiones sincronizadas.
* **Códigos no reintentables**: No vuelvas a conectarte automáticamente ante [4402](https://docs.blockvectra.com/es/errors/#4402), [4404](https://docs.blockvectra.com/es/errors/#4404), [1003](https://docs.blockvectra.com/es/errors/#1003) ni [1009](https://docs.blockvectra.com/es/errors/#1009).

### Recuperación de datos faltantes tras la reconexión

Las suscripciones WebSocket no se conservan entre conexiones; el servidor no retiene las notificaciones emitidas durante una desconexión. Tras volver a conectarse, los clientes deben ejecutar una estrategia para ponerse al día:

1. **Recupera logs con `eth_getLogs`**:
   * Conserva el número de bloque más alto procesado correctamente (`last_processed_block`).
   * Llama inmediatamente a `eth_subscribe("logs", ...)` al volver a conectarte para capturar los eventos en directo.
   * Consulta los bloques faltantes mediante `eth_getLogs` con `fromBlock: last_processed_block + 1` y `toBlock: "latest"` (o el primer bloque recibido del flujo en directo).
   * Si el intervalo de desconexión supera `max_logs_block_range` de la red (de `GET /v1/chains`), divide las consultas en segmentos que no superen ese límite.
   * Elimina los logs duplicados entre las consultas usando la tupla única `(blockHash, transactionHash, logIndex)`.
2. **Recupera cabeceras de bloque con `eth_getBlockByNumber`**:
   * Registra el último número y hash de bloque recibidos antes de la desconexión.
   * Vuelve a suscribirte a `newHeads`.
   * Consulta `eth_getBlockByNumber("latest", false)` y obtén secuencialmente los bloques intermedios faltantes. Verifica la continuidad de la cadena con `parentHash` para detectar reorganizaciones.

## Límites

| Límite                                          | Valor                                                                      | Resultado al superarlo                                              |
| ----------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| Suscripciones por conexión WebSocket            | 100                                                                        | `-32022` [`subscription_limit`](https://docs.blockvectra.com/es/errors/#subscription_limit)     |
| Suscripciones `newHeads` por conexión WebSocket | 4                                                                          | `-32022` [`subscription_limit`](https://docs.blockvectra.com/es/errors/#subscription_limit)     |
| Requisitos del filtro de suscripción `logs`     | Debe especificar un `address` o un `topic0` (primera posición de `topics`) | `-32602` [`logs_filter_required`](https://docs.blockvectra.com/es/errors/#logs_filter_required) |

## 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.
