{"openapi":"3.1.0","info":{"title":"Model90 — Global Football ML Predictions","version":"2.0.0"},"paths":{"/api/health":{"get":{"summary":"Health","description":"Liveness + readiness probe.  Returns 503 when the database is unreachable.","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api Health Get"}}}}}},"head":{"summary":"Health Head","description":"HEAD handler for uptime monitors (UptimeRobot etc.).","operationId":"health_head_api_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/mcp":{"post":{"summary":"Mcp Endpoint","description":"Minimal MCP server (Streamable HTTP transport, JSON-RPC 2.0). Read-only —\nevery tool call reads through the same functions the site itself calls, so\nthere's no separate \"agent view\" of the data that can silently go stale.","operationId":"mcp_endpoint_mcp_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/leagues":{"get":{"summary":"List Leagues","description":"Return all tracked leagues (or just enabled ones).","operationId":"list_leagues_api_leagues_get","parameters":[{"name":"enabled_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Enabled Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Leagues Api Leagues Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leagues/{league_id}/seasons":{"get":{"summary":"List League Seasons","description":"Seasons that actually have finished-fixture data for this league.\n\nPowers the season picker — only surfaces seasons with real results, not\nones still sitting in the gradual historical-backfill queue.","operationId":"list_league_seasons_api_leagues__league_id__seasons_get","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List League Seasons Api Leagues  League Id  Seasons Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures":{"get":{"summary":"List Fixtures","description":"Return upcoming NS fixtures, optionally filtered by league_id and season.","operationId":"list_fixtures_api_fixtures_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Fixtures Api Fixtures Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/live":{"get":{"summary":"List Live Fixtures","description":"Return currently live fixtures, optionally filtered by league.","operationId":"list_live_fixtures_api_fixtures_live_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Live Fixtures Api Fixtures Live Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/live/stream":{"get":{"summary":"Live Fixtures Stream","description":"SSE stream — pushes an 'update' event whenever live fixture data changes.\nNo auth required (data is public). Uses Redis pub/sub when available,\notherwise falls back to 15s server-side timer.","operationId":"live_fixtures_stream_api_fixtures_live_stream_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/fixtures/paged":{"get":{"summary":"Fixtures Paged","description":"Paginated fixture list with optional filters.","operationId":"fixtures_paged_api_fixtures_paged_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"NS | 1H | HT | 2H | FT | ...","title":"Status"},"description":"NS | 1H | HT | 2H | FT | ..."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixtures Paged Api Fixtures Paged Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}":{"get":{"summary":"Get Fixture","description":"Return a single fixture with its latest prediction and live events.","operationId":"get_fixture_api_fixtures__fixture_id__get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Fixture Api Fixtures  Fixture Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/predictions/{fixture_id}":{"get":{"summary":"Get Prediction","description":"Return the latest MatchPrediction for a fixture.","operationId":"get_prediction_api_predictions__fixture_id__get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Prediction Api Predictions  Fixture Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/predictions/{fixture_id}/explain":{"get":{"summary":"Explain Prediction","description":"Return directional feature attribution for a fixture prediction.","operationId":"explain_prediction_api_predictions__fixture_id__explain_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Explain Prediction Api Predictions  Fixture Id  Explain Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/results":{"get":{"summary":"List Results","description":"Return finished fixtures with prediction vs reality, optionally filtered by league.","operationId":"list_results_api_results_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":150,"title":"Limit"}},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Results Api Results Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standings":{"get":{"summary":"Standings","description":"Return teams sorted by Elo, optionally scoped to a league.","operationId":"standings_api_standings_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Standings Api Standings Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standings/groups":{"get":{"summary":"Group Standings","description":"Group-stage standings — real-time stats from FT fixtures, group names from AfStanding.","operationId":"group_standings_api_standings_groups_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Group Standings Api Standings Groups Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/stats":{"get":{"summary":"Fixture Stats","operationId":"fixture_stats_api_fixtures__fixture_id__stats_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Stats Api Fixtures  Fixture Id  Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/lineups":{"get":{"summary":"Fixture Lineups","operationId":"fixture_lineups_api_fixtures__fixture_id__lineups_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Fixture Lineups Api Fixtures  Fixture Id  Lineups Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/odds":{"get":{"summary":"Fixture Odds","operationId":"fixture_odds_api_fixtures__fixture_id__odds_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Odds Api Fixtures  Fixture Id  Odds Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/h2h":{"get":{"summary":"Fixture H2H","description":"Return historical H2H results. Uses api-football H2HRecord cache when available,\nfalls back to in-tournament fixtures.","operationId":"fixture_h2h_api_fixtures__fixture_id__h2h_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Fixture H2H Api Fixtures  Fixture Id  H2H Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/injuries":{"get":{"summary":"Injuries","description":"Current injuries and suspensions, optionally filtered by league.","operationId":"injuries_api_injuries_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Injuries Api Injuries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/events":{"get":{"summary":"Fixture Events","description":"Return structured match events (goals, cards, subs) for a fixture.","operationId":"fixture_events_api_fixtures__fixture_id__events_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Fixture Events Api Fixtures  Fixture Id  Events Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/odds":{"get":{"summary":"All Odds","description":"Return all fixtures that have bookmaker odds, with ML predictions for value analysis.\n\nPrecomputed and background-refreshed every _ODDS_CACHE_TTL seconds — the same pattern\nas /api/championship-odds and /api/compare — instead of computing inline on a cache\nmiss, which used to mean whichever request landed right after the TTL expired paid the\nfull join+subquery+Python-loop cost synchronously.","operationId":"all_odds_api_odds_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response All Odds Api Odds Get"}}}}}}},"/api/compare":{"get":{"summary":"Compare Predictions","description":"Return fixtures with ML predictions vs market (bookmaker-implied) probabilities.\naf_prediction data is included only when api-football has real predictions (not the\n33%/33%/33% 'no predictions available' placeholder).\n\nThe unfiltered (no league_id/season) response is precomputed and background-refreshed\nevery _ODDS_CACHE_TTL seconds — the same pattern as /api/championship-odds — because the\nfull unfiltered scan joins four relations across every fixture in the database and used\nto run synchronously on every cache miss, measured at 13+ seconds under real load.\n\nKept for back-compat; the /compare page itself now uses /api/compare/summary and\n/api/compare/finished so it never has to fetch or render the full, ever-growing\nhistorical fixture list just to show a handful of upcoming matches.","operationId":"compare_predictions_api_compare_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Compare Predictions Api Compare Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/compare/summary":{"get":{"summary":"Compare Summary","description":"Cheap aggregate stats + upcoming fixtures for the /compare hero and\ndisagreements/agreements sections — avoids sending the full (thousands\nstrong, and growing) historical fixture list just to show a handful of\nupcoming matches and two accuracy percentages.","operationId":"compare_summary_api_compare_summary_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Compare Summary Api Compare Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/compare/finished":{"get":{"summary":"Compare Finished","description":"Paginated slice of finished-match model-vs-market comparisons, sorted\nnewest first. The historical list grows without bound as more seasons\nbackfill in (8,478+ rows and climbing) — deliberately never returned in\nfull, unlike the plain /api/compare.","operationId":"compare_finished_api_compare_finished_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Compare Finished Api Compare Finished Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/squads/{team_id}":{"get":{"summary":"Squad","description":"Return squad players for a team.","operationId":"squad_api_squads__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Squad Api Squads  Team Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/discipline":{"get":{"summary":"Discipline","description":"Return yellow and red card leaders, optionally filtered by league.","operationId":"discipline_api_discipline_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Discipline Api Discipline Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/players":{"get":{"summary":"Fixture Players","description":"Return per-player stats for a completed fixture.","operationId":"fixture_players_api_fixtures__fixture_id__players_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Fixture Players Api Fixtures  Fixture Id  Players Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/players/leaderboard":{"get":{"summary":"Players Leaderboard","description":"Return top-rated players of the tournament (highest avg rating across matches).","operationId":"players_leaderboard_api_players_leaderboard_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Players Leaderboard Api Players Leaderboard Get"}}}}}}},"/api/players/search":{"get":{"summary":"Players Search","description":"Search players by name — returns distinct players with their team and photo.","operationId":"players_search_api_players_search_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":64,"title":"Name"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":8,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Players Search Api Players Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/players/{player_id}":{"get":{"summary":"Player Detail","description":"Return all match performances for a player across the tournament.","operationId":"player_detail_api_players__player_id__get","parameters":[{"name":"player_id","in":"path","required":true,"schema":{"type":"integer","title":"Player Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Player Detail Api Players  Player Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/market-odds":{"get":{"summary":"Fixture Market Odds","description":"Return O/U 2.5 and BTTS odds for a fixture.","operationId":"fixture_market_odds_api_fixtures__fixture_id__market_odds_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Market Odds Api Fixtures  Fixture Id  Market Odds Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/bookmaker-odds":{"get":{"summary":"Fixture Bookmaker Odds","description":"Return all bookmaker 1X2 odds for a fixture, sorted by home_odds.","operationId":"fixture_bookmaker_odds_api_fixtures__fixture_id__bookmaker_odds_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Fixture Bookmaker Odds Api Fixtures  Fixture Id  Bookmaker Odds Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/odds-timeline":{"get":{"summary":"Fixture Odds Timeline","description":"Return time-series odds snapshots for a fixture, grouped by bookmaker.","operationId":"fixture_odds_timeline_api_fixtures__fixture_id__odds_timeline_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}},{"name":"bookmaker","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookmaker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Odds Timeline Api Fixtures  Fixture Id  Odds Timeline Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/momentum":{"get":{"summary":"Fixture Momentum","description":"Compute match momentum from MatchEvent data in 5-minute rolling windows.","operationId":"fixture_momentum_api_fixtures__fixture_id__momentum_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Momentum Api Fixtures  Fixture Id  Momentum Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fixtures/{fixture_id}/simulate":{"post":{"summary":"Simulate Fixture","description":"Run a per-match Monte Carlo simulation using calibrated Poisson lambdas.","operationId":"simulate_fixture_api_fixtures__fixture_id__simulate_post","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}},{"name":"runs","in":"query","required":false,"schema":{"type":"integer","default":10000,"title":"Runs"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Simulate Fixture Api Fixtures  Fixture Id  Simulate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/championship-odds":{"get":{"summary":"Championship Odds","description":"Monte Carlo championship probabilities. Cached + background-refreshed every 30 min.","operationId":"championship_odds_api_championship_odds_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Championship Odds Api Championship Odds Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tournament/path":{"get":{"summary":"Tournament Path","description":"Run MC simulations and return per-team probability of reaching each knockout stage.\nReturns: { teams: [{name, r16, qf, sf, final, champion}], generated_at, runs }\n\nThe canonical runs=2000 request (what the frontend always sends) is precomputed and\nbackground-refreshed every _TOURNAMENT_PATH_CACHE_TTL seconds — the same pattern as\n/api/championship-odds — since this used to run two full Monte Carlo passes\nsynchronously on every request with no caching at all, protected only by a rate limit.","operationId":"tournament_path_api_tournament_path_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}},{"name":"runs","in":"query","required":false,"schema":{"type":"integer","default":2000,"title":"Runs"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Tournament Path Api Tournament Path Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/calibration":{"get":{"summary":"Calibration Data","description":"Return calibration data: predicted probability buckets vs actual outcome rate.","operationId":"calibration_data_api_calibration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Calibration Data Api Calibration Get"}}}}}}},"/api/calibration/performance":{"get":{"summary":"Calibration Performance","description":"Return per-round model performance metrics (Brier score + accuracy over time).","operationId":"calibration_performance_api_calibration_performance_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Calibration Performance Api Calibration Performance Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/topscorers":{"get":{"summary":"Top Scorers","operationId":"top_scorers_api_topscorers_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Top Scorers Api Topscorers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standings/official":{"get":{"summary":"Official Standings","description":"Official group/league standings synced from api-football /standings.","operationId":"official_standings_api_standings_official_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Official Standings Api Standings Official Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/standings/history":{"get":{"summary":"Standings History","description":"Returns cumulative standings checkpoints (round by round) computed from FT fixtures.\nUsed to chart how teams' points/rank evolved over time.","operationId":"standings_history_api_standings_history_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Standings History Api Standings History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/odds/bookmakers":{"get":{"summary":"List Bookmakers","description":"All supported bookmakers from api-football /odds/bookmakers.","operationId":"list_bookmakers_api_odds_bookmakers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Bookmakers Api Odds Bookmakers Get"}}}}}}},"/api/odds/bet-types":{"get":{"summary":"List Bet Types","description":"All supported betting markets from api-football /odds/mapping.","operationId":"list_bet_types_api_odds_bet_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Bet Types Api Odds Bet Types Get"}}}}}}},"/api/teams/{team_id}/statistics":{"get":{"summary":"Team Statistics","description":"Full season stats for a team from api-football /teams/statistics.","operationId":"team_statistics_api_teams__team_id__statistics_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}},{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Team Statistics Api Teams  Team Id  Statistics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leagues/{league_id}/team-stats":{"get":{"summary":"League Team Stats","description":"Season stats for every team in a league — the league-wide view of\nthe same data /api/teams/{team_id}/statistics returns one team at a time.","operationId":"league_team_stats_api_leagues__league_id__team_stats_get","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response League Team Stats Api Leagues  League Id  Team Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams/{team_id}/elo-history":{"get":{"summary":"Team Elo History","description":"Reconstruct Elo trajectory for a team across all finished fixtures.\n\nSince Elo is stored only as the current value, we replay the Elo formula\nchronologically over all finished fixtures the team played in to derive\nthe before/after rating at each match.","operationId":"team_elo_history_api_teams__team_id__elo_history_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Team Elo History Api Teams  Team Id  Elo History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams/{team_id}/dna":{"get":{"summary":"Team Dna","description":"Return 7-axis DNA profile for a team, normalized 0-100.\n\nAxes: Attack, Defense, Elo, Form, Consistency, Set Pieces, Pressing.\nDerived from fixture history and team stats in the DB.","operationId":"team_dna_api_teams__team_id__dna_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Team Dna Api Teams  Team Id  Dna Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams/mine":{"get":{"summary":"Get Followed Teams","operationId":"get_followed_teams_api_teams_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Followed Teams Api Teams Mine Get"}}}}}}},"/api/teams/{team_id}":{"get":{"summary":"Team Detail","operationId":"team_detail_api_teams__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Team Detail Api Teams  Team Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bracket/leagues":{"get":{"summary":"Bracket Leagues","description":"Return cup/tournament leagues for the bracket picker — domestic leagues excluded.","operationId":"bracket_leagues_api_bracket_leagues_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Bracket Leagues Api Bracket Leagues Get"}}}}}}},"/api/bracket":{"get":{"summary":"Bracket","operationId":"bracket_api_bracket_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bracket Api Bracket Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leagues/search":{"get":{"summary":"Search Leagues","description":"Search api-football for available leagues. Returns up to 50 results.","operationId":"search_leagues_api_leagues_search_get","parameters":[{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Search Leagues Api Leagues Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/countries":{"get":{"summary":"List Countries","description":"Return all countries available in the api-football catalog.","operationId":"list_countries_api_countries_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Countries Api Countries Get"}}}}}}},"/api/squad-pedigree/{team_id}":{"get":{"summary":"Squad Pedigree","description":"Return cached squad transfer scores and per-player transfer data for a team.","operationId":"squad_pedigree_api_squad_pedigree__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Squad Pedigree Api Squad Pedigree  Team Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/transfers/{player_id}":{"get":{"summary":"Player Transfers","description":"Return full transfer history for a player, newest first.","operationId":"player_transfers_api_transfers__player_id__get","parameters":[{"name":"player_id","in":"path","required":true,"schema":{"type":"integer","title":"Player Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Player Transfers Api Transfers  Player Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wc-leagues":{"get":{"summary":"Wc Leagues","description":"Return distinct leagues where World Cup squad players currently play, sorted by player count.","operationId":"wc_leagues_api_wc_leagues_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Wc Leagues Api Wc Leagues Get"}}}}}}},"/api/leagues/{league_id}/clubs":{"get":{"summary":"League Clubs","description":"Return all clubs that have appeared in fixtures for this league, sorted by name.","operationId":"league_clubs_api_leagues__league_id__clubs_get","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response League Clubs Api Leagues  League Id  Clubs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/transfers-by-league":{"get":{"summary":"Transfers By League","description":"Return all World Cup squad players currently playing in the given league.","operationId":"transfers_by_league_api_transfers_by_league_get","parameters":[{"name":"league","in":"query","required":true,"schema":{"type":"string","title":"League"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Transfers By League Api Transfers By League Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wc-nations":{"get":{"summary":"Wc Nations","description":"Return national teams at WC2026 with squad player counts.","operationId":"wc_nations_api_wc_nations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Wc Nations Api Wc Nations Get"}}}}}}},"/api/wc-squad-transfers/{team_id}":{"get":{"summary":"Wc Squad Transfers","description":"Squad players for a WC national team with latest club/transfer info.","operationId":"wc_squad_transfers_api_wc_squad_transfers__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Wc Squad Transfers Api Wc Squad Transfers  Team Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/squads/{team_id}/pedigree-summary":{"get":{"summary":"Squad Pedigree Summary","description":"Lightweight squad pedigree summary for fixture card chips — DB read only.","operationId":"squad_pedigree_summary_api_squads__team_id__pedigree_summary_get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Squad Pedigree Summary Api Squads  Team Id  Pedigree Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-predictions/{fixture_id}":{"post":{"summary":"Submit User Prediction","description":"Submit or update a user's pre-match pick for Beat the Model.","operationId":"submit_user_prediction_api_user_predictions__fixture_id__post","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPickBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Submit User Prediction Api User Predictions  Fixture Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-predictions/me":{"get":{"summary":"My Predictions","description":"Get the current user's picks with outcome correctness for finished matches.","operationId":"my_predictions_api_user_predictions_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response My Predictions Api User Predictions Me Get"}}}}}}},"/api/user-predictions/{fixture_id}/my-pick":{"get":{"summary":"My Fixture Pick","description":"Get the authenticated user's pick for a specific fixture (or null).","operationId":"my_fixture_pick_api_user_predictions__fixture_id__my_pick_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response My Fixture Pick Api User Predictions  Fixture Id  My Pick Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-predictions/{fixture_id}/result":{"get":{"summary":"Fixture Prediction Result","description":"Post-match Brier comparison: user pick vs model probabilities.","operationId":"fixture_prediction_result_api_user_predictions__fixture_id__result_get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Prediction Result Api User Predictions  Fixture Id  Result Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaderboard":{"get":{"summary":"Leaderboard","description":"Beat the Model leaderboard — community predictors with Brier scores, streaks, and badges.\nphase: all | group | knockout","operationId":"leaderboard_api_leaderboard_get","parameters":[{"name":"phase","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"all","title":"Phase"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Leaderboard Api Leaderboard Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comments":{"get":{"summary":"List Comments","description":"Return paginated top-level comments + their replies for an entity.","operationId":"list_comments_api_comments_get","parameters":[{"name":"entity_type","in":"query","required":true,"schema":{"$ref":"#/components/schemas/EntityTypeEnum"}},{"name":"entity_id","in":"query","required":true,"schema":{"type":"string","maxLength":32,"title":"Entity Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Comments Api Comments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Create Comment","operationId":"create_comment_api_comments_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Comment Api Comments Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comments/{comment_id}":{"put":{"summary":"Update Comment","operationId":"update_comment_api_comments__comment_id__put","parameters":[{"name":"comment_id","in":"path","required":true,"schema":{"type":"integer","title":"Comment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Comment Api Comments  Comment Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Comment","operationId":"delete_comment_api_comments__comment_id__delete","parameters":[{"name":"comment_id","in":"path","required":true,"schema":{"type":"integer","title":"Comment Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comments/{comment_id}/like":{"post":{"summary":"Toggle Like","operationId":"toggle_like_api_comments__comment_id__like_post","parameters":[{"name":"comment_id","in":"path","required":true,"schema":{"type":"integer","title":"Comment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Toggle Like Api Comments  Comment Id  Like Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comments/{comment_id}/report":{"post":{"summary":"Report Comment","operationId":"report_comment_api_comments__comment_id__report_post","parameters":[{"name":"comment_id","in":"path","required":true,"schema":{"type":"integer","title":"Comment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentReportCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Report Comment Api Comments  Comment Id  Report Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/announcements":{"get":{"summary":"List Announcements","description":"Active, unexpired announcements — pinned first, then most recent.","operationId":"list_announcements_api_announcements_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Announcements Api Announcements Get"}}}}}}},"/api/users/me/profile":{"get":{"summary":"Get My Profile","operationId":"get_my_profile_api_users_me_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get My Profile Api Users Me Profile Get"}}}}}},"put":{"summary":"Upsert Profile","operationId":"upsert_profile_api_users_me_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpsert"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Upsert Profile Api Users Me Profile Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/{user_id}/profile":{"get":{"summary":"Get User Profile","description":"Minimal by-id lookup — used to render a username/avatar next to a comment.\n\nAlways public regardless of UserProfile.is_public: that flag governs the\nfull profile page (bio, social links, followed leagues/teams), not the\nidentity already visible on the user's own public comments.","operationId":"get_user_profile_api_users__user_id__profile_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get User Profile Api Users  User Id  Profile Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/by-username/{username}/profile":{"get":{"summary":"Get Public Profile By Username","description":"Public profile page lookup, gated by is_public unless the requester is the owner/admin.","operationId":"get_public_profile_by_username_api_users_by_username__username__profile_get","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Public Profile By Username Api Users By Username  Username  Profile Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/model-insights":{"get":{"summary":"Model Insights","description":"Return SHAP feature importance, per-round performance metrics,\nstacker base-model weights, and aggregate CLV statistics.","operationId":"model_insights_api_model_insights_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Model Insights Api Model Insights Get"}}}}}}},"/api/roi-tracker":{"get":{"summary":"Roi Tracker","description":"Cumulative P&L for a flat-staking strategy on the model's top pick.\n\nFor each finished match where we have a prediction and bookmaker odds, we\nsimulate placing 1 unit on whichever outcome the model favoured most.\nReturns a chronological list of matches with running P&L.","operationId":"roi_tracker_api_roi_tracker_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Roi Tracker Api Roi Tracker Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/morning-report":{"get":{"summary":"Morning Report","description":"Daily briefing: today's matches, yesterday's results, model form, top scorers.","operationId":"morning_report_api_morning_report_get","parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Morning Report Api Morning Report Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/model-insights/clv/{fixture_id}":{"get":{"summary":"Fixture Clv","description":"Return CLV breakdown for a specific fixture.","operationId":"fixture_clv_api_model_insights_clv__fixture_id__get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fixture Clv Api Model Insights Clv  Fixture Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports/daily":{"get":{"summary":"Daily Report","description":"Template-based daily intelligence report:\n- Highest confidence upcoming match\n- Best value bets (model vs implied edge > 5%)\n- Goal fest alert (combined xG > 3.0)\n- Yesterday's biggest model miss (highest Brier)","operationId":"daily_report_api_reports_daily_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Daily Report Api Reports Daily Get"}}}}}}},"/api/advanced-analytics/{fixture_id}":{"get":{"summary":"Advanced Analytics","description":"Return advanced analytics for a fixture. FBref data if available, derived fallback.","operationId":"advanced_analytics_api_advanced_analytics__fixture_id__get","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Advanced Analytics Api Advanced Analytics  Fixture Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/confidence-map":{"get":{"summary":"Confidence Map","description":"Return Elo-based confidence scores for WC 2026 teams, keyed by ISO alpha-3.","operationId":"confidence_map_api_confidence_map_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Confidence Map Api Confidence Map Get"}}}}}}},"/api/keys":{"get":{"summary":"List Api Keys","description":"List all active API keys for the authenticated user (keys not returned).","operationId":"list_api_keys_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Api Keys Api Keys Get"}}}}}},"post":{"summary":"Create Api Key","description":"Generate a new API key for the authenticated user.","operationId":"create_api_key_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Api Key Api Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/keys/{key_id}":{"delete":{"summary":"Delete Api Key","description":"Revoke an API key.","operationId":"delete_api_key_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Api Key Api Keys  Key Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/model/evolution":{"get":{"summary":"Model Evolution","description":"Return per-model version history from the model registry.\n\nTraining runs on the dedicated `scheduler` Railway service and this\nendpoint runs on `api`, a separate container that never sees the\nscheduler's local disk — so prefer the DB-mirrored registry (same\npattern as /api/model-insights) and fall back to the local file for\nsingle-container/dev setups.","operationId":"model_evolution_api_model_evolution_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Model Evolution Api Model Evolution Get"}}}}}}},"/api/notifications/settings":{"get":{"summary":"Get Notification Settings","operationId":"get_notification_settings_api_notifications_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Notification Settings Api Notifications Settings Get"}}}}}},"patch":{"summary":"Patch Notification Settings","operationId":"patch_notification_settings_api_notifications_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationSettingsBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Patch Notification Settings Api Notifications Settings Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/preferences/events":{"get":{"summary":"Get Event Preferences","operationId":"get_event_preferences_api_notifications_preferences_events_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Event Preferences Api Notifications Preferences Events Get"}}}}}},"patch":{"summary":"Patch Event Preferences","operationId":"patch_event_preferences_api_notifications_preferences_events_patch","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Patch Event Preferences Api Notifications Preferences Events Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/subscriptions/teams":{"get":{"summary":"Get Team Subscriptions","operationId":"get_team_subscriptions_api_notifications_subscriptions_teams_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Team Subscriptions Api Notifications Subscriptions Teams Get"}}}}}}},"/api/notifications/subscriptions/teams/{team_id}":{"put":{"summary":"Upsert Team Subscription","operationId":"upsert_team_subscription_api_notifications_subscriptions_teams__team_id__put","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamSubBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upsert Team Subscription Api Notifications Subscriptions Teams  Team Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Team Subscription","operationId":"delete_team_subscription_api_notifications_subscriptions_teams__team_id__delete","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/subscriptions/competitions":{"get":{"summary":"Get Competition Subscriptions","operationId":"get_competition_subscriptions_api_notifications_subscriptions_competitions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Competition Subscriptions Api Notifications Subscriptions Competitions Get"}}}}}}},"/api/notifications/subscriptions/competitions/{league_id}":{"put":{"summary":"Upsert Competition Subscription","operationId":"upsert_competition_subscription_api_notifications_subscriptions_competitions__league_id__put","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}},{"name":"enabled","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Enabled"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upsert Competition Subscription Api Notifications Subscriptions Competitions  League Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Competition Subscription","operationId":"delete_competition_subscription_api_notifications_subscriptions_competitions__league_id__delete","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leagues/mine":{"get":{"summary":"Get Followed Leagues","operationId":"get_followed_leagues_api_leagues_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Followed Leagues Api Leagues Mine Get"}}}}}}},"/api/leagues/{league_id}/follow":{"put":{"summary":"Follow League","operationId":"follow_league_api_leagues__league_id__follow_put","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Follow League Api Leagues  League Id  Follow Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Unfollow League","operationId":"unfollow_league_api_leagues__league_id__follow_delete","parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/teams/{team_id}/follow":{"put":{"summary":"Follow Team","operationId":"follow_team_api_teams__team_id__follow_put","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Follow Team Api Teams  Team Id  Follow Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Unfollow Team","operationId":"unfollow_team_api_teams__team_id__follow_delete","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","title":"Team Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/matches/{fixture_id}/watch":{"put":{"summary":"Watch Match","operationId":"watch_match_api_notifications_matches__fixture_id__watch_put","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}},{"name":"auto_unsubscribe","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Auto Unsubscribe"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Watch Match Api Notifications Matches  Fixture Id  Watch Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Unwatch Match","operationId":"unwatch_match_api_notifications_matches__fixture_id__watch_delete","parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/watched-matches":{"get":{"summary":"List Watched Matches","operationId":"list_watched_matches_api_notifications_watched_matches_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Watched Matches Api Notifications Watched Matches Get"}}}}}}},"/api/notifications/push-subscriptions":{"put":{"summary":"Upsert Push Subscription","operationId":"upsert_push_subscription_api_notifications_push_subscriptions_put","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushSubBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upsert Push Subscription Api Notifications Push Subscriptions Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Push Subscription","operationId":"delete_push_subscription_api_notifications_push_subscriptions_delete","parameters":[{"name":"endpoint","in":"query","required":true,"schema":{"type":"string","title":"Endpoint"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/vapid-public-key":{"get":{"summary":"Vapid Public Key","operationId":"vapid_public_key_api_notifications_vapid_public_key_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Vapid Public Key Api Notifications Vapid Public Key Get"}}}}}}},"/api/notifications/history":{"get":{"summary":"Notification History","operationId":"notification_history_api_notifications_history_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"unread_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unread Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Notification History Api Notifications History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/unread-count":{"get":{"summary":"Notification Unread Count","operationId":"notification_unread_count_api_notifications_unread_count_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Notification Unread Count Api Notifications Unread Count Get"}}}}}}},"/api/notifications/history/{notification_id}":{"patch":{"summary":"Patch Notification","operationId":"patch_notification_api_notifications_history__notification_id__patch","parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"integer","title":"Notification Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotifHistoryPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Patch Notification Api Notifications History  Notification Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Notification","operationId":"delete_notification_api_notifications_history__notification_id__delete","parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"integer","title":"Notification Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/notifications/test-push":{"post":{"summary":"Test Push Notification","description":"Send a test push notification to all registered devices for the authenticated user.","operationId":"test_push_notification_api_notifications_test_push_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Test Push Notification Api Notifications Test Push Post"}}}}}}},"/api/notifications/mark-all-read":{"post":{"summary":"Mark All Notifications Read","operationId":"mark_all_notifications_read_api_notifications_mark_all_read_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Mark All Notifications Read Api Notifications Mark All Read Post"}}}}}}},"/api/notifications/sse":{"get":{"summary":"Notification Sse","description":"Server-Sent Events stream — sends in-app notification events to the browser.\nAuth via Authorization header only; use fetchEventSource on the frontend.","operationId":"notification_sse_api_notifications_sse_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/api-football-status":{"get":{"summary":"Admin Api Football Status","description":"Return api-football.com quota status.","operationId":"admin_api_football_status_api_admin_api_football_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Api Football Status Api Admin Api Football Status Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-league":{"post":{"summary":"Admin Sync League","description":"Sync teams and fixtures for a specific league/season from api-football.","operationId":"admin_sync_league_api_admin_sync_league_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"query","required":true,"schema":{"type":"integer","title":"League Id"}},{"name":"season","in":"query","required":true,"schema":{"type":"integer","title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Sync League Api Admin Sync League Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/sync-all-fixtures":{"post":{"summary":"Admin Sync All Fixtures","description":"Sync teams and fixtures for all enabled leagues from api-football.","operationId":"admin_sync_all_fixtures_api_admin_sync_all_fixtures_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync All Fixtures Api Admin Sync All Fixtures Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/enable-league":{"post":{"summary":"Admin Enable League","operationId":"admin_enable_league_api_admin_enable_league_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"query","required":true,"schema":{"type":"integer","title":"League Id"}},{"name":"season","in":"query","required":true,"schema":{"type":"integer","title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Enable League Api Admin Enable League Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/disable-league":{"post":{"summary":"Admin Disable League","description":"Stop tracking a league (keeps existing data, just stops future syncs).","operationId":"admin_disable_league_api_admin_disable_league_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"query","required":true,"schema":{"type":"integer","title":"League Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Disable League Api Admin Disable League Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/leagues/{league_id}":{"patch":{"summary":"Admin Patch League","description":"Edit a tracked league's metadata directly, without a full re-enable+resync cycle.","operationId":"admin_patch_league_api_admin_leagues__league_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaguePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Patch League Api Admin Leagues  League Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Delete League","description":"Hard-delete a league — only when it has no fixtures. Use disable-league otherwise.","operationId":"admin_delete_league_api_admin_leagues__league_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"path","required":true,"schema":{"type":"integer","title":"League Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Delete League Api Admin Leagues  League Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/leagues/seed-defaults":{"post":{"summary":"Admin Seed Default Leagues","description":"Idempotently enable the platform's default league set for a fresh deployment.","operationId":"admin_seed_default_leagues_api_admin_leagues_seed_defaults_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Seed Default Leagues Api Admin Leagues Seed Defaults Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-stats":{"post":{"summary":"Admin Sync Stats","description":"Sync match statistics for all completed fixtures.","operationId":"admin_sync_stats_api_admin_sync_stats_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Stats Api Admin Sync Stats Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-lineups":{"post":{"summary":"Admin Sync Lineups","description":"Sync lineups for fixtures in the next 24 hours.","operationId":"admin_sync_lineups_api_admin_sync_lineups_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Lineups Api Admin Sync Lineups Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-odds":{"post":{"summary":"Admin Sync Odds","description":"Sync Match Winner odds for all upcoming fixtures.","operationId":"admin_sync_odds_api_admin_sync_odds_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Odds Api Admin Sync Odds Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-topscorers":{"post":{"summary":"Admin Sync Topscorers","description":"Sync top scorers leaderboard for all enabled leagues.","operationId":"admin_sync_topscorers_api_admin_sync_topscorers_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Topscorers Api Admin Sync Topscorers Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-injuries":{"post":{"summary":"Admin Sync Injuries","description":"Sync injury/suspension list for all enabled leagues from api-football.","operationId":"admin_sync_injuries_api_admin_sync_injuries_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Injuries Api Admin Sync Injuries Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-squads-all":{"post":{"summary":"Admin Sync Squads All","description":"Sync squad rosters for all enabled leagues from api-football.","operationId":"admin_sync_squads_all_api_admin_sync_squads_all_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Squads All Api Admin Sync Squads All Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/debug-af-teams":{"get":{"summary":"Admin Debug Af Teams","description":"Return team names from api-football /teams for a given league/season.","operationId":"admin_debug_af_teams_api_admin_debug_af_teams_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"type":"integer","default":2026,"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Debug Af Teams Api Admin Debug Af Teams Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/sync-fixture-stats/{fixture_id}":{"post":{"summary":"Admin Sync Fixture Stats","description":"Force-sync stats for a single fixture and return what was fetched from api-football.","operationId":"admin_sync_fixture_stats_api_admin_sync_fixture_stats__fixture_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Sync Fixture Stats Api Admin Sync Fixture Stats  Fixture Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/debug-af-fixtures":{"get":{"summary":"Admin Debug Af Fixtures","description":"Show first 30 fixtures from api-football with date + team names for debugging.","operationId":"admin_debug_af_fixtures_api_admin_debug_af_fixtures_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"League Id"}},{"name":"season","in":"query","required":false,"schema":{"type":"integer","default":2026,"title":"Season"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Debug Af Fixtures Api Admin Debug Af Fixtures Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/generate-predictions":{"post":{"summary":"Admin Generate Predictions","description":"Run our Poisson/Elo model to generate MatchPrediction rows for upcoming fixtures.","operationId":"admin_generate_predictions_api_admin_generate_predictions_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Generate Predictions Api Admin Generate Predictions Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/backfill-predictions":{"post":{"summary":"Admin Backfill Predictions","description":"Generate predictions for finished fixtures that have no prediction yet (backfill).","operationId":"admin_backfill_predictions_api_admin_backfill_predictions_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Backfill Predictions Api Admin Backfill Predictions Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/refresh-championship":{"post":{"summary":"Admin Refresh Championship","description":"Manually trigger championship Monte Carlo cache refresh (synchronous).","operationId":"admin_refresh_championship_api_admin_refresh_championship_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Refresh Championship Api Admin Refresh Championship Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-af-predictions":{"post":{"summary":"Admin Sync Af Predictions","description":"Sync api-football AI predictions for all upcoming fixtures.","operationId":"admin_sync_af_predictions_api_admin_sync_af_predictions_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Af Predictions Api Admin Sync Af Predictions Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-events":{"post":{"summary":"Admin Sync Events","description":"Sync match events for all completed fixtures. force=true re-syncs already-synced ones.","operationId":"admin_sync_events_api_admin_sync_events_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Sync Events Api Admin Sync Events Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/sync-discipline":{"post":{"summary":"Admin Sync Discipline","description":"Sync yellow/red card leaderboards for all enabled leagues from api-football.","operationId":"admin_sync_discipline_api_admin_sync_discipline_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Discipline Api Admin Sync Discipline Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-players":{"post":{"summary":"Admin Sync Players","description":"Sync per-player match statistics for all completed fixtures.","operationId":"admin_sync_players_api_admin_sync_players_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Players Api Admin Sync Players Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-market-odds":{"post":{"summary":"Admin Sync Market Odds","description":"Sync Over/Under 2.5 and BTTS odds for all upcoming/live fixtures.","operationId":"admin_sync_market_odds_api_admin_sync_market_odds_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Market Odds Api Admin Sync Market Odds Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-h2h/{fixture_id}":{"post":{"summary":"Admin Sync H2H","description":"Sync H2H history from api-football for a specific fixture's two teams.","operationId":"admin_sync_h2h_api_admin_sync_h2h__fixture_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"fixture_id","in":"path","required":true,"schema":{"type":"integer","title":"Fixture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Sync H2H Api Admin Sync H2H  Fixture Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/sync-all-h2h":{"post":{"summary":"Admin Sync All H2H","description":"Sync H2H for all upcoming fixtures that don't already have H2H records.","operationId":"admin_sync_all_h2h_api_admin_sync_all_h2h_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync All H2H Api Admin Sync All H2H Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/train-meta":{"post":{"summary":"Admin Train Meta","description":"Train (or retrain) the meta-model stacking layer from completed fixtures.","operationId":"admin_train_meta_api_admin_train_meta_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Train Meta Api Admin Train Meta Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/train-xg":{"post":{"summary":"Admin Train Xg","description":"Train (or retrain) the xG proxy Poisson model from FixtureStat data.","operationId":"admin_train_xg_api_admin_train_xg_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Train Xg Api Admin Train Xg Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-standings":{"post":{"summary":"Admin Sync Standings","description":"Sync official standings for all enabled leagues from api-football.","operationId":"admin_sync_standings_api_admin_sync_standings_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Standings Api Admin Sync Standings Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/recalculate-elo":{"post":{"summary":"Admin Recalculate Elo","description":"Recalculate all team Elo ratings from scratch by replaying historical fixtures.","operationId":"admin_recalculate_elo_api_admin_recalculate_elo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Recalculate Elo Api Admin Recalculate Elo Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-team-stats":{"post":{"summary":"Admin Sync Team Stats","description":"Sync season stats for all teams across all enabled leagues from api-football.","operationId":"admin_sync_team_stats_api_admin_sync_team_stats_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Team Stats Api Admin Sync Team Stats Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/historical-backfill/status":{"get":{"summary":"Admin Historical Backfill Status","description":"Progress summary for the gradual api-football historical backfill.","operationId":"admin_historical_backfill_status_api_admin_historical_backfill_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Historical Backfill Status Api Admin Historical Backfill Status Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/historical-backfill/run":{"post":{"summary":"Admin Historical Backfill Run","description":"Manually trigger one backfill batch (bypassing the scheduler interval).","operationId":"admin_historical_backfill_run_api_admin_historical_backfill_run_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"batch_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Batch Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Historical Backfill Run Api Admin Historical Backfill Run Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/sync-odds-reference":{"post":{"summary":"Admin Sync Odds Reference","description":"Sync bookmaker list and bet type list from api-football reference endpoints.","operationId":"admin_sync_odds_reference_api_admin_sync_odds_reference_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Odds Reference Api Admin Sync Odds Reference Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-player-profiles":{"post":{"summary":"Admin Sync Player Profiles","description":"Sync biographical profiles for all known tournament players from api-football /players.","operationId":"admin_sync_player_profiles_api_admin_sync_player_profiles_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Player Profiles Api Admin Sync Player Profiles Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/train-models":{"post":{"summary":"Admin Train Models","description":"Train Poisson + ELO models from completed DB fixtures.\nleague_id=None trains the global model; all_leagues=true trains global + all per-league.","operationId":"admin_train_models_api_admin_train_models_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"league_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"League Id"}},{"name":"all_leagues","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"All Leagues"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Train Models Api Admin Train Models Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/compute-performance":{"post":{"summary":"Admin Compute Performance","description":"Compute and persist per-round Brier score + accuracy metrics.","operationId":"admin_compute_performance_api_admin_compute_performance_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Compute Performance Api Admin Compute Performance Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-clv":{"post":{"summary":"Admin Sync Clv","description":"Fetch closing odds from API-Football for all FT fixtures missing them, then compute CLV.","operationId":"admin_sync_clv_api_admin_sync_clv_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Clv Api Admin Sync Clv Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/train-stack":{"post":{"summary":"Admin Train Stack","description":"Kick off the full XGBoost/LightGBM/RF stacking pipeline in a background thread.\nReturns immediately; poll /api/model-insights to see when SHAP data appears.","operationId":"admin_train_stack_api_admin_train_stack_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Train Stack Api Admin Train Stack Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/full-refresh":{"post":{"summary":"Admin Full Refresh","description":"Run the full refresh pipeline in a background thread: train all models, generate\npredictions, compute performance metrics. Returns immediately; poll model-insights.","operationId":"admin_full_refresh_api_admin_full_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Full Refresh Api Admin Full Refresh Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-live":{"post":{"summary":"Admin Sync Live","description":"Manually trigger live fixture score sync from api-football.","operationId":"admin_sync_live_api_admin_sync_live_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Live Api Admin Sync Live Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-transfers":{"post":{"summary":"Admin Sync Transfers","description":"Fetch transfer history for all WC teams from api-football (/transfers?team=id).\nCosts 1 API call per unique team (typically 32 for WC2026).\nRun after sync-squads to get position data.","operationId":"admin_sync_transfers_api_admin_sync_transfers_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Transfers Api Admin Sync Transfers Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/sync-squad-scores":{"post":{"summary":"Admin Sync Squad Scores","description":"Compute and cache SquadTransferScore for all teams from stored PlayerTransfer rows.\nZero API calls — pure computation from local DB. Run after sync-transfers.","operationId":"admin_sync_squad_scores_api_admin_sync_squad_scores_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Sync Squad Scores Api Admin Sync Squad Scores Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/comments/reported":{"get":{"summary":"Admin List Reported Comments","description":"Moderation queue — comments with at least one report, worst-first.","operationId":"admin_list_reported_comments_api_admin_comments_reported_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Admin List Reported Comments Api Admin Comments Reported Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/comments/{comment_id}/moderate":{"post":{"summary":"Admin Moderate Comment","operationId":"admin_moderate_comment_api_admin_comments__comment_id__moderate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"comment_id","in":"path","required":true,"schema":{"type":"integer","title":"Comment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentModerateAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Moderate Comment Api Admin Comments  Comment Id  Moderate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/announcements":{"get":{"summary":"Admin List Announcements","description":"All announcements, including inactive/expired — for the admin manager.","operationId":"admin_list_announcements_api_admin_announcements_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Admin List Announcements Api Admin Announcements Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"summary":"Admin Create Announcement","operationId":"admin_create_announcement_api_admin_announcements_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnouncementCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Create Announcement Api Admin Announcements Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/announcements/{announcement_id}":{"put":{"summary":"Admin Update Announcement","operationId":"admin_update_announcement_api_admin_announcements__announcement_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"announcement_id","in":"path","required":true,"schema":{"type":"integer","title":"Announcement Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnouncementUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Update Announcement Api Admin Announcements  Announcement Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Admin Delete Announcement","operationId":"admin_delete_announcement_api_admin_announcements__announcement_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"announcement_id","in":"path","required":true,"schema":{"type":"integer","title":"Announcement Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/model/retrain":{"post":{"summary":"Admin Retrain","description":"Trigger full 7-model pipeline retrain in background.","operationId":"admin_retrain_api_admin_model_retrain_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Retrain Api Admin Model Retrain Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/model/rollback":{"post":{"summary":"Admin Rollback","description":"Roll back a registered model artifact by N versions.","operationId":"admin_rollback_api_admin_model_rollback_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"model_name","in":"query","required":true,"schema":{"type":"string","description":"xgboost | lightgbm | random_forest | stacker","title":"Model Name"},"description":"xgboost | lightgbm | random_forest | stacker"},{"name":"steps_back","in":"query","required":false,"schema":{"type":"integer","maximum":5,"minimum":1,"default":1,"title":"Steps Back"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Rollback Api Admin Model Rollback Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/model/registry":{"get":{"summary":"Admin Model Registry","description":"Return full model registry contents.","operationId":"admin_model_registry_api_admin_model_registry_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Model Registry Api Admin Model Registry Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/award-badges":{"post":{"summary":"Admin Award Badges","description":"Backfill badge computation for all users who have prediction history.","operationId":"admin_award_badges_api_admin_award_badges_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Award Badges Api Admin Award Badges Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/health":{"get":{"summary":"Admin Health","description":"Aggregate health snapshot: scheduler jobs, Redis, DB pool, model artifacts, api-football quota.","operationId":"admin_health_api_admin_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Admin Health Api Admin Health Get"}}}}},"security":[{"HTTPBearer":[]}]}}},"components":{"schemas":{"AnnouncementCreate":{"properties":{"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title"},"body":{"type":"string","maxLength":4000,"minLength":1,"title":"Body"},"severity":{"type":"string","title":"Severity","description":"info | warning | critical","default":"info"},"is_pinned":{"type":"boolean","title":"Is Pinned","default":false},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["title","body"],"title":"AnnouncementCreate"},"AnnouncementUpdate":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Title"},"body":{"anyOf":[{"type":"string","maxLength":4000,"minLength":1},{"type":"null"}],"title":"Body"},"severity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Severity"},"is_pinned":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Pinned"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","title":"AnnouncementUpdate"},"CommentCreate":{"properties":{"entity_type":{"$ref":"#/components/schemas/EntityTypeEnum"},"entity_id":{"type":"string","maxLength":32,"title":"Entity Id","description":"fixture_id, team_id, or player_id as string"},"body":{"type":"string","maxLength":2000,"minLength":1,"title":"Body"},"parent_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Parent Id"}},"type":"object","required":["entity_type","entity_id","body"],"title":"CommentCreate"},"CommentModerateAction":{"properties":{"action":{"type":"string","title":"Action","description":"dismiss | remove"}},"type":"object","required":["action"],"title":"CommentModerateAction"},"CommentReportCreate":{"properties":{"reason":{"type":"string","title":"Reason","description":"spam | abuse | off_topic | other"}},"type":"object","required":["reason"],"title":"CommentReportCreate"},"CommentUpdate":{"properties":{"body":{"type":"string","maxLength":2000,"minLength":1,"title":"Body"}},"type":"object","required":["body"],"title":"CommentUpdate"},"EntityTypeEnum":{"type":"string","enum":["fixture","team","player","general"],"title":"EntityTypeEnum","description":"Allowed entity types for comments. Enforced server-side — never trust the client."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"KeyCreate":{"properties":{"name":{"type":"string","maxLength":128,"title":"Name","default":""}},"type":"object","title":"KeyCreate"},"LeaguePatch":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"flag_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flag Url"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"enabled_season":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Enabled Season"}},"type":"object","title":"LeaguePatch"},"NotifHistoryPatch":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"NotifHistoryPatch"},"NotificationSettingsBody":{"properties":{"master_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Master Enabled"},"quiet_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quiet Start"},"quiet_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quiet End"},"quiet_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quiet Action"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"importance":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Importance"}},"type":"object","title":"NotificationSettingsBody"},"ProfileUpsert":{"properties":{"username":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Username"},"avatar_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Avatar Url"},"favorite_team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Favorite Team Id"},"bio":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Bio"},"social_links":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Social Links"},"is_public":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Public"}},"type":"object","title":"ProfileUpsert"},"PushSubBody":{"properties":{"endpoint":{"type":"string","title":"Endpoint"},"p256dh":{"type":"string","title":"P256Dh"},"auth":{"type":"string","title":"Auth"},"ua_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ua Hint"}},"type":"object","required":["endpoint","p256dh","auth"],"title":"PushSubBody"},"TeamSubBody":{"properties":{"notify_goals":{"type":"boolean","title":"Notify Goals","default":true},"notify_cards":{"type":"boolean","title":"Notify Cards","default":true},"notify_results":{"type":"boolean","title":"Notify Results","default":true},"notify_lineup":{"type":"boolean","title":"Notify Lineup","default":false}},"type":"object","title":"TeamSubBody"},"UserPickBody":{"properties":{"pick":{"type":"string","title":"Pick"},"display_name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Display Name"}},"type":"object","required":["pick"],"title":"UserPickBody"},"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"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}