/v1/snapshots,
/v1/markets/{id}/orderbook, or the
live WebSocket — has the same shape.
Snapshot fields
| Field | Type | Notes |
|---|---|---|
market_id | string | Hex CLOB market hash (0x…). |
ts | ISO-8601 UTC | Snapshot timestamp, millisecond precision. |
yes_bids / yes_asks | array of {price, size} | YES side levels, sorted (bids desc, asks asc). |
no_bids / no_asks | array of {price, size} | NO side levels, same ordering. |
best_yes_bid | float|null | First yes_bids price. |
best_yes_ask | float|null | First yes_asks price. |
mid_yes | float|null | (best_yes_bid + best_yes_ask) / 2. |
spread_yes | float|null | best_yes_ask − best_yes_bid. |
underlying_ticker | string | BTC / ETH / SOL. |
underlying_price | float|null | Binance spot at ts, denormalised so you don’t need to join. |
source | string | "ws" (real-time WS push) or "price_change" (CLOB delta). |
Level depth
yes_* / no_* arrays carry up to 10 levels per side. That’s
deeper than Polymarket’s CLOB usually quotes (most books are 3–5
levels), but matches the cap the CLOB itself publishes.
If you need a quick top-of-book number, use the precomputed
best_* / mid_* columns rather than re-parsing the arrays — same
value, less JSON.
Symmetry
Polymarket’s CLOB enforces that YES and NO orderbooks are price-complement mirrors: a YES bid at 0.59 of the same size, and vice versa. We render both sides verbatim from the WS feed without dedup — both columns are populated, and the symmetry should hold. If you spot a violation (yes_bid + no_ask < 1.0 or > 1.0 by more than a few
cents), please report it — it’s either a logical arb (see
Arb audit) or a feed glitch.
Cadence
The Polymarket collector samples adaptively:- Active markets (recent move or trade): up to 8 snapshots / sec.
- Quiet markets: throttle to ~2 sec base.
- Median observed cadence: 178 ms between snapshots, per-market.
- p90 cadence: 7.2 sec (during quiet periods).
/v1/markets/{id}/orderbook endpoint
returns the raw stream without resampling.
L2 depth for exchanges
Polymarket-side L2 lives at the schema above. The exchange-side (Binance spot / Bybit linear perp) L2 lives in separate endpoints with a slightly different field shape (bids/asks directly as
[[price, qty], …] arrays):
GET /v1/binance/depth— top-20 @ 100 msGET /v1/bybit/depth— top-50 @ ~200 ms