Skip to main content
The BOOK channel delivers a normalized orderbook: a full SNAPSHOT first, then DELTA frames carrying only the levels that changed. It’s the default channel when you omit channels on SUBSCRIBE.

Prices and sizes

Every market is normalized to one scale, regardless of venue: A Level is { price, size }. A snapshot carries separate bids and asks arrays of levels; a delta carries a flat list of changes, where each change is { side, price, size } and size: 0 means that price level is now gone.

SNAPSHOT and DELTA

A SNAPSHOT replaces your local book. A DELTA mutates it: each change is { side, price, size }, and size: 0 deletes that price level. We deliberately don’t distinguish add / update / remove. It’s always “set this level to this size, where 0 means gone.” Both timestamps are Unix milliseconds. venueTimestamp is the best time we hold for the underlying event, usually the venue’s own; serverTimestamp is when we emitted the frame. A venueTimestamp of 0 means we have no time for that frame: skip any age or latency calculation for it rather than reading it as a very old book. Some frames carry a time that is later than the last ladder change, such as a book we fetched to recover after a disconnect, which is stamped with when it was fetched. The first snapshot on a subscribe can predate your subscribe. It is the most recent book we hold for that market. When we open an upstream subscription for you it is current; when the market is already being streamed for someone else, or its venue publishes on one account-wide feed rather than per market, it is whatever the venue last published, which on a market that has not moved in a while is already aged. The gap between serverTimestamp and venueTimestamp is an approximate age. The two come from different clocks, so skew between the venue’s clock and ours can push it either way, and a frame stamped when we fetched or received it shows a shorter gap than the time since the ladder last changed. Treat a large gap as “quiet”, not as bad data: those levels were still resting when the venue last spoke. Subsequent frames on a moving market arrive within milliseconds. A minimal apply loop:

Sequencing and resync

Per subscription, seq is a monotonically increasing integer that we assign at ingestion (not the venue). The core guarantee for the book channel:
We never send a DELTA whose seq is not exactly the previous seq + 1. If we otherwise would, we send a SNAPSHOT instead.
How this works:
  • The first frame on a book subscription is always a SNAPSHOT.
  • On a venue gap or upstream reconnect, you get a STATUS frame with state: "RESYNCING", then a fresh SNAPSHOT, then DELTAs resume. Drop your book on RESYNCING and trust the next snapshot.
  • A mid-stream SNAPSHOT (seq jumps via a snapshot rather than a +1 delta) is normal and expected. Replace your book and carry on.
Because of this contract, your apply loop needs no gap-handling logic of its own. As a minimal-effort defensive check, track the last seq per subscription; if a DELTA ever arrives where seq !== last + 1, you can simply wait for the SNAPSHOT that the contract guarantees is coming. The trade channel has its own per-market sequence space and no resync mechanics: its seq works differently, so don’t apply book reasoning to it.