?book= and ?market= query filters so you can pull only the slices you care about in one round trip.
lib-gar-est-2026-04-14) or a raw game_id (40664-16839-2026-04-14). Both resolve to the same record. Unmatched games where pn_slug is null still work — just use the game_id.
Polynode slug (e.g.
nba-mia-cha-2026-04-14) or raw game_id (e.g. 40664-16839-2026-04-14).Your API key. Accepted via query param or
Authorization: Bearer header.Comma-separated list of
pn_market_type values to include (e.g. moneyline,spreads,totals). Omit for all markets.Comma-separated list of book names to include (e.g.
DraftKings,Polymarket,BetMGM). Omit for all books.Response
This is a real response for a live NBA game (Portland @ Phoenix, Q3 03:42) filtered tomarket=moneyline on three books:
Top-level shape
| Field | Type | Description |
|---|---|---|
game | object | Full game envelope: teams, scores, venue, status, start_date, broadcast. Same shape returned by List Live Games. |
market_count | integer | Number of distinct pn_market_type keys in markets after filtering. |
outcome_count | integer | Total number of outcomes across all markets after filtering. |
markets | object | Dict keyed by pn_market_type. Each value is a flat list of outcomes. Markets with zero outcomes after filtering are omitted. |
Outcome object
| Field | Type | Description |
|---|---|---|
book | string | Sportsbook name exactly as upstream labels it ("DraftKings", "FanDuel", "BetMGM", "Polymarket", "Polymarket (USA)", "bet365"). Pass into ?book= to filter. |
outcome | string | Outcome label. Team name for moneyline, "Over 4.5" / "Under 4.5" for totals, player name with line for player props. Same field name as the WS price_change event. |
price | number | American odds. Negative = favorite (-225 = risk 100), positive = underdog (+175 = risk 175). Prediction-market books sometimes emit extreme values like +9900 or -99900 when a market is near-resolved — cap or convert to implied probability client-side if you’re running arb math. |
points | number | null | Spread or total line when applicable (-6.5, 2.5, 217.5). null for moneyline. |
player_id | string | null | Upstream player id when the outcome is a player prop. |
Same endpoint as /markets
/v1/games/{id} and /v1/games/{id}/markets return identical shapes and accept identical filters. They are aliases. Use whichever URL reads better in your code.
Book coverage varies by league and market
Not every book carries every market. A live NBA moneyline is carried by 60-90 books; a live AHL game might only have 5-10. DraftKings’ mainline sportsbook does not currently publish NBA moneylines — their NBA odds ship under theDraftKings Predictions book name. If you filter to ?book=DraftKings on an NBA game and get empty results, that’s why. Use List Books to see which books are currently known to the system.
Post-restart warmup window
For ~30 seconds after the service restarts, the market backfill runs one market type at a time across all sports. You may see fewerpn_market_type keys than the steady-state total. Retry a few seconds later or subscribe to /ws/odds to stream the fill as it happens.
Refresh semantics
- Live games re-poll every ~1 second.
- Idle (unplayed / final) games re-poll every ~10 seconds.
- For real-time deltas, subscribe to
/ws/oddsand applyprice_changeevents on top of this baseline.

