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:
| 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 |
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
Pending (100)
Submitted (110)
Success (200)
Rejected (400)
Reverted (500)
{
"id": "tx-123",
"status": 100,
"chainId": "1",
"createdAt": 1704067200
}
{
"id": "tx-123",
"status": 110,
"chainId": "1",
"createdAt": 1704067200,
"hash": "0x..."
}
{
"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
}
}
{
"id": "tx-123",
"status": 400,
"chainId": "1",
"createdAt": 1704067200,
"message": "Insufficient funds",
"data": { "details": "..." }
}
{
"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
}
}
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
| Limit | Value |
|---|
| Subscriptions per connection | 100 |
| Subscriptions per API key | 1000 |
| Chain IDs per subscription | 50 |
| Event type patterns per subscription | 20 |
| Transaction ID length | 200 chars |
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 |