EventSource client, apply the initial snapshot, then
fold in delta/update events. All streams diff server-side and send a comment
heartbeat (:heartbeat) roughly every 15s so proxies keep the connection open.
Reconnect discipline. On any disconnect, reconnect and re-apply the fresh
snapshot — do not assume you can resume mid-stream. Messages carry a
monotonic sequence (id: or eventSeq); if you detect a gap, reconnect and
re-snapshot rather than trusting a partial book.The five streams
Perp order book
GET /perps/book-stream — public depth for one perp/future market.Perp user stream
GET /perps/stream/events — book + your fills + your positions.Options board
GET /markets/board/stream — public marks, IV, Greeks per underlying.Options CLOB stream
GET /options/stream/events — tradable book + tape for one instrument.Portfolio balances
GET /portfolio/balances/stream — your cross-bucket balance state.book-stream, board/stream) need no credentials. Private
streams require a session cookie or API key; their fills, positions, and
balances are scoped to the authenticated account.
Envelope & event names
Named-event streams emitevent: snapshot on connect then event: delta (or
event: update) on change, with a canonical envelope:
size: "0" means that price level was
removed. An event: error carries { code, message, retryable }.
Perp order book — public
Levels. Default
25, max 100.Emit cadence. Default
100, range 50–2000.GET /perps/book-stream — pure market data, no user fields. First snapshot is
the full book; then update diffs. Each level is { price, size, total }.
data
Perp user stream — private
One market per connection.
Default
25, max 250.Default
~500, range 100–5000.GET /perps/stream/events — auth required. One market per connection,
carrying three things: the public order book, your fills, and your
positions. Pass marketId.
GET /perps/stream/user — auth required. Your fills and positions across
all markets on one connection (no order book). This is the stream to use for
account-wide fill tracking and market making — one connection instead of one per
market. Params: openOnly, intervalMs (default ~250).
Book levels; deltas send changed levels (
size:"0" = removed).Your fills:
{ side, price, quantity, liquidity, createdAt } where liquidity
is maker or taker.Your positions:
{ side, quantity, entryPrice, realizedPnl, status }. Deltas
send position upserts and removedIds.Options board — public
e.g.
BTC. Defaults to the primary underlying.GET /markets/board/stream — ~1 update/sec, data-only messages wrapping
{ eventType: "OptionsBoardSnapshot", eventSeq, engineTs, payload }. The payload
is the full board snapshot: underlyingPrice, underlyingSymbol, expiries[],
per-expiry forwards, and options[] rows with strike, expiry, bid, ask, mark, iv, delta plus the volatility-index block.
The board is the reference marks surface — not a tradable book. For a hittable
options book, use the options CLOB stream below.
Options CLOB stream — private
One option instrument.
Default
25, max 250.Default
~100, range 50–2000.Add the reference-mark overlay.
GET /options/stream/events — auth required. Same envelope as the perp user
stream: event: snapshot (OptionsStreamSnapshot) then event: delta
(OptionsStreamDelta) with monotonic eventSeq. Payload: the instrument’s
tradable CLOB order book, the public trade tape
({ side, price, quantity, liquidity }, no counterparty data), and — only when
includeReference=true — a reference overlay { markPrice, source, tradable: false }.
Portfolio balances — private
GET /portfolio/balances/stream — auth required. event: snapshot
({ type: "snapshot", payload }) on connect, then event: update whenever your
unified balances change across the wallet / perps / options / spot buckets.
Heartbeat every 15s; event: error on upstream failure.