Protocol & session frames
All streaming rides ONE WebSocket endpoint (GET /v1/ws, standard
HTTP/1.1 Upgrade). After the upgrade, both sides exchange small JSON
frames:
- client → server:
{"op": "subscribe" | "unsubscribe", "channel": "...", "params": {...}}and{"op": "ping"} - server → client:
{"channel": "...", "event": "...", "data": {...}}, acks (subscribed/unsubscribed),ping/pong, anderrorframes.
Auth: public channels need no auth. Private channels (fill,
account) unlock by presenting the bearer token on the Upgrade
request (Authorization: Bearer <prefix>.<suffix>). Browser
clients, whose WebSocket API cannot set headers, may pass the same
credential as ?token=<key> — the header wins when both are present,
and non-browser clients should prefer the header (query strings get
logged by intermediaries).
Heartbeat: the server sends {"event":"ping"} every 15 s; reply
(any frame counts as liveness) or the connection is closed. The
server-side write timeout is 5 s — slow consumers are dropped.
Reconnect: missed frames are NOT replayed. On reconnect,
resubscribe and reconcile via REST (GET /v1/snapshot,
GET /v1/orders); orderbook_delta re-bootstraps with a full-book
frame and candles re-sends the open bar, so those two self-heal.
Acks: subscribed / unsubscribed acks echo channel (and
instrument_id when applicable) but do NOT echo the candles
resolution param — track it locally when correlating.
Download the machine-readable spec: asyncapi.yaml.
Authentication
Bearer token (<prefix>.<suffix> — API key or session token)
presented as the Authorization header on the HTTP Upgrade
request (browsers may use ?token=<key>; the header wins).
Optional for public channels; required to subscribe to fill
and account.
Client frames
{ "op": "subscribe", "channel": "orderbook_delta", "params": { "instrument_id": 1000 } }
{ "op": "unsubscribe", "channel": "orderbook_delta", "params": { "instrument_id": 1000 } }
{ "op": "ping" }
| Field | Type | Required | Description |
|---|---|---|---|
op | subscribe (const) | ✓ | |
channel | orderbook_delta · trade · candles · mark · market_lifecycle · fill · account | ✓ | |
params | object | — | |
params.instrument_id | integer · int64 | — | Required for orderbook_delta / trade / candles / mark. |
params.resolution | 1m · 5m · 15m · 1h · 1d | — | Required for candles. |
Server frames
{ "event": "subscribed", "channel": "orderbook_delta", "data": { "channel": "orderbook_delta", "instrument_id": 1000 } }
{ "event": "unsubscribed", "channel": "orderbook_delta", "data": { "channel": "orderbook_delta", "instrument_id": 1000 } }
{ "event": "ping" }
{ "event": "pong" }
{ "event": "error", "data": { "reason": "authentication required for channel 'fill'" } }
Acks echo channel (and instrument_id where applicable) but not the
candles resolution param — track it locally when correlating. Error
reasons include unknown channel: <name>,
invalid params: <details>, and
authentication required for channel 'fill'; after an error frame the
server may close the connection.