tickstreamdocs

DOCS

L3 / market-by-order

Order-by-order depth: every individual resting order with its exchange order id, queue priority and nanosecond timestamp.

requiresL3 / Market-by-order or above

The l3 channel streams depth per order instead of per price level. Every individual resting order is its own event — placed, modified, cancelled or filled — carrying the exchange order id, its queue priority at that price and a nanosecond exchange timestamp. It's included on the Ultra plan.

L2 vs L3

L2 tells you there are 42 contracts bid at 23481.25. L3 tells you those 42 are seven separate orders, in what queue order, and which one just pulled. That's the difference between seeing size and seeing intent — queue position, iceberg detection and order-lifetime studies all need L3.

Subscribe

{ "op": "subscribe", "channel": "l3", "symbols": ["NQ"] }
# the l3 channel is raw-WS today — the SDK helper ships next
import json, websockets

async with websockets.connect("wss://stream.tick-stream.xyz/v1/stream?key=sk_live_…") as ws:
    await ws.send(json.dumps({"op": "subscribe", "channel": "l3", "symbols": ["NQ"]}))
    async for raw in ws:
        e = json.loads(raw)
        if e["type"] == "l3":
            print(e["action"], e["order_id"], e["side"], e["price"], e["size"])

L3 is available for the CME futures roots (NQ, ES, YM, RTY…) — the same symbols as Level 2. Subscribing to l3 does not replace book: you can run both on one connection, and the aggregated book frames are built from this very order feed.

The l3 message

{
  "type": "l3",
  "symbol": "NQ",
  "order_id": "7412998336104",
  "action": "new",
  "side": "bid",
  "price": 23481.25,
  "size": 3,
  "priority": 18,
  "seq": 49437907,
  "ts": 1753900800,
  "ns": 412903771
}
FieldTypeDescription
order_idstringExchange order id. Stable for the whole life of the order — this is what lets you track one participant's order across modifications.
actionstringnew (order added), change (size/price modified) or delete (cancelled or fully filled).
sidestringbid or ask.
pricenumberLimit price of this order.
sizenumberDisplayed size of this order (not the level total).
prioritynumberExchange queue priority at that price — lower means closer to the front of the queue.
seqnumberExchange sequence number. The authoritative event order — sort by this, not by arrival.
tsintegerExchange timestamp in Unix seconds.
nsintegerNanoseconds within that second, as stamped by the exchange.

Rebuilding a book from L3

An order feed is a delta feed: apply each event to a map keyed by order_id and you hold the exact book. Aggregate that map by price whenever you need a level view.

# an L3 stream IS the book — aggregate it whenever you want a level view
book = {}  # order_id -> (side, price, size)

def apply(e):
    if e["action"] in ("new", "change"):
        book[e["order_id"]] = (e["side"], e["price"], e["size"])
    elif e["action"] == "delete":
        book.pop(e["order_id"], None)

def levels(side):
    out = {}
    for s, px, sz in book.values():
        if s == side:
            out[px] = out.get(px, 0) + sz
    return sorted(out.items(), reverse=(side == "bid"))
gaps are visible, never silent

If your connection can't keep up, we send a {"type":"warning","warning":{"code":"l3_lagged","dropped":N}} frame instead of quietly skipping events — a book rebuilt across a hidden gap is wrong in ways that are very hard to notice. On that warning, drop your local book and resubscribe.

GET /v1/l3 — replay

Replay recorded order-level events over REST. Same fields as the stream, ordered by time.

ParamRequiredDescription
symbolyesThe instrument, e.g. NQ.
start / endnoISO-8601 UTC or Unix seconds. Max window 1 hour per request — an L3 hour is hundreds of thousands of events. Defaults: end = now, start = 5 minutes before.
limitnoMax events (default 50,000, max 500,000).
curl "https://api.tick-stream.xyz/v1/l3?symbol=NQ&start=2026-07-30T13:30:00Z&end=2026-07-30T14:00:00Z" \
  -H "Authorization: Bearer sk_live_…"
no L3 history before we recorded it

There is no vendor archive for order-level data — nobody sells CME MBO history back in time, and our own tick/L2 archive (2019 →) does not contain it either. The L3 replay window therefore starts the day we switched order-level recording on and grows forward. If you need L3 for a specific study, tell us the symbol now so it's in the recording set: [email protected].

plan

Subscribing to l3 or calling /v1/l3 without it returns 403 plan_required. See what the packages include.