Skip to main content
Every client → server message uses the same envelope on both gateways:
  • id — client-side correlation id; echoed in the response.
  • cmd — one of subscribe / update_subscription / unsubscribe / list_subscriptions / get_book_snapshot / ping.
  • params — command-specific payload (omitted for ping and list_subscriptions).
Every accepted subscription gets a connection-local sid (numeric). Use sid for subsequent updates / unsubscribes and to route incoming events. sids are not stable across reconnects.

subscribe

On /ws/user:
On /ws/market:
Response (market gateway, with a bad tokenId rejected):

Normalization rules

  • All addresses lowercased.
  • tokenId is decimal-string with no leading zeroes.
  • conditionId is lowercased 32-byte hex.
  • Duplicate ids removed.

Rejection codes


update_subscription

Modify the id list of an existing id-based subscription instead of opening a new one. Not allowed on channels whose subscription has no id list (user_orders, user_fills, user_activity, notifications, dispute_intent, bond_payout_credited, me_limits_invalidated, the all_* channels and global_activity): the command is answered with invalid_params ("<channel> does not support id updates").

Add ids

Remove ids

Response (server returns the resulting full id set):
A failed update_subscription leaves the subscription unchanged and answers with an error frame, not a rejected[] list:
The codes are invalid_params for a malformed request, a subscription-less channel or a malformed id, forbidden for a vault id that is not this socket’s vault, not_found for an unknown sid, duplicate_subscription when another subscription on the connection already has the resulting shape, and subscription_too_many_ids when the ids already on the sid plus the added ones exceed 100. Error frames also carry a trace_id when one is available.

get_book_snapshot

Force a fresh book_snapshot without unsubscribing / resubscribing. Use on a sequence gap (book_delta data.prevSeq differs from the last seq you applied) or after a long pause. By sid (every token on that token_book subscription; add ids to refresh only some of them):
By token ids, without a sid:
The server first acknowledges with the resolved token list (sid is echoed only when you passed one):
It then pushes one book_snapshot per token id, or a book_snapshot_failed for a token whose snapshot couldn’t be fetched. Snapshots requested by ids alone carry no sid.
retryable is always true — back off and send the command again. subscriptionActive is true when the request carried a sid (that subscription stays in place and keeps streaming) and false for a request by ids alone. A sid that isn’t a token_book subscription is rejected with invalid_params; an unknown sid with not_found; a request with neither sid nor an ids array with invalid_params ("ids array is required").

unsubscribe

Unknown sids are silently ignored (idempotent — the response only lists sids that were actually removed).

list_subscriptions

Useful after a reconnect to confirm what the server thinks you’re subscribed to before rebuilding state.

ping

ts is the server clock in milliseconds — clients can use it as a clock-skew probe. The server enforces an idle timeout (60 s by default). It sends a WebSocket protocol-level ping every half window (30 s by default) and drops, without a close frame, any connection that has neither answered with a protocol pong nor sent a message since the previous ping. Browsers and the common WebSocket libraries answer protocol pings automatically. Production clients should still send a ping command every 20–30 s: any client message counts as activity, and it also keeps intermediate proxies / load balancers from closing an idle TCP connection.