Skip to content
Alchemy Logo

StreamL2BookDiff

This API is in private preview. Target September 2026; timing is subject to change.

StreamL2BookDiff delivers incremental price-level changes so that a client can maintain a local order book at a fraction of snapshot bandwidth. This is ideal for latency-sensitive consumers that need continuous book state.

  • Each message contains changes for the markets that changed in its block
  • The initial snapshot supplies current levels unless skip_initial_snapshot is set
  • Diffs carry absolute level sizes, not size deltas
  • Per-market sequence values identify continuity for each local book

message StreamL2BookDiffRequest {
  repeated string coins = 1;
  repeated string market_types = 2;
  uint32 n_levels = 3;
  uint32 n_sig_figs = 4;
  uint64 mantissa = 5;
  bool skip_initial_snapshot = 6;
}

Field: coins Type: repeated string

Markets to subscribe to. Empty means all markets.

Field: market_types Type: repeated string

Accepted values are perp, spot, outcome, or *. The default is ["perp"], so spot and outcome markets are not delivered unless requested. The default never grows: add new market types explicitly, or pass ["*"] to opt in to future types automatically. This field is rejected when combined with an explicit coins list.

Field: n_levels Type: uint32

Levels per side: 1, 10, 20 (default), or 50.

Field: n_sig_figs Type: uint32

Accepted values are 2, 3, 4, or 5.

Field: mantissa Type: uint64

Accepted values are 2 or 5, and this field is valid only when n_sig_figs = 5. Aggregation rounds bids down and asks up. With n_sig_figs = 5 and mantissa = 2, a bid of 70325 becomes 70324 and an ask of 70325 becomes 70326.

Field: skip_initial_snapshot Type: bool

Default: false. When false, the first message for each market carries that market's current levels as a snapshot. Set true only if you already hold a compatible snapshot and position.

message L2BookDiffUpdate {
  uint64 height = 1;
  uint64 time = 2;
  bool snapshot = 3;
  string cursor = 4;
  repeated CoinDiff diffs = 5;
}
 
message CoinDiff {
  string coin = 1;
  uint64 seq = 2;
  uint64 prev_seq = 3;
  bool snapshot = 4;
  repeated Level bids = 5;
  repeated Level asks = 6;
}
 
message Level {
  string px = 1;
  string sz = 2;
  uint32 n = 3;
}

height: Block number.

time: Block timestamp in milliseconds.

snapshot: True when this message carries initial levels for any market.

cursor: Resume position. Persist after applying.

diffs: One entry per market that changed in this block.

diffs[].snapshot: True when the CoinDiff replaces state for that market only.

seq / prev_seq: Per-market sequence and its predecessor. If prev_seq does not match your current position for that market, you have a gap.

bids / asks: Changed levels only.

  • A level with sz of "0" has been removed from the book. Delete that price.
  • Any other level is an upsert: set that price to the given sz and n.
  • Sizes are absolute — the level's new total, not a delta.
  • Levels not present in a diff are unchanged.
  • The snapshot and all subsequent diffs must use identical n_levels, n_sig_figs, and mantissa. Applying diffs from one aggregation setting to a snapshot taken at another produces an invalid book.

A message flagged as a snapshot replaces your local state. Anything else is a diff that must chain onto your previous block.

If continuity is broken, a fresh snapshot is pushed to you. The snapshot flag is the only continuity signal you need to handle — receiving it means discard local state and adopt the snapshot.

  1. After applying each message, persist cursor and the per-market seq.
  2. On reconnect, send cursor.
  3. Check prev_seq against your position for each market on every diff.
  4. If a snapshot arrives for a market, discard your book for that market and adopt it.

StreamL2BookStreamL2BookDiffStreamL4BookUpdates
PayloadFull snapshot per blockChanged levels onlyPer-order changes
Client stateNone requiredMaintains a local bookMaintains a local book
BandwidthHighestLowModerate
DetailAggregated levelsAggregated levelsIndividual orders, with queue position
Use caseDisplays, periodic readsEfficient live bookMarket making, queue analysis
Was this page helpful?