{"openapi":"3.1.0","info":{"title":"Player Props API","description":"Real-time player prop betting lines from Bovada. The-odds-api compatible format.","version":"0.1.0"},"paths":{"/v1/sports":{"get":{"tags":["Sports"],"summary":"List Sports","description":"List all available sports.","operationId":"list_sports_v1_sports_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SportOut"},"type":"array","title":"Response List Sports V1 Sports Get"}}}}},"security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}]}},"/v1/sports/{sport_key}/events":{"get":{"tags":["Events & Odds"],"summary":"List Events","description":"List upcoming events for a sport (no odds — free endpoint).","operationId":"list_events_v1_sports__sport_key__events_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventOut"},"title":"Response List Events V1 Sports  Sport Key  Events Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/odds":{"get":{"tags":["Events & Odds"],"summary":"List Odds","description":"Bulk odds for a sport. Filter by market keys (comma-separated).\n\nServed through a short-TTL single-flight cache — this is the single\nhighest-volume read path (48% of peak-hour traffic on the 2026-08-08 record\nday) and the response is tier-independent. See api/odds_cache.py for the\nTTL rationale. No `session` dependency: the loader opens its own read\nsession so a cancelled leader request can't poison coalesced callers.\n\nReturns a pre-rendered `Response`, so FastAPI skips `response_model`\nvalidation and re-serialization on the hot path — that step measured\n0.22-0.48s of BLOCKING event-loop time per ~2 MB response and was being paid\non cache HITS too. `response_model` is kept for the OpenAPI schema only;\n`odds_cache.render_odds_json` reproduces its output byte for byte (see that\nfunction before changing any model in this response tree).","operationId":"list_odds_v1_sports__sport_key__odds_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"markets","in":"query","required":false,"schema":{"type":"string","default":"h2h","title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Game-period filter. Omitted = full-game markets only (backwards-compatible default). Pass a comma-separated list of canonical codes (e.g. 'q1,q2' or 'h1') to filter to specific periods. Pass 'all' to include every period alongside full-game.","title":"Period"},"description":"Game-period filter. Omitted = full-game markets only (backwards-compatible default). Pass a comma-separated list of canonical codes (e.g. 'q1,q2' or 'h1') to filter to specific periods. Pass 'all' to include every period alongside full-game."},{"name":"includeLinks","in":"query","required":false,"schema":{"type":"boolean","description":"When true, each bookmaker block carries a `link` — that book's public event-page URL (plain navigation, no affiliate tagging). Only books with a verified URL template emit links (Bovada, DraftKings, FanDuel, BetMGM, Kalshi, Polymarket, Smarkets); others return null. Matches the-odds-api's `includeLinks` param.","default":false,"title":"Includelinks"},"description":"When true, each bookmaker block carries a `link` — that book's public event-page URL (plain navigation, no affiliate tagging). Only books with a verified URL template emit links (Bovada, DraftKings, FanDuel, BetMGM, Kalshi, Polymarket, Smarkets); others return null. Matches the-odds-api's `includeLinks` param."},{"name":"includeBookIds","in":"query","required":false,"schema":{"type":"boolean","description":"When true, each bookmaker block carries `book_event_id` (that book's own event identifier) and every outcome carries `book_outcome_id` (that book's own selection/contract id). Use these to join PropLine rows onto a book's native feed without matching on team names, players and lines. Kalshi ships both — the event ticker and the per-contract market ticker (e.g. KXMLBGAME-26AUG08NYYBOS-NYY). Books that don't publish a stable id return null. PropLine-specific; both fields are always present in the response shape and are null unless this param is set (same convention as `link`/`includeLinks`), so no existing consumer's parsing changes.","default":false,"title":"Includebookids"},"description":"When true, each bookmaker block carries `book_event_id` (that book's own event identifier) and every outcome carries `book_outcome_id` (that book's own selection/contract id). Use these to join PropLine rows onto a book's native feed without matching on team names, players and lines. Kalshi ships both — the event ticker and the per-contract market ticker (e.g. KXMLBGAME-26AUG08NYYBOS-NYY). Books that don't publish a stable id return null. PropLine-specific; both fields are always present in the response shape and are null unless this param is set (same convention as `link`/`includeLinks`), so no existing consumer's parsing changes."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventOddsOut"},"title":"Response List Odds V1 Sports  Sport Key  Odds Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/odds":{"get":{"tags":["Events & Odds"],"summary":"Get Event Odds","description":"Get odds for a single event — supports player prop markets.\nThis is where the real value is.\n\nDefault `markets` is `h2h,spreads,totals` — the three game-line\nmarkets every book carries across every sport. Pass an explicit\n`markets=` to fetch player props (sport-specific keys like\npitcher_strikeouts / player_points / player_goals).\nPrevious default was MLB-only and silently returned 0 bookmakers\non every other sport when the caller (or SDK) omitted the param.","operationId":"get_event_odds_v1_sports__sport_key__events__event_id__odds_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"type":"string","default":"h2h,spreads,totals","title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period.","title":"Period"},"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period."},{"name":"includeLinks","in":"query","required":false,"schema":{"type":"boolean","description":"When true, each bookmaker block carries a `link` — that book's public event-page URL (plain navigation, no affiliate tagging). Only books with a verified URL template emit links (Bovada, DraftKings, FanDuel, BetMGM, Kalshi, Polymarket, Smarkets); others return null. Matches the-odds-api's `includeLinks` param.","default":false,"title":"Includelinks"},"description":"When true, each bookmaker block carries a `link` — that book's public event-page URL (plain navigation, no affiliate tagging). Only books with a verified URL template emit links (Bovada, DraftKings, FanDuel, BetMGM, Kalshi, Polymarket, Smarkets); others return null. Matches the-odds-api's `includeLinks` param."},{"name":"includeBookIds","in":"query","required":false,"schema":{"type":"boolean","description":"When true, each bookmaker block carries `book_event_id` (that book's own event identifier) and every outcome carries `book_outcome_id` (that book's own selection/contract id). Use these to join PropLine rows onto a book's native feed without matching on team names, players and lines. Kalshi ships both — the event ticker and the per-contract market ticker (e.g. KXMLBGAME-26AUG08NYYBOS-NYY). Books that don't publish a stable id return null. PropLine-specific; both fields are always present in the response shape and are null unless this param is set (same convention as `link`/`includeLinks`), so no existing consumer's parsing changes.","default":false,"title":"Includebookids"},"description":"When true, each bookmaker block carries `book_event_id` (that book's own event identifier) and every outcome carries `book_outcome_id` (that book's own selection/contract id). Use these to join PropLine rows onto a book's native feed without matching on team names, players and lines. Kalshi ships both — the event ticker and the per-contract market ticker (e.g. KXMLBGAME-26AUG08NYYBOS-NYY). Books that don't publish a stable id return null. PropLine-specific; both fields are always present in the response shape and are null unless this param is set (same convention as `link`/`includeLinks`), so no existing consumer's parsing changes."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventOddsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/markets":{"get":{"tags":["Events & Odds"],"summary":"List Event Markets","description":"List available market types for a specific event.\nUseful for discovering what props are available before requesting odds.","operationId":"list_event_markets_v1_sports__sport_key__events__event_id__markets_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/odds/history":{"get":{"tags":["Events & Odds"],"summary":"Get Event Odds History","description":"Historical odds movement for a single event.\nPaid tiers (Hobby / Pro / Streaming Lite / Streaming / Enterprise):\nfull snapshot history. Free tier: redacted (shows structure and count).","operationId":"get_event_odds_history_v1_sports__sport_key__events__event_id__odds_history_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"type":"string","default":"h2h,spreads,totals","title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp; only include snapshots at or after this time.","title":"From"},"description":"ISO timestamp; only include snapshots at or after this time."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp; only include snapshots at or before this time.","title":"To"},"description":"ISO timestamp; only include snapshots at or before this time."},{"name":"relative_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Offset relative to commence_time, e.g. '-3h', '-30m', '-90s'. Mutually exclusive with `from`.","title":"Relative From"},"description":"Offset relative to commence_time, e.g. '-3h', '-30m', '-90s'. Mutually exclusive with `from`."},{"name":"relative_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Offset relative to commence_time, e.g. '-1m' or '0' for the closing line itself. Mutually exclusive with `to`.","title":"Relative To"},"description":"Offset relative to commence_time, e.g. '-1m' or '0' for the closing line itself. Mutually exclusive with `to`."},{"name":"interval","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Downsample to one snapshot per bucket. One of '30s', '1m', '5m', '15m', '30m', '1h'.","title":"Interval"},"description":"Downsample to one snapshot per bucket. One of '30s', '1m', '5m', '15m', '30m', '1h'."},{"name":"changes_only","in":"query","required":false,"schema":{"type":"boolean","description":"When true, drop snapshots whose (price, point) match the previous one — keep only moment-of-change rows.","default":false,"title":"Changes Only"},"description":"When true, drop snapshots whose (price, point) match the previous one — keep only moment-of-change rows."},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period.","title":"Period"},"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventHistoryOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/odds/closing":{"get":{"tags":["Events & Odds"],"summary":"Get Event Odds Closing","description":"Closing line per outcome — the last snapshot at or before\ncommence_time, per (book, market, outcome). The canonical CLV\nhelper: a single call returns the closing price your bet should\nbe measured against, instead of pulling /odds/history and\npost-processing to find the last pre-game row.\n\nPaid tiers: full data. Free tier: redacted (structure only).","operationId":"get_event_odds_closing_v1_sports__sport_key__events__event_id__odds_closing_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"type":"string","default":"h2h,spreads,totals","title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period.","title":"Period"},"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventClosingOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/movement":{"get":{"tags":["Events & Odds"],"summary":"Get Event Movement","description":"Line movement + steam detection, derived from our snapshot tick history.\n\nFor each (book, market, outcome) returns the opening line, the latest\nline, and the implied-probability / point shift between them. The\ntop-level ``steam`` array flags outcomes that multiple books moved in\nthe same direction — the classic sharp-money signal, computed across\nall 16 books we poll. No competitor offers this (they're pull-only).\n\nPaid tiers (Hobby+): full data. Free tier: redacted (structure only).","operationId":"get_event_movement_v1_sports__sport_key__events__event_id__movement_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"type":"string","default":"h2h,spreads,totals","title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."},{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period.","title":"Period"},"description":"Game-period filter. Omitted = full-game markets only. Pass canonical codes ('q1', 'h1', 'p1', 'i6', 'f5') comma-separated, or 'all' to include every period."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventMovementOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/futures":{"get":{"tags":["Events & Odds"],"summary":"List Futures","description":"List futures markets for a sport — championship winner, MVP,\ndivision winner, etc. One row per (futures event, book, market) with\nevery team or player priced. Free tier; pulled from each book's\nfutures feed (Bovada today). Order is by event commence_time\n(typically season-end) ascending.\n\nOptional `?bookmakers=` (comma-separated book keys) narrows the\nper-book market rows to those books — same the-odds-api-compatible\ncontract as every /odds endpoint: omitted = all books, unknown keys\nmatch nothing. A futures event with no market left after filtering is\ndropped so consumers never get an empty `markets: []` row.","operationId":"list_futures_v1_sports__sport_key__futures_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FuturesEventOut"},"title":"Response List Futures V1 Sports  Sport Key  Futures Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/context":{"get":{"tags":["Events & Odds"],"summary":"Get Event Context","description":"Game conditions: probable pitchers, confirmed-lineup flag, the\nhome-plate umpire, and first-pitch weather (outdoor / open-roof venues).\n\nThe context a prop settles under — joined into /results so every graded\noutcome carries its conditions. Free tier. MLB today; weather extends\nto other outdoor sports next. Returns 404 if no context is on file yet\n(e.g. before the context loop has reached the event, or for sports\nwithout a context source).","operationId":"get_event_context_v1_sports__sport_key__events__event_id__context_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameContextOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/ev":{"get":{"tags":["+EV"],"summary":"Get Event Ev","description":"Compute cross-book +EV for a single event.\n\n`markets` is an optional comma-separated filter. If omitted, every\nmarket on the event is evaluated. Each market line that has Pinnacle\n(preferred) or Bovada (fallback) coverage gets a no-vig fair price\nand an EV% per book.\n\n`bookmakers` is an optional comma-separated book-key filter\n(the-odds-api-compatible, same as on the odds endpoints) — shop only\nthe books you hold accounts at.\n\nIMPORTANT: the filter narrows the PRICES you get back. It never\nnarrows the fair-line anchor. The no-vig fair price still comes from\nthe sharp book (Pinnacle → Polymarket → Kalshi → Bovada), so\n`bookmakers=draftkings` still returns DraftKings EV% measured against\nPinnacle — the whole point of the endpoint. Filtering the anchor away\ninstead would leave every line unpriceable and return nothing.\n`fair_source` on each line always names the anchor actually used,\nfiltered or not. Lines where none of your books quote a price are\nomitted.","operationId":"get_event_ev_v1_sports__sport_key__events__event_id__ev_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventEvOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/ev/calc":{"get":{"tags":["+EV"],"summary":"Calc Event Ev","description":"Calculate EV% for a user-supplied price against the event's no-vig\nfair anchor.\n\nUseful when you bet at a book PropLine doesn't carry directly\n(Caesars, BetMGM, Fanatics, BetUS, Hard Rock, etc.). The fair line\nis derived from the same Pinnacle-preferred anchor as the bulk\n`/ev` endpoint, so the math is identical — you're just plugging in\na price we don't ingest. Returns 404 with the available outcome\nnames when the (market, point, name) tuple doesn't match any\nfair-anchored line on the event.\n\nPaid tier required (Hobby and up).","operationId":"calc_event_ev_v1_sports__sport_key__events__event_id__ev_calc_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"market","in":"query","required":true,"schema":{"type":"string","description":"Market key, e.g. 'h2h', 'spreads', 'totals', 'pitcher_strikeouts'.","title":"Market"},"description":"Market key, e.g. 'h2h', 'spreads', 'totals', 'pitcher_strikeouts'."},{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"Outcome name. For h2h/spreads: team name. For totals/props: 'Over' or 'Under'.","title":"Name"},"description":"Outcome name. For h2h/spreads: team name. For totals/props: 'Over' or 'Under'."},{"name":"price","in":"query","required":true,"schema":{"type":"integer","description":"American odds at your book, e.g. -118 or +145.","title":"Price"},"description":"American odds at your book, e.g. -118 or +145."},{"name":"point","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Line/point for spreads, totals, and player props. Omit for h2h. For spreads, sign matters: e.g. -1.5 for the favorite.","title":"Point"},"description":"Line/point for spreads, totals, and player props. Omit for h2h. For spreads, sign matters: e.g. -1.5 for the favorite."},{"name":"description","in":"query","required":false,"schema":{"type":"string","description":"Player name for player-prop markets; empty for game-line markets.","default":"","title":"Description"},"description":"Player name for player-prop markets; empty for game-line markets."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvCalcOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/projections":{"get":{"tags":["Projections"],"summary":"Get Event Projections","description":"Market-implied consensus projection per (market, player).\n\n`markets` is an optional comma-separated market-key filter, applied\nafter the cache so one caller's filter can't fragment the cache key.","operationId":"get_event_projections_v1_sports__sport_key__events__event_id__projections_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Markets"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventProjectionsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/best-line":{"get":{"tags":["Best Line"],"summary":"Get Event Best Line","description":"Return the best price across all books for every (market, player,\nline) tuple on an event.\n\n`markets` is an optional comma-separated filter (e.g.\n`markets=h2h,spreads,pitcher_strikeouts`). When omitted, every\nmarket on the event is included.\n\n`bookmakers` is an optional comma-separated book-key filter\n(the-odds-api-compatible, same as on the odds endpoints). Omitted =\nevery comparable book; unknown keys match nothing. Useful to shop\nonly the books you hold accounts at.\n\nEach line in the response carries a `sides` dict mapping side name\n(e.g. \"Over\"/\"Under\" or team names) to the best price across all\nbooks, plus an `all_prices` array sorted best-first so consumers\ncan render runner-ups without a second request.","operationId":"get_event_best_line_v1_sports__sport_key__events__event_id__best_line_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Markets"}},{"name":"bookmakers","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param.","title":"Bookmakers"},"description":"Comma-separated bookmaker keys (e.g. 'draftkings,fanduel'). Omitted = all books. Matches the-odds-api's `bookmakers` param."},{"name":"includeLinks","in":"query","required":false,"schema":{"type":"boolean","description":"When true, every price row carries a `link` — that book's public event-page URL, the click-out for 'go bet this'. Books without a verified URL template return null. Links appear on free-tier redacted responses too (navigation isn't the paid data).","default":false,"title":"Includelinks"},"description":"When true, every price row carries a `link` — that book's public event-page URL, the click-out for 'go bet this'. Books without a verified URL template return null. Links appear on free-tier redacted responses too (navigation isn't the paid data)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventBestLineOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/clv/grade":{"post":{"tags":["CLV"],"summary":"Grade Clv","description":"Grade placed bets against their closing lines.","operationId":"grade_clv_v1_clv_grade_post","requestBody":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ClvBetIn"},"type":"array","title":"Bets","description":"Placed bets to grade."}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClvGradeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}]}},"/v1/sports/{sport_key}/scores":{"get":{"tags":["Scores & Results"],"summary":"List Scores","description":"Game scores and status for recent events (last N days).\nFree tier — no Pro required.","operationId":"list_scores_v1_sports__sport_key__scores_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"days_from","in":"query","required":false,"schema":{"type":"integer","default":3,"title":"Days From"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScoreOut"},"title":"Response List Scores V1 Sports  Sport Key  Scores Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/baseball_mlb/grand-salami":{"get":{"tags":["Scores & Results"],"summary":"Mlb Grand Salami","description":"Daily \"Grand Salami\" — total runs across all MLB games for a given UTC\ndate. No book retails this as a single market, so we synthesize the\nline from each book's primary game totals and pair it with the actual\ntotal runs scored once the slate completes.\n\nDefault: today (UTC). Pass ?date=YYYY-MM-DD for a historical day.\nFree tier — no auth gating beyond the standard API key.","operationId":"mlb_grand_salami_v1_sports_baseball_mlb_grand_salami_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"date","in":"query","required":false,"schema":{"type":"string","default":"","title":"Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrandSalamiOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/hockey_nhl/daily-goals-total":{"get":{"tags":["Scores & Results"],"summary":"Nhl Daily Goals Total","description":"Daily NHL goals total — total goals scored across every NHL game for a\ngiven UTC date (incl. OT/SO), plus each book's implied \"Daily Goals\nTotal\" line (sum of per-game primary totals). No retail book quotes\nthis as a single market.\n\nDefault: today (UTC). Pass ?date=YYYY-MM-DD for a historical day.\nFree tier — no auth gating beyond the standard API key.","operationId":"nhl_daily_goals_total_v1_sports_hockey_nhl_daily_goals_total_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"date","in":"query","required":false,"schema":{"type":"string","default":"","title":"Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyGoalsTotalOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/stats":{"get":{"tags":["Scores & Results"],"summary":"Get Event Stats","description":"Actual player/team stats from box scores (book-agnostic).\nUse these to resolve props against any sportsbook's lines.\nFree tier — no Pro required.","operationId":"get_event_stats_v1_sports__sport_key__events__event_id__stats_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"stat_type","in":"query","required":false,"schema":{"type":"string","default":"","title":"Stat Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventStatsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/events/{event_id}/results":{"get":{"tags":["Scores & Results"],"summary":"Get Event Results","description":"Resolved prop outcomes with actual player stats.\nPaid tiers (Hobby / Pro / Streaming Lite / Streaming / Enterprise):\nfull resolution data. Free tier: 403 — this is a moat feature\nvs the-odds-api and isn't part of the free surface.","operationId":"get_event_results_v1_sports__sport_key__events__event_id__results_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"markets","in":"query","required":false,"schema":{"type":"string","default":"","title":"Markets"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResultOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/players/{player_name}/history":{"get":{"tags":["Players"],"summary":"Get Player History","description":"Resolved prop history for a player in a given market.\n\nReturns one entry per (event, bookmaker) pair with line + prices +\nresolution + actual value.\n\nPaid tiers (Hobby / Pro / Streaming Lite / Streaming / Enterprise):\nfull data. Free tier: structure only — resolution + actual_value\nredacted.","operationId":"get_player_history_v1_sports__sport_key__players__player_name__history_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"player_name","in":"path","required":true,"schema":{"type":"string","title":"Player Name"}},{"name":"market","in":"query","required":true,"schema":{"type":"string","description":"Market key, e.g. pitcher_strikeouts","title":"Market"},"description":"Market key, e.g. pitcher_strikeouts"},{"name":"bookmaker","in":"query","required":false,"schema":{"type":"string","description":"Optional bookmaker filter","default":"","title":"Bookmaker"},"description":"Optional bookmaker filter"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayerHistoryOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/players/{player_name}/trends":{"get":{"tags":["Players"],"summary":"Get Player Trends","description":"Aggregated hit-rate trends for a player — \"did X go over in N of his\nlast M games?\" — across every market they have graded history in.\n\nFor each market we report over/under/push splits across the last\n5 / 10 / 20 / 50 graded games, the current over/under streak, average\nactual stat, and the most recent line. The over/under verdict each\ngame compares the player's real stat (book-agnostic) against one\nreference book's posted line.\n\nDerived entirely from PropLine's prop resolution — the-odds-api has\nno equivalent. Paid tiers (Hobby+): full data. Free tier: market list\n+ graded-game counts, with the rates redacted.","operationId":"get_player_trends_v1_sports__sport_key__players__player_name__trends_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"player_name","in":"path","required":true,"schema":{"type":"string","title":"Player Name"}},{"name":"market","in":"query","required":false,"schema":{"type":"string","description":"Optional market key to filter to one market","default":"","title":"Market"},"description":"Optional market key to filter to one market"},{"name":"dfs_odds_type","in":"query","required":false,"schema":{"type":"string","description":"Optional DFS pick-em flavor filter (PrizePicks): 'standard', 'goblin', or 'demon'. When set, trends are computed against that flavor's PrizePicks line only — e.g. compare a player's goblin-line hit-rate vs his standard-line trend. Omitted = cross-book behavior (reference line from the preferred-book list, flavor ignored).","default":"","title":"Dfs Odds Type"},"description":"Optional DFS pick-em flavor filter (PrizePicks): 'standard', 'goblin', or 'demon'. When set, trends are computed against that flavor's PrizePicks line only — e.g. compare a player's goblin-line hit-rate vs his standard-line trend. Omitted = cross-book behavior (reference line from the preferred-book list, flavor ignored)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayerTrendsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sports/{sport_key}/players/{player_name}/games":{"get":{"tags":["Players"],"summary":"Get Player Game Log","description":"A player's recent games with every raw box-score stat per game.\n\nOne call replaces one request per event. Free tier, like /stats — this is\nthe same book-agnostic box-score data, batched by player instead of by\nevent, and carries no line, price or grade.\n\nPass `opponent=` for head-to-head. History reaches as far back as the\narchive holds for that sport (see /docs#stats); it is not capped to the\ncurrent season.","operationId":"get_player_game_log_v1_sports__sport_key__players__player_name__games_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport_key","in":"path","required":true,"schema":{"type":"string","title":"Sport Key"}},{"name":"player_name","in":"path","required":true,"schema":{"type":"string","title":"Player Name"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"opponent","in":"query","required":false,"schema":{"type":"string","description":"Filter to games against this opponent (H2H). Team name or abbreviation.","default":"","title":"Opponent"},"description":"Filter to games against this opponent (H2H). Team name or abbreviation."},{"name":"stat_type","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated stat names to return; omit for all.","default":"","title":"Stat Type"},"description":"Comma-separated stat names to return; omit for all."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayerGameLogOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/exports/resolved-props":{"get":{"tags":["Exports"],"summary":"Export Resolved Props","description":"Stream resolved prop outcomes as CSV. Pro+ tier required.\n\nOne row per (event, market, bookmaker, outcome). Includes the line,\nprice, resolution (won/lost/push/void), actual stat value, AND the\nclosing line (`closing_price` / `closing_at` — the last snapshot at or\nbefore commence_time) — the exact data model builders need for CLV and\nbacktesting, and something the-odds-api cannot offer since they don't\nresolve props.\n\nHistorical depth is tier-gated: Pro = last 90 days, Streaming = last\n365 days, Enterprise = unbounded. The effective floor is reflected in\nthe `X-PropLine-Export-Window-Start` response header.\n\nArchive coverage is stated in-band: `X-PropLine-Archive-Starts`\ncarries the sport's earliest graded date (`none` if the sport has no\ngraded data yet — e.g. NFL before its first 2026 game), and\n`X-PropLine-Archive-Notice` is set when the requested window ends\nbefore the archive begins, meaning the export can only be empty.","operationId":"export_resolved_props_v1_exports_resolved_props_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport","in":"query","required":true,"schema":{"type":"string","description":"Sport key (e.g. baseball_mlb). Required.","title":"Sport"},"description":"Sport key (e.g. baseball_mlb). Required."},{"name":"market","in":"query","required":false,"schema":{"type":"string","description":"Optional market filter, e.g. pitcher_strikeouts","default":"","title":"Market"},"description":"Optional market filter, e.g. pitcher_strikeouts"},{"name":"bookmaker","in":"query","required":false,"schema":{"type":"string","description":"Optional bookmaker filter","default":"","title":"Bookmaker"},"description":"Optional bookmaker filter"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO datetime lower bound on resolved_at","title":"Since"},"description":"ISO datetime lower bound on resolved_at"},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO datetime upper bound on resolved_at","title":"Until"},"description":"ISO datetime upper bound on resolved_at"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/exports/odds-history":{"get":{"tags":["Exports"],"summary":"Export Odds History","description":"Stream the full line-movement time-series as CSV — every recorded odds\nsnapshot (price + point, per book) for every outcome, not just the\nclosing line. One row per (outcome, snapshot).\n\nThis is the raw tick history that **no subscription tier can pull in\nbulk**: Pro/Streaming get per-event `/odds/history` and the\nresolved-props export (closing line only), but the bulk snapshot\nfirehose is exclusive to the one-time Historical Backfill pass and\nEnterprise. Backfill pass = trailing 2-year lookback (Enterprise\nunbounded); uncapped calls.\n\nA full all-sport, all-history pull is many GB — page month-by-month\nwith `since`/`until` to keep any single FILE a size you can handle.\n(The DB side no longer needs the help: the export runs one short\nstatement per 6-hour slice regardless of the window you ask for.)\n\nArchive coverage is stated in-band: `X-PropLine-Archive-Starts`\ncarries the sport's earliest recorded date (`none` if no data yet),\nand `X-PropLine-Archive-Notice` is set when the requested window\nends before the archive begins, meaning the export can only be empty.","operationId":"export_odds_history_v1_exports_odds_history_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"sport","in":"query","required":true,"schema":{"type":"string","description":"Sport key (e.g. baseball_mlb). Required.","title":"Sport"},"description":"Sport key (e.g. baseball_mlb). Required."},{"name":"market","in":"query","required":false,"schema":{"type":"string","description":"Optional market filter, e.g. pitcher_strikeouts","default":"","title":"Market"},"description":"Optional market filter, e.g. pitcher_strikeouts"},{"name":"bookmaker","in":"query","required":false,"schema":{"type":"string","description":"Optional bookmaker filter","default":"","title":"Bookmaker"},"description":"Optional bookmaker filter"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO datetime lower bound on recorded_at","title":"Since"},"description":"ISO datetime lower bound on recorded_at"},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO datetime upper bound on recorded_at","title":"Until"},"description":"ISO datetime upper bound on recorded_at"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/exports/sample":{"get":{"tags":["Exports"],"summary":"Export Sample","description":"Public sample: last 7 days of MLB pitcher_strikeouts as CSV.\n\nNo auth required — this is a SEO/marketing lead magnet. Capped to\nkeep it a taste, not a full dataset. For full access, Pro tier\nusers hit /v1/exports/resolved-props.","operationId":"export_sample_v1_exports_sample_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/markets/hit-rates":{"get":{"tags":["Analytics"],"summary":"Get Market Hit Rates","description":"Per-market daily Over hit rates over the last N days.\n\nResponse shape:\n    {\n      \"days\": 28,\n      \"bookmaker\": \"bovada\",\n      \"markets\": {\n        \"pitcher_strikeouts\": [\n          {\"date\": \"2026-04-01\", \"total\": 14, \"won\": 6},\n          ...\n        ],\n        \"batter_total_bases\": [...],\n        ...\n      }\n    }\n\n`total` and `won` are scoped to graded **Over** outcomes only — the\nsame denominator the cross-sport accuracy panel uses, so the numbers\nline up. `total` excludes voids; `won` is the subset where the actual\nstat exceeded the line.","operationId":"get_market_hit_rates_v1_markets_hit_rates_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":60,"minimum":1,"description":"Look-back window in days","default":28,"title":"Days"},"description":"Look-back window in days"},{"name":"bookmaker","in":"query","required":false,"schema":{"type":"string","description":"Bookmaker to aggregate. Defaults to bovada — the canonical book for /today.","default":"bovada","title":"Bookmaker"},"description":"Bookmaker to aggregate. Defaults to bovada — the canonical book for /today."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/markets/resolution-summary":{"get":{"tags":["Analytics"],"summary":"Get Resolution Summary","description":"Factual volume of graded player props over the last N days.\n\nAggregated counts only (no individual prop data) — same public-safe\nposture as /markets/hit-rates. NOTE: like every new /v1 route this is\npart of the public API contract and must be propagated to all the\nsurfaces in CLAUDE.md's \"Adding a public API endpoint\" checklist\n(docs page, recipes, OpenAPI, RapidAPI, llms.txt/full, Python/Node/\nMCP/CLI). There is no \"showcase endpoint\" exemption.\n\nThe point is the moat claim the-odds-api / OddsJam can't make at any\ntier: every one of these outcomes was graded against the real box\nscore. This is a *volume* statement, never a profitability one.\n\nResponse:\n    {\n      \"days\": 30,\n      \"total_graded\": 812334,   # resolution set (incl. void)\n      \"total_settled\": 798901,  # won/lost/push (excl. void)\n      \"events_graded\": 4120,\n      \"sports_covered\": 33,\n      \"by_sport\": [{\"sport_key\",\"title\",\"graded\",\"events\"}...],\n      \"top_markets\": [{\"market_key\",\"graded\"}...]   # top 12\n    }","operationId":"get_resolution_summary_v1_markets_resolution_summary_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"description":"Look-back window in days","default":30,"title":"Days"},"description":"Look-back window in days"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/dfs/payouts":{"get":{"tags":["DFS"],"summary":"Dfs Payouts","description":"PrizePicks Power/Flex payout schedule + per-leg breakeven win probability.\n\nPass `?leg_win_prob=0.58` to also get the expected return and +EV flag for\neach play type and leg count at that assumed hit rate. See the `disclaimer`\nfield: these are standard published payouts (demon/goblin per-pick modifiers\nare not in PrizePicks's feed), and breakeven assumes independent legs.","operationId":"dfs_payouts_v1_dfs_payouts_get","security":[{"APIKeyHeader":[]},{"APIKeyQuery":[]}],"parameters":[{"name":"platform","in":"query","required":false,"schema":{"type":"string","description":"DFS platform. Only 'prizepicks' today.","default":"prizepicks","title":"Platform"},"description":"DFS platform. Only 'prizepicks' today."},{"name":"leg_win_prob","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"description":"Optional. Assumed per-leg win probability. When supplied, each play also returns expected_return (per $1) and is_plus_ev at that rate.","title":"Leg Win Prob"},"description":"Optional. Assumed per-leg win probability. When supplied, each play also returns expected_return (per $1) and is_plus_ev at that rate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DfsPayoutsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/freshness":{"get":{"tags":["Status"],"summary":"Public Freshness","description":"Per-bookmaker freshness — `last_update` summary across all markets.\n\nReturns:\n    bookmakers: [\n      { key, market_count, latest_update, staleness_seconds, is_stale,\n        worst_staleness_seconds, suspended_market_count,\n        market_classes: {\n          game_lines: { market_count, latest_update, staleness_seconds,\n                        active_market_count, oldest_market_update,\n                        worst_staleness_seconds, suspended_market_count },\n          props:      { ...same shape },\n        } }\n    ]\n    stale_threshold_seconds\n    as_of (server time the rows were sampled)\n\n`staleness_seconds` is the time since the most recent successful\nmarket write for the book — a rough proxy for \"how fresh is the\nfreshest line on this book.\" It overstates per-event freshness\nbecause any single market touch resets it; for the marketing page\nthat's fine since the public claim we're backing is \"we ingest\nbook data continuously and recently.\"\n\n`market_classes` splits that per class (game lines vs props) so a class\ngoing dark behind fresh game lines — the Pinnacle 2026-08-02 prop\nincident — is visible here too. Single grouped query, no Event join, so\nunlike the monitor's query this split does NOT exclude futures markets\n(they land under `props` and can keep it looking fresher than the\nper-game prop board really is) — acceptable for a trust surface.\n\nA third `futures` class was considered (sportsapis.dev review follow-up,\n2026-08-27) and deliberately NOT added, for two reasons that compound:\n(1) `futures` is an `Event.is_future` property, not a `Market.key`\nproperty, so `market_class_case()` — which buckets on `Market.key` alone\nand is SHARED with the monitor — cannot emit it without an Event join in\nevery caller. And the monitor (`sport_book_class_freshness_rows`)\ndeliberately EXCLUDES futures so a year-round-fresh outright can't mask a\ndark prop parse, so it can never carry a futures class: \"keep the\nvocabulary shared with the monitor\" and \"add a futures class\" are\nmutually exclusive on the same shared expression. (2) Splitting futures\nout of props *correctly* (props excluding futures) forces an Event join\ninto THIS first query, which is deliberately join-free and spans every\nmarket in the DB — not the bounded active-board window the ~167ms cost\nwas measured on. The worst-case fields (`worst_staleness_seconds` et al.)\nALREADY exclude futures via the active-board Event join, so the only\nresidual is a mildly inflated headline `props` count/latest on a trust\npage — already noted as acceptable above. Net: high coupling + unbounded\ncost to fix a cosmetic inflation. Skipped on purpose.\n\nEach class (and the book) also carries the WORST case:\n`worst_staleness_seconds` / `oldest_market_update` — the age of the\noldest NON-SUSPENDED market on the active board (events from -6h to\n+48h) — plus `active_market_count` and `suspended_market_count`.\nHeadline staleness answers \"is the book being ingested\"; worst-case\nanswers \"is any individual market being silently missed\". A market\nwith `suspended_at` set is excluded from the worst-case number because\na flagged withdrawal is not a capture hole (the book pulled it; we\nkeep its last price and say so on /odds). Second grouped query with an\nEvent join, bounded by the active-board window.","operationId":"public_freshness_v1_freshness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","description":"Liveness check. Accepts both GET and HEAD because external uptime\nmonitors (UptimeRobot, BetterStack, etc.) default to HEAD, which a\nplain `@app.get` decorator returns 405 for. Body is identical for\nGET; HEAD just gets the headers + 200.","operationId":"health_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"head":{"summary":"Health","description":"Liveness check. Accepts both GET and HEAD because external uptime\nmonitors (UptimeRobot, BetterStack, etc.) default to HEAD, which a\nplain `@app.get` decorator returns 405 for. Body is identical for\nGET; HEAD just gets the headers + 200.","operationId":"health_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"BestLineOut":{"properties":{"market_key":{"type":"string","title":"Market Key"},"description":{"type":"string","title":"Description"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"sides":{"additionalProperties":{"$ref":"#/components/schemas/BestLineSideOut"},"type":"object","title":"Sides"}},"type":"object","required":["market_key","description","point","sides"],"title":"BestLineOut","description":"One (market_key, player, point) tuple with the best price per side."},"BestLineSideOut":{"properties":{"best":{"$ref":"#/components/schemas/BestPriceOut"},"all_prices":{"items":{"$ref":"#/components/schemas/BestPriceOut"},"type":"array","title":"All Prices"}},"type":"object","required":["best","all_prices"],"title":"BestLineSideOut","description":"Best price + every alternative for one side of a market line.\n\n`best` is the highest American price across the books returning a\nvalid quote for this side. `all_prices` is the same set sorted\nbest-first (one row per book), so consumers can show runner-ups\nwithout a second request. DFS pick'em books (PrizePicks, Sleeper,\nDabble) are excluded — their quotes aren't independently bettable\npayouts; Underdog is included only at its clean two-way lines\n(payout_multiplier == 1.0), same rule as /ev."},"BestPriceOut":{"properties":{"book":{"type":"string","title":"Book"},"book_title":{"type":"string","title":"Book Title"},"price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price"},"last_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Update"},"link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Link"},"app_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Link"},"liquidity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Liquidity"},"liquidity_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Liquidity Updated At"}},"type":"object","required":["book","book_title","price"],"title":"BestPriceOut","description":"A single book's price at a given line. Used in best-line responses."},"BookmakerHistoryOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"markets":{"items":{"$ref":"#/components/schemas/MarketHistoryOut"},"type":"array","title":"Markets"}},"type":"object","required":["key","title","markets"],"title":"BookmakerHistoryOut"},"BookmakerOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"last_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Update"},"link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Link"},"app_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Link"},"pregame_only":{"type":"boolean","title":"Pregame Only","default":false},"book_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Book Event Id"},"markets":{"items":{"$ref":"#/components/schemas/MarketOut"},"type":"array","title":"Markets"}},"type":"object","required":["key","title","markets"],"title":"BookmakerOut"},"BookmakerResultOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"markets":{"items":{"$ref":"#/components/schemas/ResolvedMarketOut"},"type":"array","title":"Markets"}},"type":"object","required":["key","title","markets"],"title":"BookmakerResultOut"},"ClosingBookmakerOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"markets":{"items":{"$ref":"#/components/schemas/ClosingMarketOut"},"type":"array","title":"Markets"}},"type":"object","required":["key","title","markets"],"title":"ClosingBookmakerOut"},"ClosingMarketOut":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team"},"outcomes":{"items":{"$ref":"#/components/schemas/ClosingOutcomeOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["key","description","outcomes"],"title":"ClosingMarketOut"},"ClosingOutcomeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"closing_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closing At"},"closing_age_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Closing Age Seconds"},"is_stale":{"type":"boolean","title":"Is Stale","default":false},"book_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Book Updated At"},"book_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Book Version"},"opening_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Opening Price"},"opening_point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Opening Point"},"opening_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Opening At"},"opening_age_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Opening Age Seconds"},"redacted":{"type":"boolean","title":"Redacted","default":false},"dfs_odds_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dfs Odds Type"}},"type":"object","required":["name","description","price","point"],"title":"ClosingOutcomeOut"},"ClvBetIn":{"properties":{"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"},"sport_key":{"type":"string","title":"Sport Key"},"event_id":{"type":"integer","title":"Event Id"},"market":{"type":"string","title":"Market"},"bookmaker":{"type":"string","title":"Bookmaker"},"selection":{"type":"string","title":"Selection"},"side":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Side"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"price":{"type":"integer","title":"Price"},"stake":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Stake"}},"type":"object","required":["sport_key","event_id","market","bookmaker","selection","price"],"title":"ClvBetIn","description":"One placed bet to be graded against its closing line."},"ClvGradeResponse":{"properties":{"summary":{"$ref":"#/components/schemas/ClvSummaryOut"},"bets":{"items":{"$ref":"#/components/schemas/ClvGradedOut"},"type":"array","title":"Bets"},"redacted":{"type":"boolean","title":"Redacted","default":false},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["summary","bets"],"title":"ClvGradeResponse"},"ClvGradedOut":{"properties":{"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"},"sport_key":{"type":"string","title":"Sport Key"},"event_id":{"type":"integer","title":"Event Id"},"market":{"type":"string","title":"Market"},"bookmaker":{"type":"string","title":"Bookmaker"},"selection":{"type":"string","title":"Selection"},"side":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Side"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"price":{"type":"integer","title":"Price"},"stake":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Stake"},"matched":{"type":"boolean","title":"Matched","default":false},"unmatched_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unmatched Reason"},"closing_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Closing Price"},"closing_point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Closing Point"},"closing_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closing At"},"closing_is_stale":{"type":"boolean","title":"Closing Is Stale","default":false},"closing_fair_prob":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Closing Fair Prob"},"fair_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fair Source"},"closing_is_final":{"type":"boolean","title":"Closing Is Final","default":false},"clv_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Clv Pct"},"ev_vs_close_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ev Vs Close Pct"},"beat_close":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Beat Close"},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"actual_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Value"}},"type":"object","required":["sport_key","event_id","market","bookmaker","selection","price"],"title":"ClvGradedOut"},"ClvSummaryOut":{"properties":{"bets":{"type":"integer","title":"Bets"},"matched":{"type":"integer","title":"Matched"},"unmatched":{"type":"integer","title":"Unmatched"},"graded":{"type":"integer","title":"Graded"},"pending":{"type":"integer","title":"Pending","default":0},"avg_clv_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Clv Pct"},"avg_ev_vs_close_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Ev Vs Close Pct"},"beat_close_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Beat Close Pct"},"profit_units":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Profit Units"}},"type":"object","required":["bets","matched","unmatched","graded"],"title":"ClvSummaryOut"},"DailyGoalsTotalBookOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"games_priced":{"type":"integer","title":"Games Priced"},"line":{"type":"number","title":"Line"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"}},"type":"object","required":["key","title","games_priced","line"],"title":"DailyGoalsTotalBookOut"},"DailyGoalsTotalOut":{"properties":{"sport_key":{"type":"string","title":"Sport Key"},"date":{"type":"string","title":"Date"},"games_total":{"type":"integer","title":"Games Total"},"games_completed":{"type":"integer","title":"Games Completed"},"games_in_progress":{"type":"integer","title":"Games In Progress"},"games_upcoming":{"type":"integer","title":"Games Upcoming"},"actual_total_goals":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Actual Total Goals"},"bookmakers":{"items":{"$ref":"#/components/schemas/DailyGoalsTotalBookOut"},"type":"array","title":"Bookmakers"}},"type":"object","required":["sport_key","date","games_total","games_completed","games_in_progress","games_upcoming","actual_total_goals","bookmakers"],"title":"DailyGoalsTotalOut"},"DfsPayoutTierOut":{"properties":{"correct":{"type":"integer","title":"Correct"},"multiplier":{"type":"number","title":"Multiplier"}},"type":"object","required":["correct","multiplier"],"title":"DfsPayoutTierOut"},"DfsPayoutsOut":{"properties":{"platform":{"type":"string","title":"Platform"},"leg_win_prob":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Leg Win Prob"},"disclaimer":{"type":"string","title":"Disclaimer"},"plays":{"items":{"$ref":"#/components/schemas/DfsPlayPayoutOut"},"type":"array","title":"Plays"}},"type":"object","required":["platform","disclaimer","plays"],"title":"DfsPayoutsOut"},"DfsPlayPayoutOut":{"properties":{"play_type":{"type":"string","title":"Play Type"},"legs":{"type":"integer","title":"Legs"},"all_correct_multiplier":{"type":"number","title":"All Correct Multiplier"},"payouts":{"items":{"$ref":"#/components/schemas/DfsPayoutTierOut"},"type":"array","title":"Payouts"},"breakeven_leg_win_prob":{"type":"number","title":"Breakeven Leg Win Prob"},"expected_return":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Expected Return"},"is_plus_ev":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Plus Ev"}},"type":"object","required":["play_type","legs","all_correct_multiplier","payouts","breakeven_leg_win_prob"],"title":"DfsPlayPayoutOut"},"EvCalcOut":{"properties":{"market":{"type":"string","title":"Market"},"name":{"type":"string","title":"Name"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"description":{"type":"string","title":"Description"},"price":{"type":"integer","title":"Price"},"fair_source":{"type":"string","title":"Fair Source"},"fair_prob":{"type":"number","title":"Fair Prob"},"implied_prob":{"type":"number","title":"Implied Prob"},"ev_pct":{"type":"number","title":"Ev Pct"},"is_plus_ev":{"type":"boolean","title":"Is Plus Ev"}},"type":"object","required":["market","name","point","description","price","fair_source","fair_prob","implied_prob","ev_pct","is_plus_ev"],"title":"EvCalcOut","description":"User-supplied price evaluated against the event's no-vig fair anchor."},"EvLineOut":{"properties":{"market_key":{"type":"string","title":"Market Key"},"description":{"type":"string","title":"Description"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"fair_source":{"type":"string","title":"Fair Source"},"fair_probs":{"additionalProperties":{"type":"number"},"type":"object","title":"Fair Probs"},"outcomes":{"items":{"$ref":"#/components/schemas/EvOutcomeOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["market_key","description","point","fair_source","fair_probs","outcomes"],"title":"EvLineOut"},"EvOutcomeOut":{"properties":{"book":{"type":"string","title":"Book"},"book_title":{"type":"string","title":"Book Title"},"name":{"type":"string","title":"Name"},"price":{"type":"integer","title":"Price"},"ev_pct":{"type":"number","title":"Ev Pct"},"is_plus_ev":{"type":"boolean","title":"Is Plus Ev"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"}},"type":"object","required":["book","book_title","name","price","ev_pct","is_plus_ev"],"title":"EvOutcomeOut"},"EventBestLineOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"books_considered":{"items":{"type":"string"},"type":"array","title":"Books Considered"},"lines":{"items":{"$ref":"#/components/schemas/BestLineOut"},"type":"array","title":"Lines"},"redacted":{"type":"boolean","title":"Redacted","default":false},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","books_considered","lines"],"title":"EventBestLineOut","description":"Cross-book best-line response for one event."},"EventClosingOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"bookmakers":{"items":{"$ref":"#/components/schemas/ClosingBookmakerOut"},"type":"array","title":"Bookmakers"},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","bookmakers"],"title":"EventClosingOut"},"EventEvOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"fair_source_default":{"type":"string","title":"Fair Source Default"},"lines":{"items":{"$ref":"#/components/schemas/EvLineOut"},"type":"array","title":"Lines"},"redacted":{"type":"boolean","title":"Redacted","default":false},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","fair_source_default","lines"],"title":"EventEvOut"},"EventHistoryOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"live":{"type":"boolean","title":"Live","default":false},"bookmakers":{"items":{"$ref":"#/components/schemas/BookmakerHistoryOut"},"type":"array","title":"Bookmakers"},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","bookmakers"],"title":"EventHistoryOut"},"EventMovementOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"bookmakers":{"items":{"$ref":"#/components/schemas/MovementBookmakerOut"},"type":"array","title":"Bookmakers"},"steam":{"items":{"$ref":"#/components/schemas/SteamMoveOut"},"type":"array","title":"Steam"},"redacted":{"type":"boolean","title":"Redacted","default":false},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","bookmakers","steam"],"title":"EventMovementOut"},"EventOddsOut":{"properties":{"home_team_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team Key"},"away_team_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team Key"},"home_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team Id"},"away_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team Id"},"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"live":{"type":"boolean","title":"Live","default":false},"last_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Update"},"merged_from_event_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Merged From Event Ids"},"bookmakers":{"items":{"$ref":"#/components/schemas/BookmakerOut"},"type":"array","title":"Bookmakers"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","bookmakers"],"title":"EventOddsOut"},"EventOut":{"properties":{"home_team_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team Key"},"away_team_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team Key"},"home_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team Id"},"away_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team Id"},"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"live":{"type":"boolean","title":"Live","default":false},"merged_from_event_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Merged From Event Ids"},"bookmakers":{"anyOf":[{"items":{"$ref":"#/components/schemas/BookmakerOut"},"type":"array"},{"type":"null"}],"title":"Bookmakers"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time"],"title":"EventOut"},"EventProjectionsOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"method":{"type":"string","title":"Method"},"projections":{"items":{"$ref":"#/components/schemas/ProjectionRowOut"},"type":"array","title":"Projections"},"redacted":{"type":"boolean","title":"Redacted","default":false},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","method","projections"],"title":"EventProjectionsOut"},"EventResultOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"live":{"type":"boolean","title":"Live","default":false},"status":{"type":"string","title":"Status"},"home_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score"},"away_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score"},"bookmakers":{"items":{"$ref":"#/components/schemas/BookmakerResultOut"},"type":"array","title":"Bookmakers"},"context":{"anyOf":[{"$ref":"#/components/schemas/GameContextOut"},{"type":"null"}]},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","status","home_score","away_score","bookmakers"],"title":"EventResultOut"},"EventStatsOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"status":{"type":"string","title":"Status"},"home_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score"},"away_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score"},"stats":{"items":{"$ref":"#/components/schemas/PlayerStatOut"},"type":"array","title":"Stats"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","status","home_score","away_score","stats"],"title":"EventStatsOut"},"FuturesEventOut":{"properties":{"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"title":{"type":"string","title":"Title"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"markets":{"items":{"$ref":"#/components/schemas/FuturesMarketOut"},"type":"array","title":"Markets"}},"type":"object","required":["id","sport_key","title","commence_time","markets"],"title":"FuturesEventOut"},"FuturesMarketOut":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description"},"bookmaker":{"type":"string","title":"Bookmaker"},"bookmaker_title":{"type":"string","title":"Bookmaker Title"},"last_update":{"type":"string","format":"date-time","title":"Last Update"},"book_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Book Updated At"},"outcomes":{"items":{"$ref":"#/components/schemas/FuturesOutcomeOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["key","description","bookmaker","bookmaker_title","last_update","outcomes"],"title":"FuturesMarketOut"},"FuturesOutcomeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description","default":""},"price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price"},"price_decimal":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price Decimal"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"}},"type":"object","required":["name","price","price_decimal"],"title":"FuturesOutcomeOut"},"GameContextOut":{"properties":{"event_id":{"type":"string","title":"Event Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"venue":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Venue"},"roof_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Roof Type"},"is_indoor":{"type":"boolean","title":"Is Indoor","default":false},"home_probable_pitcher":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Probable Pitcher"},"away_probable_pitcher":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Probable Pitcher"},"home_probable_pitcher_hand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Probable Pitcher Hand"},"away_probable_pitcher_hand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Probable Pitcher Hand"},"lineup_confirmed":{"type":"boolean","title":"Lineup Confirmed","default":false},"home_plate_umpire":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Plate Umpire"},"weather":{"anyOf":[{"$ref":"#/components/schemas/WeatherOut"},{"type":"null"}]},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["event_id","sport_key","home_team","away_team","commence_time"],"title":"GameContextOut","description":"Conditions a game is played under — the context every prop settles\nagainst. Free tier. MLB today; weather extends to other outdoor\nsports next."},"GrandSalamiBookOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"games_priced":{"type":"integer","title":"Games Priced"},"line":{"type":"number","title":"Line"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"}},"type":"object","required":["key","title","games_priced","line"],"title":"GrandSalamiBookOut"},"GrandSalamiOut":{"properties":{"sport_key":{"type":"string","title":"Sport Key"},"date":{"type":"string","title":"Date"},"games_total":{"type":"integer","title":"Games Total"},"games_completed":{"type":"integer","title":"Games Completed"},"games_in_progress":{"type":"integer","title":"Games In Progress"},"games_upcoming":{"type":"integer","title":"Games Upcoming"},"actual_total_runs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Actual Total Runs"},"bookmakers":{"items":{"$ref":"#/components/schemas/GrandSalamiBookOut"},"type":"array","title":"Bookmakers"}},"type":"object","required":["sport_key","date","games_total","games_completed","games_in_progress","games_upcoming","actual_total_runs","bookmakers"],"title":"GrandSalamiOut"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HitRateSplitOut":{"properties":{"window":{"type":"integer","title":"Window"},"games":{"type":"integer","title":"Games"},"over":{"type":"integer","title":"Over"},"under":{"type":"integer","title":"Under"},"push":{"type":"integer","title":"Push"},"over_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Over Pct"}},"type":"object","required":["window","games","over","under","push","over_pct"],"title":"HitRateSplitOut","description":"Over/under split across a fixed look-back window of graded games.\n\n`over_pct` is over / (over + under) — pushes are excluded from the\ndenominator (standard hit-rate convention). None when the window has\nno decisive (non-push) games."},"MarketHistoryOut":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team"},"outcomes":{"items":{"$ref":"#/components/schemas/OutcomeHistoryOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["key","description","outcomes"],"title":"MarketHistoryOut"},"MarketOut":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description","default":""},"last_update":{"type":"string","format":"date-time","title":"Last Update"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"suspended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suspended At"},"team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team"},"outcomes":{"items":{"$ref":"#/components/schemas/OutcomeOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["key","last_update","outcomes"],"title":"MarketOut"},"MovementBookmakerOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"markets":{"items":{"$ref":"#/components/schemas/MovementMarketOut"},"type":"array","title":"Markets"}},"type":"object","required":["key","title","markets"],"title":"MovementBookmakerOut"},"MovementMarketOut":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description","default":""},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team"},"outcomes":{"items":{"$ref":"#/components/schemas/MovementOutcomeOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["key","outcomes"],"title":"MovementMarketOut"},"MovementOutcomeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"open_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Open Price"},"open_point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Open Point"},"open_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Open At"},"latest_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Latest Price"},"latest_point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latest Point"},"latest_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Latest At"},"prob_shift":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prob Shift"},"point_shift":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point Shift"},"direction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Direction"},"num_snapshots":{"type":"integer","title":"Num Snapshots","default":0},"redacted":{"type":"boolean","title":"Redacted","default":false},"dfs_odds_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dfs Odds Type"}},"type":"object","required":["name"],"title":"MovementOutcomeOut"},"OddsSnapshotOut":{"properties":{"price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"recorded_at":{"type":"string","format":"date-time","title":"Recorded At"},"book_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Book Updated At"},"book_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Book Version"}},"type":"object","required":["price","point","recorded_at"],"title":"OddsSnapshotOut"},"OutcomeHistoryOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"snapshots":{"items":{"$ref":"#/components/schemas/OddsSnapshotOut"},"type":"array","title":"Snapshots"},"snapshots_available":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Snapshots Available"},"redacted":{"type":"boolean","title":"Redacted","default":false},"dfs_odds_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dfs Odds Type"}},"type":"object","required":["name","description","snapshots"],"title":"OutcomeHistoryOut"},"OutcomeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"book_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Book Updated At"},"book_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Book Version"},"payout_multiplier":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Payout Multiplier"},"dfs_odds_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dfs Odds Type"},"last_change_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Change At"},"liquidity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Liquidity"},"liquidity_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Liquidity Updated At"},"line_gap":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Line Gap"},"book_outcome_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Book Outcome Id"},"player_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player Id"}},"type":"object","required":["name","description","price","point"],"title":"OutcomeOut"},"PlayerGameLogOut":{"properties":{"player_name":{"type":"string","title":"Player Name"},"sport_key":{"type":"string","title":"Sport Key"},"opponent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opponent"},"games":{"items":{"$ref":"#/components/schemas/PlayerGameOut"},"type":"array","title":"Games"}},"type":"object","required":["player_name","sport_key","opponent","games"],"title":"PlayerGameLogOut"},"PlayerGameOut":{"properties":{"event_id":{"type":"string","title":"Event Id"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"status":{"type":"string","title":"Status"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"home_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score"},"away_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score"},"team_abbr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Abbr"},"player_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player Team"},"opponent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opponent"},"is_home":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Home"},"stats":{"additionalProperties":{"type":"number"},"type":"object","title":"Stats"}},"type":"object","required":["event_id","commence_time","status","home_team","away_team","home_score","away_score","team_abbr","player_team","opponent","is_home","stats"],"title":"PlayerGameOut","description":"One completed game in a player's game log.\n\n`stats` is a flat map of every stat_type recorded for this player in this\ngame, so a caller gets the whole box-score line in one row rather than one\nrequest per stat. The vocabulary is per-sport — see /docs#stats."},"PlayerHistoryEntryOut":{"properties":{"event_id":{"type":"string","title":"Event Id"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"bookmaker":{"type":"string","title":"Bookmaker"},"bookmaker_title":{"type":"string","title":"Bookmaker Title"},"line":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Line"},"over_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Over Price"},"under_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Under Price"},"actual_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Value"},"over_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Over Result"},"under_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Under Result"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"redacted":{"type":"boolean","title":"Redacted","default":false}},"type":"object","required":["event_id","commence_time","home_team","away_team","bookmaker","bookmaker_title","line","over_price","under_price","actual_value","over_result","under_result","resolved_at"],"title":"PlayerHistoryEntryOut"},"PlayerHistoryOut":{"properties":{"player_name":{"type":"string","title":"Player Name"},"sport_key":{"type":"string","title":"Sport Key"},"market":{"type":"string","title":"Market"},"entries":{"items":{"$ref":"#/components/schemas/PlayerHistoryEntryOut"},"type":"array","title":"Entries"},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["player_name","sport_key","market","entries"],"title":"PlayerHistoryOut"},"PlayerMarketTrendOut":{"properties":{"market":{"type":"string","title":"Market"},"games_graded":{"type":"integer","title":"Games Graded"},"reference_bookmaker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Bookmaker"},"reference_bookmaker_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Bookmaker Title"},"recent_line":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Recent Line"},"avg_actual":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Actual"},"last_5":{"anyOf":[{"$ref":"#/components/schemas/HitRateSplitOut"},{"type":"null"}]},"last_10":{"anyOf":[{"$ref":"#/components/schemas/HitRateSplitOut"},{"type":"null"}]},"last_20":{"anyOf":[{"$ref":"#/components/schemas/HitRateSplitOut"},{"type":"null"}]},"last_50":{"anyOf":[{"$ref":"#/components/schemas/HitRateSplitOut"},{"type":"null"}]},"current_streak":{"anyOf":[{"$ref":"#/components/schemas/TrendStreakOut"},{"type":"null"}]},"last_game":{"anyOf":[{"$ref":"#/components/schemas/TrendLastGameOut"},{"type":"null"}]},"redacted":{"type":"boolean","title":"Redacted","default":false}},"type":"object","required":["market","games_graded","reference_bookmaker","reference_bookmaker_title","recent_line","avg_actual","last_5","last_10","last_20","last_50","current_streak","last_game"],"title":"PlayerMarketTrendOut","description":"Aggregated hit-rate trends for one player in one market — the\n\"X went over in 7 of his last 10\" surface. Derived purely from\nPropLine's prop resolution (the-odds-api has no equivalent)."},"PlayerStatOut":{"properties":{"player_name":{"type":"string","title":"Player Name"},"team_abbr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Abbr"},"stat_type":{"type":"string","title":"Stat Type"},"stat_value":{"type":"number","title":"Stat Value"}},"type":"object","required":["player_name","team_abbr","stat_type","stat_value"],"title":"PlayerStatOut"},"PlayerTrendsOut":{"properties":{"player_name":{"type":"string","title":"Player Name"},"sport_key":{"type":"string","title":"Sport Key"},"dfs_odds_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dfs Odds Type"},"markets":{"items":{"$ref":"#/components/schemas/PlayerMarketTrendOut"},"type":"array","title":"Markets"},"upgrade_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Url"}},"type":"object","required":["player_name","sport_key","markets"],"title":"PlayerTrendsOut"},"ProjectionRowOut":{"properties":{"market_key":{"type":"string","title":"Market Key"},"player":{"type":"string","title":"Player"},"player_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player Id"},"projected_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Projected Value"},"consensus_over_prob":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Consensus Over Prob"},"books_contributing":{"type":"integer","title":"Books Contributing"},"last_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Update"}},"type":"object","required":["market_key","player","projected_value","consensus_over_prob","books_contributing","last_update"],"title":"ProjectionRowOut"},"ResolvedMarketOut":{"properties":{"key":{"type":"string","title":"Key"},"description":{"type":"string","title":"Description"},"outcomes":{"items":{"$ref":"#/components/schemas/ResolvedOutcomeOut"},"type":"array","title":"Outcomes"}},"type":"object","required":["key","description","outcomes"],"title":"ResolvedMarketOut"},"ResolvedOutcomeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price"},"point":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Point"},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"actual_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Value"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"redacted":{"type":"boolean","title":"Redacted","default":false},"dfs_odds_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dfs Odds Type"},"player_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player Id"}},"type":"object","required":["name","description","price","point","resolution","actual_value","resolved_at"],"title":"ResolvedOutcomeOut"},"ScoreOut":{"properties":{"home_team_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team Key"},"away_team_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team Key"},"home_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team Id"},"away_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team Id"},"id":{"type":"string","title":"Id"},"sport_key":{"type":"string","title":"Sport Key"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"live":{"type":"boolean","title":"Live","default":false},"status":{"type":"string","title":"Status"},"home_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score"},"away_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"}},"type":"object","required":["id","sport_key","home_team","away_team","commence_time","status","home_score","away_score"],"title":"ScoreOut"},"SportOut":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"active":{"type":"boolean","title":"Active"}},"type":"object","required":["key","title","active"],"title":"SportOut"},"SteamMoveOut":{"properties":{"market":{"type":"string","title":"Market"},"period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"books_quoting":{"type":"integer","title":"Books Quoting"},"books_moved":{"type":"integer","title":"Books Moved"},"consensus_direction":{"type":"string","title":"Consensus Direction"},"avg_prob_shift":{"type":"number","title":"Avg Prob Shift"},"consensus_point_shift":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Consensus Point Shift"},"steam_score":{"type":"number","title":"Steam Score"}},"type":"object","required":["market","name","books_quoting","books_moved","consensus_direction","avg_prob_shift","steam_score"],"title":"SteamMoveOut"},"TrendLastGameOut":{"properties":{"event_id":{"type":"string","title":"Event Id"},"commence_time":{"type":"string","format":"date-time","title":"Commence Time"},"line":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Line"},"actual_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Value"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"}},"type":"object","required":["event_id","commence_time","line","actual_value","result"],"title":"TrendLastGameOut"},"TrendStreakOut":{"properties":{"result":{"type":"string","title":"Result"},"length":{"type":"integer","title":"Length"}},"type":"object","required":["result","length"],"title":"TrendStreakOut"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WeatherOut":{"properties":{"temperature_f":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature F"},"humidity_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Humidity Pct"},"precip_probability_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Precip Probability Pct"},"precip_in":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Precip In"},"wind_speed_mph":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Speed Mph"},"wind_gust_mph":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Gust Mph"},"wind_direction_deg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Direction Deg"},"wind_direction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Wind Direction"},"conditions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conditions"},"observed_for":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Observed For"}},"type":"object","title":"WeatherOut"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"},"APIKeyQuery":{"type":"apiKey","in":"query","name":"apiKey"}}}}