Public Channels
Public channels are unauthenticated and keyed by numeric marketId. Book
levels are [price, qty] string pairs in micro-units ("1000000" = 1.0), so
they survive JavaScript number limits.
Channels
| Channel | Scope | Payload |
|---|---|---|
marketSnapshot | Market | The full public snapshot: book (yes/no for outcome markets, spot for spot markets), mids, last prices, 24 h volume and reference prices, recent trades, topOfBookChecksum |
l2Book | Market | { marketId, seq, prevSeq, stateVersion, topOfBookChecksum, book } — the same book object, without the surrounding statistics |
trades | Market | { marketId, seq, prevSeq, stateVersion, topOfBookChecksum, trades[] } — public trade tape without account fields |
bbo | Market | { marketId, seq, prevSeq, stateVersion, topOfBookChecksum, spot: { bid, ask } } for spot markets, yes/no best levels for outcome markets |
activeAssetCtx | Market | Per-market context (mids, last, 24 h reference); the compact companion to marketSnapshot |
Private fields are stripped before public frames leave the server; the
topOfBookChecksum lets you verify that your local top of book matches the
server after applying a frame.
Subscribe
{ "id": "sub-1", "method": "subscribe", "subscription": { "type": "l2Book", "marketId": 3, "depth": 20 } }
{ "id": "sub-2", "method": "subscribe", "subscription": { "type": "trades", "marketId": 3, "limit": 50 } }
{ "id": "sub-3", "method": "subscribe", "subscription": { "type": "bbo", "marketId": 14 } }
The acknowledgement echoes the subscription and states snapshotSeq and
liveFromSeq; the first frames after it are the snapshot, then
snapshot_end, then live deltas.
Orderbook pattern
- Subscribe to
l2Bookfor the market. - Apply the snapshot the server sends after the ack (or fetch
GET /api/v1/public/markets/{marketId}/orderbookand drop frames withseq <= snapshot seq). - Apply deltas only while
seq == prev_seq + 1. - Compare
topOfBookChecksumafter each frame; on a mismatch or a gap, resubscribe withfromSeqset to the last good sequence, and if the server answersresume_required, rebuild from REST.
Placement status on the recoverable market feed
The snapshot-and-delta endpoints at /api/v1/feed/public,
/api/v1/feed/public/a, and /api/v1/feed/public/b send a global status
frame right after the connection's session frame and whenever order
placement readiness changes:
{
"type": "status",
"sessionState": "cancel_only",
"placementReady": false,
"cancelOnlyAvailable": true,
"reason": "execution persistence degraded (1 unrecovered job(s))",
"tsMs": 1786259008273
}
This is connection state rather than sequenced market data. It has no seq,
prev_seq, marketId, or channel, is not replayed, and must not take part
in gap detection. Stop new placement when placementReady is false;
cancelOnlyAvailable says whether cancellation still works.
GET /api/v1/status remains available as a fallback after reconnects.
Limits
The session frame carries maxSubscriptionsPerConnection and
publicMaxMarketsPerConnection. Exceeding either closes the connection with
code 4409. Market makers that need many markets should open several
connections or use the redundant /feed/public/a + /b lines, which carry
every market in one sequenced stream.