Skip to main content

Protocol & session frames

endpointwss://api.staging.sphx.io/v1/ws

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, and error frames.

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

subscribe / unsubscribe / ping
{ "op": "subscribe", "channel": "orderbook_delta", "params": { "instrument_id": 1000 } }
{ "op": "unsubscribe", "channel": "orderbook_delta", "params": { "instrument_id": 1000 } }
{ "op": "ping" }
FieldTypeRequiredDescription
opsubscribe (const)
channelorderbook_delta · trade · candles · mark · market_lifecycle · fill · account
paramsobject
params.instrument_idinteger · int64Required for orderbook_delta / trade / candles / mark.
params.resolution1m · 5m · 15m · 1h · 1dRequired for candles.

Server frames

acks · heartbeat · error
{ "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.