WebSocket Transport

Real-time x402 payments over WebSockets

Pay once, stream requests continuously.

WebSocket relay lets agents reuse a single connection for multiple paid requests — faster, cheaper, and optimized for real-time workloads like AI agents, chat systems, and streaming APIs.

Recommended for AI agents, chat systems, and high-frequency usage.

10-second example

agent.ts
import { RelaiWebSocketClient } from "@relai-fi/x402/ws"

const ws = new RelaiWebSocketClient({
  url: "wss://api.relai.fi/api/ws/relay",
  wallets: { solana: solanaWallet, evm: evmWallet }
})

await ws.connect()

// first call — triggers 402 → sign → retry automatically
const res = await ws.call({
  apiId: "1769629274857",
  path: "/v1/chat/completions",
  body: { messages: [{ role: "user", content: "hello" }] }
})

// subsequent calls — no reconnect, no new handshake
const res2 = await ws.call({ apiId: "1769629274857", path: "/v1/chat/completions", ... })

Why WebSocket?

Use WebSocket relay when:

you send many requests (agents, bots, pipelines)
you need low latency between calls
you want to avoid repeated payment handshakes
you stream responses (AI completions, chat)
Otherwise, HTTP relay works fine — and is simpler to set up.

How it works

ConnectRequest402SignRetryStreamNext request
No reconnect. No new handshake for subsequent requests.

WebSocket relay keeps the same x402 payment model. Only the transport changes — not the payment logic.

Shared endpoint

Each API has its own HTTP relay URL — WebSocket calls go through one shared gateway.

HTTP relay (per API)
https://api.relai.fi/relay/{apiId}/...
WebSocket gateway (shared)
wss://api.relai.fi/api/ws/relay

Given the HTTP URL https://api.relai.fi/relay/1769629274857/v1/chat/completions?model=gpt-4o-mini, the WS parameters are:

apiId=1769629274857
path=/v1/chat/completions?model=gpt-4o-mini

Request format

Send a relay.call message with a unique id for response correlation:

relay.call envelope
{
  "id": "req-42",
  "method": "relay.call",
  "params": {
    "apiId": "1769629274857",
    "path": "/v1/chat/completions?model=gpt-4o-mini",
    "requestMethod": "POST",
    "requestHeaders": {
      "Content-Type": "application/json"
    },
    "requestBody": {
      "messages": [{ "role": "user", "content": "Hello" }]
    }
  }
}

Payment handshake

Same x402 flow as HTTP — just over WebSocket frames:

01Send request without top-level payment
02Server responds with error.code = 402 and error.paymentRequired
03Sign a valid x402 payment payload
04Retry the same request with top-level payment field added
05Read result and optional paymentResponse

Persistent connections

Reuse one WS connection for many relay requests
Correlate every response by its id field
Use per-request timeouts, not just connection-level
On transport errors, fall back to HTTP relay automatically

For API providers

You don't need to change anything. Keep your existing HTTP relay integration — buyers can still access your paid endpoints over WebSocket automatically. The same x402 payment flow applies; only the transport is different.

Troubleshooting

No response for a request

Ensure every request has a unique id and your client matches responses by that id.

Unexpected 402 loop

Verify the retry request contains a top-level payment field matching one of the accepted requirements.

WS unavailable in some environments

Keep HTTP fallback enabled and set a shorter WS timeout so flows are not blocked by long retries.

    Real-time x402 payments over WebSockets | RelAI Documentation | RelAI