What it streams
Realtime odds updates for outcomes within markets, scoped to a specificfixtureId.
Odds are grouped by bookmaker and keyed by a unique oddsId per outcome.
Each entry represents a single oddsId (one price for one outcome).
Routing
- Entity key:
payload.fixtureId - Filters:
sportIds,tournamentIds,fixtureIds,bookmakers - Access: determined by your
apiKey - Bookmaker-gated: ✅ Yes
Delivery semantics
The odds channel delivers conflated state on a fixed ~6 ms batching window: if multiple updates for the sameoddsId occur within one window, only the newest is sent.
- No state is lost — the final value of every price move is always delivered
- Bounded staleness — a delivered price is never more than one batching window behind our observation of the bookmaker
- The window is a fixed performance parameter, not a load-shedding mechanism
Need every price move or the closing line? For full tick-level movement use Historical Odds and for opening/closing prices use CLV.
Payload structure
oddsId:outcome object (full schema)
Each odds entry is an outcome, with the following fields:Notes on timestamps
Each update carries the full delivery chain:changedAt − bookmakerChangedAt is the observation delay for that update. Per-bookmaker freshness bounds are published on GET /bookmakers — see Latency and freshness.
Limits
limit is the maximum accepted stake at the current price — for a trading system, size-at-price matters as much as the price itself. OddsPapi normalizes limits across books and carries them for close to every sharp book (see "limit": 19354 on Pinnacle below). Limit changes are delivered as regular odds updates.
limit and the meta ladders bound different things: limit bounds a single order, the ladder bounds the fill. On a traditional book limit is the only size signal there is; on an exchange you have both and they constrain you independently.
See sharp-line trading & CLV for using limits together with per-book delay, main-line filtering, and closing line value.
Advanced metadata (meta)
Exchanges and prediction markets carry their orderbook on the quote itself, under meta.
Ladder entries
back and lay are arrays of rungs, best price first, up to three deep. Each rung:
Either side can be
[]. A one-sided book is normal on a thin market, not an error, and
best back touching best lay is a crossed book — read changedAt before trading it.
Additional keys
Onpolymarket, polymarket.us, kalshi and prophetx, meta also carries
bookmakerLayOutcomeId — the venue’s own id for the opposite side of the market. You need
it to route a lay order, because bookmakerOutcomeId on the quote addresses the back side
only. Those four share the same back / lay semantics, so one parser covers all of them.
Treat meta as additive and preserve keys you do not recognise.
betfair-ex uses a venue-specific shape instead: availableToBack and availableToLay
(rungs of { price, size } only — no cents or limit), plus tradedVolume, betDelay
and, on handicap markets, bookmakerHandicap.bookmakerMarketId / bookmakerOutcomeId.
Example: traditional bookmaker odds
Example: prediction market odds (extended fields)
Implementation guidance
- Always key storage by
- Group outcomes by
marketId(see Concepts) for:- arbitrage detection
- overround calculations
- probability normalization
- Treat
active=falseormarketActive=falseas hard stops - Preserve unknown fields in
metato remain forward-compatible