{"openapi":"3.1.0","info":{"title":"HoopsAPI","version":"0.2.0","description":"Basketball odds from multiple bookmakers. One API.\n\nBookmakers: 1xbet, betway, fanduel, pinnacle, smarkets, unibet. Odds refresh every 10 minutes.\n\n**Periods:** `ft` (full game, including overtime), `h1`, `h2`, `q1`\u2013`q4`.\n\n**Markets:** `moneyline`, `spread` (`line` is the home team's handicap: -4.5 means home gives 4.5), `total`, `team_total_home`, `team_total_away`.\n\n**Main line:** where a bookmaker offers several lines, the main one is the most evenly priced."},"servers":[{"url":"https://hoopsapi.com/api","description":"Production"}],"paths":{"/v1/games":{"get":{"tags":["games"],"summary":"List Games","operationId":"list_games_v1_games_get","parameters":[{"name":"competition","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by competition name, case-insensitive (e.g. NBA)","title":"Competition"},"description":"Filter by competition name, case-insensitive (e.g. NBA)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GamesListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Upcoming games that have odds, with each bookmaker's main lines for every period."}},"/v1/games/{game_id}":{"get":{"tags":["games"],"summary":"Get Game","operationId":"get_game_v1_games__game_id__get","parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"integer","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Game not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFound"}}}}},"description":"One game with every alternate line. Finished games are served from the archive with their closing odds."}},"/v1/games/{game_id}/history":{"get":{"tags":["games"],"summary":"Get Game History","description":"Every price change for a game, newest first (Data plan). Works for upcoming and finished games.","operationId":"get_game_history_v1_games__game_id__history_get","parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"integer","title":"Game Id"}},{"name":"provider","in":"query","required":false,"description":"Only this bookmaker","schema":{"type":"string"}},{"name":"market","in":"query","required":false,"description":"Only this market","schema":{"type":"string","enum":["moneyline","spread","total","team_total_home","team_total_away"]}},{"name":"period","in":"query","required":false,"description":"Only this period","schema":{"type":"string","enum":["ft","h1","h2","q1","q2","q3","q4"]}},{"name":"limit","in":"query","required":false,"description":"Max changes to return","schema":{"type":"integer","minimum":1,"maximum":5000,"default":500}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Game not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFound"}}}}}}},"/v1/competitions":{"get":{"tags":["competitions"],"summary":"List Competitions","operationId":"list_competitions_v1_competitions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompetitionsListResponse"}}}}}}},"/v1/providers":{"get":{"tags":["providers"],"summary":"List Providers","operationId":"list_providers_v1_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvidersListResponse"}}}}},"description":"Bookmakers and how fresh their data is."}},"/v1/discrepancies":{"get":{"tags":["discrepancies"],"summary":"List Discrepancies","operationId":"list_discrepancies_v1_discrepancies_get","parameters":[{"name":"competition","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by competition name","title":"Competition"},"description":"Filter by competition name"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Top N per category","default":5,"title":"Limit"},"description":"Top N per category"},{"name":"period","in":"query","required":false,"description":"Period to compare","schema":{"type":"string","enum":["ft","h1","h2","q1","q2","q3","q4"],"default":"ft"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscrepanciesListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Biggest cross-bookmaker gaps in main lines: moneyline prices, handicap lines and totals (Pro and Data plans)."}},"/health":{"get":{"tags":["system"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key obtained from your HoopsAPI dashboard"}},"schemas":{"CompetitionResponse":{"properties":{"pinnacle_id":{"type":"integer","title":"Pinnacle Id"},"name":{"type":"string","title":"Name"},"container":{"type":"string","title":"Container"},"event_count":{"type":"integer","title":"Event Count"}},"type":"object","required":["pinnacle_id","name","container","event_count"],"title":"CompetitionResponse"},"CompetitionsListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"competitions":{"items":{"$ref":"#/components/schemas/CompetitionResponse"},"type":"array","title":"Competitions"}},"type":"object","required":["count","competitions"],"title":"CompetitionsListResponse"},"DiscrepanciesListResponse":{"properties":{"moneyline":{"items":{"$ref":"#/components/schemas/GameDiscrepancy"},"type":"array","title":"Moneyline"},"handicap":{"items":{"$ref":"#/components/schemas/GameDiscrepancy"},"type":"array","title":"Handicap"},"over_under":{"items":{"$ref":"#/components/schemas/GameDiscrepancy"},"type":"array","title":"Over Under"}},"type":"object","required":["moneyline","handicap","over_under"],"title":"DiscrepanciesListResponse"},"GameDiscrepancy":{"properties":{"game_id":{"type":"integer","title":"Game Id"},"competition":{"type":"string","title":"Competition"},"home":{"type":"string","title":"Home"},"away":{"type":"string","title":"Away"},"start_time":{"type":"string","format":"date-time","title":"Start Time"},"high_provider":{"type":"string","title":"High Provider"},"high_value":{"type":"number","title":"High Value"},"low_provider":{"type":"string","title":"Low Provider"},"low_value":{"type":"number","title":"Low Value"},"difference":{"type":"number","title":"Difference"}},"type":"object","required":["game_id","competition","home","away","start_time","high_provider","high_value","low_provider","low_value","difference"],"title":"GameDiscrepancy"},"GameHistoryResponse":{"type":"object","title":"GameHistoryResponse","properties":{"game_id":{"type":"integer"},"home":{"type":"string"},"away":{"type":"string"},"competition":{"type":"string"},"count":{"type":"integer"},"changes":{"type":"array","items":{"$ref":"#/components/schemas/PriceChange"},"description":"One entry per price change, newest first"}},"required":["game_id","home","away","competition","count","changes"]},"GameResponse":{"type":"object","title":"GameResponse","properties":{"game_id":{"type":"integer"},"competition":{"type":"string"},"container":{"type":"string","description":"Region or country, e.g. USA"},"home":{"type":"string"},"away":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time","description":"Last time any price for this game changed"},"providers":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProviderOdds"}},"periods":{"type":"object","description":"Keyed by period (ft, h1, h2, q1\u2013q4), then by bookmaker","additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PeriodMarkets"}}}},"required":["game_id","competition","container","home","away","start_time","updated_at","providers","periods"]},"GamesListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"games":{"items":{"$ref":"#/components/schemas/GameResponse"},"type":"array","title":"Games"}},"type":"object","required":["count","games"],"title":"GamesListResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Moneyline":{"type":"object","title":"Moneyline","properties":{"home":{"type":"number"},"away":{"type":"number"}},"required":["home","away"]},"ProviderOdds":{"type":"object","title":"ProviderOdds","description":"Full-game main lines (kept for compatibility; periods has the same and more).","properties":{"moneyline":{"anyOf":[{"$ref":"#/components/schemas/Moneyline"},{"type":"null"}]},"handicap":{"anyOf":[{"$ref":"#/components/schemas/Spread"},{"type":"null"}]},"over_under":{"anyOf":[{"$ref":"#/components/schemas/Total"},{"type":"null"}]},"captured_at":{"type":["string","null"],"format":"date-time","description":"Last successful scrape of this bookmaker"}},"required":["moneyline","handicap","over_under","captured_at"]},"ProviderResponse":{"type":"object","title":"ProviderResponse","properties":{"name":{"type":"string"},"last_update":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["ok","stale"],"description":"stale when not scraped successfully for 30 minutes"},"games":{"type":"integer","description":"Games listed on the last successful scrape"}},"required":["name","last_update","status","games"]},"ProvidersListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"providers":{"items":{"$ref":"#/components/schemas/ProviderResponse"},"type":"array","title":"Providers"}},"type":"object","required":["count","providers"],"title":"ProvidersListResponse"},"Spread":{"type":"object","title":"Spread","description":"line is the home handicap","properties":{"line":{"type":"number"},"home":{"type":"number"},"away":{"type":"number"}},"required":["line","home","away"]},"Total":{"type":"object","title":"Total","properties":{"line":{"type":"number"},"over":{"type":"number"},"under":{"type":"number"}},"required":["line","over","under"]},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"PeriodMarkets":{"type":"object","title":"PeriodMarkets","description":"A bookmaker's main line per market for one period. Markets it doesn't offer are omitted.","properties":{"moneyline":{"$ref":"#/components/schemas/Moneyline"},"spread":{"$ref":"#/components/schemas/Spread"},"total":{"$ref":"#/components/schemas/Total"},"team_total_home":{"$ref":"#/components/schemas/Total"},"team_total_away":{"$ref":"#/components/schemas/Total"}}},"PeriodLines":{"type":"object","title":"PeriodLines","description":"Every line a bookmaker offers for one period, main line first.","properties":{"spread":{"type":"array","items":{"$ref":"#/components/schemas/Spread"}},"total":{"type":"array","items":{"$ref":"#/components/schemas/Total"}},"team_total_home":{"type":"array","items":{"$ref":"#/components/schemas/Total"}},"team_total_away":{"type":"array","items":{"$ref":"#/components/schemas/Total"}}}},"GameDetailResponse":{"type":"object","title":"GameDetailResponse","properties":{"game_id":{"type":"integer"},"competition":{"type":"string"},"container":{"type":"string","description":"Region or country, e.g. USA"},"home":{"type":"string"},"away":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time","description":"Last time any price for this game changed"},"providers":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProviderOdds"}},"periods":{"type":"object","description":"Keyed by period (ft, h1, h2, q1\u2013q4), then by bookmaker","additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PeriodMarkets"}}},"status":{"type":"string","enum":["upcoming","archived"],"description":"archived games return their closing odds"},"lines":{"type":"object","description":"Keyed by period (ft, h1, h2, q1\u2013q4), then by bookmaker","additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PeriodLines"}}}},"required":["game_id","competition","container","home","away","start_time","updated_at","providers","periods","status","lines"]},"PriceChange":{"type":"object","title":"PriceChange","properties":{"provider":{"type":"string"},"market":{"type":"string","enum":["moneyline","spread","total","team_total_home","team_total_away"]},"period":{"type":"string","enum":["ft","h1","h2","q1","q2","q3","q4"]},"line":{"type":["number","null"]},"outcome":{"type":"string","description":"home, away, over or under"},"price":{"type":"number"},"at":{"type":"string","format":"date-time"}},"required":["provider","market","period","line","outcome","price","at"]},"NotFound":{"type":"object","title":"NotFound","properties":{"detail":{"type":"string"}}}}}}