> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gelato.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Track Requests via WebSocket

> Get real-time transaction status updates using WebSocket connections

Track your Gelato transactions in real-time using WebSocket connections instead of polling. WebSockets provide instant status updates as your transactions move through the lifecycle.

## Using the SDK

WebSockets are enabled by default in the `@gelatocloud/gasless` SDK. Methods automatically race WebSocket notifications against HTTP polling for the fastest result.

To disable WebSockets:

```typescript theme={null}
const relayer = createGelatoEvmRelayerClient({
  apiKey: process.env.GELATO_API_KEY,
  ws: { disable: true }
});
```

### Subscribe to a Single Transaction

```typescript theme={null}
const id = await relayer.sendTransaction({
  chainId: baseSepolia.id,
  to: '0xTargetContract...',
  data: '0xCalldata...',
});

const subscription = await relayer.ws.subscribe({ id });

subscription.on('success', (data) => {
  console.log(`Included in block ${data.receipt.blockNumber}`);
});

subscription.on('reverted', (data) => {
  console.log(`Reverted: ${data.receipt.blockNumber}`);
});

// Cleanup when done
await relayer.ws.unsubscribe(subscription.subscriptionId);
relayer.ws.disconnect();
```

### Subscribe to All Transactions

```typescript theme={null}
const subscription = await relayer.ws.subscribe();

subscription.on('submitted', (data) => console.log(`${data.id} submitted`));
subscription.on('success', (data) => console.log(`${data.id} success`));
subscription.on('rejected', (data) => console.log(`${data.id} rejected`));
```

### Unsubscribe

```typescript theme={null}
await relayer.ws.unsubscribe(subscription.subscriptionId);
relayer.ws.disconnect();
```

## WebSocket API

Real-time updates for transactions via WebSocket connections.

### Authentication

All WebSocket endpoints require API key authentication. Pass key in `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

If you are on a browser you can also pass the API key as a query parameter in the URL: `wss://api.gelato.cloud/ws?apiKey=YOUR_API_KEY`

### Simple Transaction Subscription

Auto-subscribes to a specific transaction. Uses JSON-RPC 2.0 format for all messages.

**URL:** `wss://api.gelato.cloud/ws/transactions/:id`

```javascript theme={null}
const ws = new WebSocket('wss://api.gelato.cloud/ws/transactions/abc123', {
  headers: { Authorization: 'Bearer YOUR_API_KEY' }
});

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg);
  // Connection: { jsonrpc: '2.0', method: 'connected', params: { clientId: '...', subscriptionId: '...', entityId: 'abc123', timestamp: 1234567890 } }
  // Event: { jsonrpc: '2.0', method: 'subscription', params: { subscription: '...', result: { event: 'transaction.pending', data: { id: 'abc123', status: 100, chainId: '1', createdAt: 1234567890 } } } }
  // Event: { jsonrpc: '2.0', method: 'subscription', params: { subscription: '...', result: { event: 'transaction.success', data: { id: 'abc123', status: 200, chainId: '1', receipt: {...}, createdAt: 1234567890 } } } }
};
```

### Advanced Subscription (JSON-RPC)

Flexible filtering: multiple transactions, chains, event types. Subscribe/unsubscribe dynamically.

**URL:** `wss://api.gelato.cloud/ws`

**Protocol:** JSON-RPC 2.0

**Method:** `subscribe`

**Params:**

* `transactionId` (string, optional): Specific transaction ID (max 200 chars)
* `chainIds` (string\[], optional): Chain IDs to filter (max 50)
* `eventTypes` (string\[], optional): Event type patterns (max 20)

At least one filter required.

**Event type patterns:** See [Events & Status Codes](#events--status-codes) for the full list. Use `transaction.*` for all events or `*` for everything.

```javascript theme={null}
// Subscribe to specific transactions
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  method: 'subscribe',
  params: [{
    transactionId: 'abc123'
  }],
  id: 1
}));

// Subscribe to all events on Arbitrum
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  method: 'subscribe',
  params: [{
    eventTypes: ['transaction.*'],
    chainIds: ['42161']
  }],
  id: 2
}));
```

### Unsubscribe

Works on both `/ws/transactions/:id` and `/ws` connections.

**Method:** `unsubscribe`

**Params:** `[subscriptionId]`

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  method: 'unsubscribe',
  params: ['sub-uuid-from-subscribe'],
  id: msgId++
}));

// Response: { jsonrpc: '2.0', result: true, id: 2 }
```

### Message Types

**Connection Confirmation (JSON-RPC)**

Sent when connection established on `/ws`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "connected",
  "params": {
    "clientId": "uuid",
    "timestamp": 1234567890
  }
}
```

**Connection Confirmation (Simple Endpoints)**

Sent when connection established on `/ws/transactions/:id`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "connected",
  "params": {
    "clientId": "uuid",
    "subscriptionId": "sub-uuid",
    "entityId": "abc123",
    "timestamp": 1234567890
  }
}
```

**Error Response**

```json theme={null}
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": { "issues": ["..."] }
  },
  "id": 1
}
```

**Ping/Pong**

Keep connection alive by sending ping:

```javascript theme={null}
// Send
ws.send(JSON.stringify({ type: 'ping' }));

// Receive
// { type: 'pong', timestamp: 1234567890 }
```

### Connection Health

**Server Heartbeat**

The server sends native WebSocket ping frames every 30 seconds. Clients should respond with pong frames (most WebSocket libraries handle this automatically).

If the server doesn't receive a pong within 60 seconds, it will close the connection with code `1000`.

<Note>
  This is separate from the JSON `{type: "ping"}` message, which is also supported for backward compatibility.
</Note>

**WebSocket Close Codes**

When the server closes a connection, it sends a close frame with a status code and optional reason:

| Code | Meaning          | Description                                                 |
| ---- | ---------------- | ----------------------------------------------------------- |
| 1000 | Normal Closure   | Clean disconnect (unsubscribe all, timeout, client request) |
| 1001 | Going Away       | Server is shutting down                                     |
| 1008 | Policy Violation | Authentication failure or rate limit exceeded               |
| 1011 | Internal Error   | Unexpected server error                                     |
| 4000 | Invalid Filter   | Bad subscription parameters                                 |
| 4001 | Limit Exceeded   | Too many subscriptions (100/connection or 1000/API key)     |
| 4002 | Unauthorized     | API key invalid, expired, or missing                        |
| 4003 | Forbidden        | Testnet key used on production endpoint                     |

```javascript theme={null}
ws.onclose = (event) => {
  console.log(`Closed: ${event.code} - ${event.reason}`);

  if (event.code === 4001) {
    // Rate limit - reduce subscriptions
  } else if (event.code === 4002) {
    // Auth failure - refresh API key
  } else if (event.code === 1000) {
    // Normal - reconnect with backoff
  }
};
```

## Events & Status Codes

| Code | Status    | SDK Event   | API Pattern             | Description                                  |
| ---- | --------- | ----------- | ----------------------- | -------------------------------------------- |
| 100  | Pending   | `pending`   | `transaction.pending`   | Transaction created, waiting to be submitted |
| 110  | Submitted | `submitted` | `transaction.submitted` | Transaction submitted to blockchain          |
| 200  | Success   | `success`   | `transaction.success`   | Transaction confirmed successfully           |
| 400  | Rejected  | `rejected`  | `transaction.rejected`  | Transaction rejected (before submission)     |
| 500  | Reverted  | `reverted`  | `transaction.reverted`  | Transaction reverted onchain                 |

Use `transaction.*` to subscribe to all transaction events, or `*` for all events.

**Base Fields (All Statuses)**

All status objects include:

* `id` (string): Transaction identifier
* `status` (number): Status code (100/110/200/400/500)
* `chainId` (string): Chain ID
* `createdAt` (number): Unix timestamp (seconds)

**Status-Specific Fields**

<Tabs>
  <Tab title="Pending (100)">
    ```json theme={null}
    {
      "id": "tx-123",
      "status": 100,
      "chainId": "1",
      "createdAt": 1704067200
    }
    ```
  </Tab>

  <Tab title="Submitted (110)">
    ```json theme={null}
    {
      "id": "tx-123",
      "status": 110,
      "chainId": "1",
      "createdAt": 1704067200,
      "hash": "0x..."
    }
    ```
  </Tab>

  <Tab title="Success (200)">
    ```json theme={null}
    {
      "id": "tx-123",
      "status": 200,
      "chainId": "1",
      "createdAt": 1704067200,
      "receipt": {
        "status": "0x1",
        "gasUsed": "0x5208",
        "blockHash": "0x...",
        "blockNumber": "0x3039",
        "transactionHash": "0x...",
        "transactionIndex": 0,
        "from": "0x...",
        "to": "0x...",
        "logs": [],
        "logsBloom": "0x00...",
        "type": "0x2",
        "effectiveGasPrice": "0x4a817c800",
        "cumulativeGasUsed": "0x5208",
        "contractAddress": null
      }
    }
    ```
  </Tab>

  <Tab title="Rejected (400)">
    ```json theme={null}
    {
      "id": "tx-123",
      "status": 400,
      "chainId": "1",
      "createdAt": 1704067200,
      "message": "Insufficient funds",
      "data": { "details": "..." }
    }
    ```
  </Tab>

  <Tab title="Reverted (500)">
    ```json theme={null}
    {
      "id": "tx-123",
      "status": 500,
      "chainId": "1",
      "createdAt": 1704067200,
      "message": "execution reverted",
      "data": "0x08c379a0...",
      "receipt": {
        "status": "0x0",
        "gasUsed": "0x5208",
        "blockHash": "0x...",
        "blockNumber": "0x3039",
        "transactionHash": "0x...",
        "transactionIndex": 0,
        "from": "0x...",
        "to": "0x...",
        "logs": [],
        "logsBloom": "0x00...",
        "type": "0x2",
        "effectiveGasPrice": "0x4a817c800",
        "cumulativeGasUsed": "0x5208",
        "contractAddress": null
      }
    }
    ```
  </Tab>
</Tabs>

Receipt structure varies by chain type. All receipts include the transaction hash and chain-specific execution details.

<Note>
  For complete RPC method documentation, see `relayer_getStatus`.
</Note>

## Error Codes

Standard JSON-RPC error codes:

| Code   | Meaning                                    |
| ------ | ------------------------------------------ |
| -32700 | Parse error — Invalid JSON                 |
| -32600 | Invalid Request — Not valid JSON-RPC       |
| -32601 | Method not found — Unknown method          |
| -32602 | Invalid params — Invalid filter parameters |
| -32000 | Server error — Generic server error        |
