Skip to main content
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:
const bundler = await createGelatoBundlerClient({
  account,
  apiKey: process.env.GELATO_API_KEY,
  ws: { disable: true }
});

Subscribe to a Single Transaction

const id = await bundler.sendUserOperation({
  calls: [{
    to: '0xTargetContract...',
    data: '0xCalldata...',
  }],
  payment: sponsored()
});

const subscription = await bundler.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 bundler.ws.unsubscribe(subscription.subscriptionId);
bundler.ws.disconnect();

Subscribe to All Transactions

const subscription = await bundler.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

await bundler.ws.unsubscribe(subscription.subscriptionId);
bundler.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

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
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 for the full list. Use transaction.* for all events or * for everything.
// 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]
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:
{
  "jsonrpc": "2.0",
  "method": "connected",
  "params": {
    "clientId": "uuid",
    "timestamp": 1234567890
  }
}
Connection Confirmation (Simple Endpoints) Sent when connection established on /ws/transactions/:id:
{
  "jsonrpc": "2.0",
  "method": "connected",
  "params": {
    "clientId": "uuid",
    "subscriptionId": "sub-uuid",
    "entityId": "abc123",
    "timestamp": 1234567890
  }
}
Error Response
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": { "issues": ["..."] }
  },
  "id": 1
}
Ping/Pong Keep connection alive by sending ping:
// 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.
This is separate from the JSON {type: "ping"} message, which is also supported for backward compatibility.
WebSocket Close Codes When the server closes a connection, it sends a close frame with a status code and optional reason:
CodeMeaningDescription
1000Normal ClosureClean disconnect (unsubscribe all, timeout, client request)
1001Going AwayServer is shutting down
1008Policy ViolationAuthentication failure or rate limit exceeded
1011Internal ErrorUnexpected server error
4000Invalid FilterBad subscription parameters
4001Limit ExceededToo many subscriptions (100/connection or 1000/API key)
4002UnauthorizedAPI key invalid, expired, or missing
4003ForbiddenTestnet key used on production endpoint
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

CodeStatusSDK EventAPI PatternDescription
100Pendingpendingtransaction.pendingTransaction created, waiting to be submitted
110Submittedsubmittedtransaction.submittedTransaction submitted to blockchain
200Successsuccesstransaction.successTransaction confirmed successfully
400Rejectedrejectedtransaction.rejectedTransaction rejected (before submission)
500Revertedrevertedtransaction.revertedTransaction 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
{
  "id": "tx-123",
  "status": 100,
  "chainId": "1",
  "createdAt": 1704067200
}
Receipt structure varies by chain type. All receipts include the transaction hash and chain-specific execution details.
For complete RPC method documentation, see relayer_getStatus.

Rate Limits

LimitValue
Subscriptions per connection100
Subscriptions per API key1000
Chain IDs per subscription50
Event type patterns per subscription20
Transaction ID length200 chars

Error Codes

Standard JSON-RPC error codes:
CodeMeaning
-32700Parse error — Invalid JSON
-32600Invalid Request — Not valid JSON-RPC
-32601Method not found — Unknown method
-32602Invalid params — Invalid filter parameters
-32000Server error — Generic server error