{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/auth/register":{"post":{"tags":["auth"],"summary":"Register","operationId":"register_api_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/verify":{"post":{"tags":["auth"],"summary":"Verify","operationId":"verify_api_auth_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/token":{"post":{"tags":["auth"],"summary":"Login","operationId":"login_api_auth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_login_api_auth_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/forgot":{"post":{"tags":["auth"],"summary":"Forgot Password","operationId":"forgot_password_api_auth_forgot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ForgotRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/reset":{"post":{"tags":["auth"],"summary":"Reset Password","operationId":"reset_password_api_auth_reset_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ResetRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/me":{"get":{"tags":["auth"],"summary":"Get Me","operationId":"get_me_api_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/recommend":{"post":{"tags":["baseline"],"summary":"Recommend Heroes","operationId":"recommend_heroes_api_recommend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaselineRecommendRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/winrate":{"post":{"tags":["baseline"],"summary":"Predict Winrate","operationId":"predict_winrate_api_winrate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WinRateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/winrate/batch":{"post":{"tags":["baseline"],"summary":"Predict Winrate Batch","description":"Score up to 150 drafts in ONE dynamic-batch model invoke.\n\nSame per-row contract as /api/winrate (unknown shortName -> the model's\n\"unknown\" slot, >5 heroes truncated to 5, empty draft -> exact 50/50);\nresults come back in input order.","operationId":"predict_winrate_batch_api_winrate_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WinRateBatchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bp_tree":{"post":{"tags":["baseline"],"summary":"Bp Tree Endpoint","operationId":"bp_tree_endpoint_api_bp_tree_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BPTreeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bp_autoplay":{"post":{"tags":["baseline"],"summary":"Bp Autoplay Endpoint","description":"Fast-forward: model plays top-1 for [current, target) in one round-trip\n(deep-play ②; user-confirmed client-side before this is ever called).","operationId":"bp_autoplay_endpoint_api_bp_autoplay_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BPAutoplayRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/model/version":{"get":{"tags":["baseline"],"summary":"Get Model Version","operationId":"get_model_version_api_model_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/pro/recommend":{"post":{"tags":["pro"],"summary":"Recommend Pro Heroes","operationId":"recommend_pro_heroes_api_pro_recommend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProRecommendRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/pro/winrate":{"post":{"tags":["pro"],"summary":"Predict Pro Winrate","operationId":"predict_pro_winrate_api_pro_winrate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProWinRateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/plus/recommend":{"post":{"tags":["plus"],"summary":"Recommend Plus Heroes","operationId":"recommend_plus_heroes_api_plus_recommend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusRecommendRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/plus/winrate":{"post":{"tags":["plus"],"summary":"Predict Plus Winrate","operationId":"predict_plus_winrate_api_plus_winrate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlusWinRateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live-matches":{"get":{"tags":["live"],"summary":"Get Live Matches","operationId":"get_live_matches_api_live_matches_get","parameters":[{"name":"snapshot","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Snapshot"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live-matches/recent":{"get":{"tags":["live"],"summary":"Get Recent Matches","operationId":"get_recent_matches_api_live_matches_recent_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"stats_window","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Stats Window"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/content/hero-tier-list":{"get":{"tags":["content"],"summary":"Hero Tier List Json","operationId":"hero_tier_list_json_api_content_hero_tier_list_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/content/hero-tier-list/highrank":{"get":{"tags":["content"],"summary":"Hero Tier List Highrank Json","operationId":"hero_tier_list_highrank_json_api_content_hero_tier_list_highrank_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/content/hero-tier-list/brackets":{"get":{"tags":["content"],"summary":"Hero Tier List Brackets Json","operationId":"hero_tier_list_brackets_json_api_content_hero_tier_list_brackets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/content/hero-momentum":{"get":{"tags":["content"],"summary":"Hero Momentum Json","operationId":"hero_momentum_json_api_content_hero_momentum_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/content/hero-counters":{"get":{"tags":["content"],"summary":"Hero Counters Json","operationId":"hero_counters_json_api_content_hero_counters_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/content/hero-synergy":{"get":{"tags":["content"],"summary":"Hero Synergy Json","operationId":"hero_synergy_json_api_content_hero_synergy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/explain":{"post":{"tags":["explain"],"summary":"Explain Pick","operationId":"explain_pick_api_explain_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExplainRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dota/duration":{"post":{"tags":["duration"],"summary":"Duration Curve","operationId":"duration_curve_api_dota_duration_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WinRateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/contact":{"post":{"tags":["contact"],"summary":"Submit Contact","operationId":"submit_contact_api_contact_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/heroes":{"get":{"tags":["deadlock"],"summary":"Heroes","operationId":"heroes_api_deadlock_heroes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/deadlock/player/{account_id}":{"get":{"tags":["deadlock"],"summary":"Player","operationId":"player_api_deadlock_player__account_id__get","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"integer","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/predict/draft":{"post":{"tags":["deadlock"],"summary":"Predict Draft","operationId":"predict_draft_api_deadlock_predict_draft_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/recommend":{"post":{"tags":["deadlock"],"summary":"Recommend Last Pick","description":"Pick suggester: score every remaining hero in the open slot (one\nbatched onnx run) and return the top 6. `delta` is percentage points vs\nthe average candidate.","operationId":"recommend_last_pick_api_deadlock_recommend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/predict/live":{"post":{"tags":["deadlock"],"summary":"Predict Live","operationId":"predict_live_api_deadlock_predict_live_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/og/{kind}/{a}/{b}":{"get":{"tags":["deadlock"],"summary":"Deadlock Pair Og","description":"1200x630 share-card PNG for a Deadlock matchup/synergy pair page, so the\npage URL unfurls a per-pair card on Discord/X/Reddit (the viral surface).","operationId":"deadlock_pair_og_api_deadlock_og__kind___a___b__get","parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}},{"name":"a","in":"path","required":true,"schema":{"type":"string","title":"A"}},{"name":"b","in":"path","required":true,"schema":{"type":"string","title":"B"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/og/draft":{"get":{"tags":["deadlock"],"summary":"Deadlock Draft Og","description":"6v6 draft share card for /s/deadlock. Hero ids come from the URL; the win\nprobability is recomputed by the draft model here, so it can't be spoofed.","operationId":"deadlock_draft_og_api_deadlock_og_draft_get","parameters":[{"name":"t0","in":"query","required":false,"schema":{"type":"string","default":"","title":"T0"}},{"name":"t1","in":"query","required":false,"schema":{"type":"string","default":"","title":"T1"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/deadlock/content/tier-list":{"get":{"tags":["deadlock"],"summary":"Deadlock Tier List","operationId":"deadlock_tier_list_api_deadlock_content_tier_list_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/deadlock/content/counters":{"get":{"tags":["deadlock"],"summary":"Deadlock Counters","operationId":"deadlock_counters_api_deadlock_content_counters_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/deadlock/content/synergy":{"get":{"tags":["deadlock"],"summary":"Deadlock Synergy","operationId":"deadlock_synergy_api_deadlock_content_synergy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/deadlock/content/ban-rates":{"get":{"tags":["deadlock"],"summary":"Deadlock Ban Rates","operationId":"deadlock_ban_rates_api_deadlock_content_ban_rates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/deadlock/content/hero-momentum":{"get":{"tags":["deadlock"],"summary":"Deadlock Momentum","operationId":"deadlock_momentum_api_deadlock_content_hero_momentum_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/deadlock/content/tier-list/brackets":{"get":{"tags":["deadlock"],"summary":"Deadlock Tier Brackets","operationId":"deadlock_tier_brackets_api_deadlock_content_tier_list_brackets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/lol/predict":{"post":{"tags":["lol"],"summary":"Predict","operationId":"predict_api_lol_predict_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lol/duration":{"post":{"tags":["lol"],"summary":"Duration Curve","description":"Partial- or full-draft duration curve (0 = unpicked role slot).","operationId":"duration_curve_api_lol_duration_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lol/model":{"get":{"tags":["lol"],"summary":"Model Info","operationId":"model_info_api_lol_model_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/predict/draft":{"post":{"tags":["marvel-rivals"],"summary":"Predict Draft","operationId":"predict_draft_api_marvel_rivals_predict_draft_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marvel-rivals/recommend":{"post":{"tags":["marvel-rivals"],"summary":"Recommend Last Pick","description":"Pick suggester (0 = empty slot). Same contract as the Deadlock\n/recommend: with a partial-draft model and `team`, that side's first empty\nslot is filled; otherwise exactly one empty slot is required and\ncandidates are scored as COMPLETE 6v6 lineups. One pair of batched onnx\nruns. `delta` is percentage points vs the average candidate.","operationId":"recommend_last_pick_api_marvel_rivals_recommend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/marvel-rivals/heroes":{"get":{"tags":["marvel-rivals"],"summary":"Heroes","operationId":"heroes_api_marvel_rivals_heroes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/content/tier-list":{"get":{"tags":["marvel-rivals"],"summary":"Tier List","operationId":"tier_list_api_marvel_rivals_content_tier_list_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/content/counters":{"get":{"tags":["marvel-rivals"],"summary":"Counters","operationId":"counters_api_marvel_rivals_content_counters_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/content/synergy":{"get":{"tags":["marvel-rivals"],"summary":"Synergy","operationId":"synergy_api_marvel_rivals_content_synergy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/content/ban-rates":{"get":{"tags":["marvel-rivals"],"summary":"Ban Rates","operationId":"ban_rates_api_marvel_rivals_content_ban_rates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/content/hero-momentum":{"get":{"tags":["marvel-rivals"],"summary":"Hero Momentum","operationId":"hero_momentum_api_marvel_rivals_content_hero_momentum_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/marvel-rivals/content/tier-list/brackets":{"get":{"tags":["marvel-rivals"],"summary":"Tier Brackets","operationId":"tier_brackets_api_marvel_rivals_content_tier_list_brackets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/newsletter/subscribe":{"post":{"tags":["newsletter"],"summary":"Subscribe Newsletter","operationId":"subscribe_newsletter_api_newsletter_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/newsletter/unsubscribe":{"get":{"tags":["newsletter"],"summary":"Unsubscribe","description":"GET (recipient clicks the footer link) returns a confirmation page; POST is\nthe RFC 8058 List-Unsubscribe-Post one-click that mailbox providers send.","operationId":"unsubscribe_api_newsletter_unsubscribe_get","parameters":[{"name":"e","in":"query","required":false,"schema":{"type":"string","default":"","title":"E"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["newsletter"],"summary":"Unsubscribe","description":"GET (recipient clicks the footer link) returns a confirmation page; POST is\nthe RFC 8058 List-Unsubscribe-Post one-click that mailbox providers send.","operationId":"unsubscribe_api_newsletter_unsubscribe_get","parameters":[{"name":"e","in":"query","required":false,"schema":{"type":"string","default":"","title":"E"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/newsletter/resubscribe":{"get":{"tags":["newsletter"],"summary":"Resubscribe","operationId":"resubscribe_api_newsletter_resubscribe_get","parameters":[{"name":"e","in":"query","required":false,"schema":{"type":"string","default":"","title":"E"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/newsletter/subscribe-game":{"get":{"tags":["newsletter"],"summary":"Subscribe Game","operationId":"subscribe_game_api_newsletter_subscribe_game_get","parameters":[{"name":"e","in":"query","required":false,"schema":{"type":"string","default":"","title":"E"}},{"name":"g","in":"query","required":false,"schema":{"type":"string","default":"","title":"G"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/newsletter/resend-webhook":{"post":{"tags":["newsletter"],"summary":"Resend Webhook","operationId":"resend_webhook_api_newsletter_resend_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/rank/winrate":{"post":{"tags":["rank"],"summary":"Predict Rank Winrate","operationId":"predict_rank_winrate_api_rank_winrate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RankWinRateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/rank/version":{"get":{"tags":["rank"],"summary":"Get Rank Model Version","operationId":"get_rank_model_version_api_rank_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/dota-live/recommend":{"post":{"tags":["dota-live"],"summary":"Recommend","description":"One stateless call -> win% + item recs + (optional) skill rec.","operationId":"recommend_api_dota_live_recommend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveSnapshot"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dota-live/health":{"get":{"tags":["dota-live"],"summary":"Health","description":"Liveness + what's loaded (for the overlay to gate on / for QA).","operationId":"health_api_dota_live_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/og/pair/{kind}/{a}/{b}":{"get":{"tags":["share"],"summary":"Og Dota Pair","description":"Share-card PNG for a Dota matchup/synergy pair page (/dota2/{matchup,synergy}/a/b).","operationId":"og_dota_pair_api_og_pair__kind___a___b__get","parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}},{"name":"a","in":"path","required":true,"schema":{"type":"string","title":"A"}},{"name":"b","in":"path","required":true,"schema":{"type":"string","title":"B"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/og/hero/dota2/{slug}":{"get":{"tags":["share"],"summary":"Og Dota Hero","description":"Per-hero share-card image for /dota2/hero/<slug>. The hero page's og:image\npoints here (slug is fixed per page, so no /s/ landing needed).","operationId":"og_dota_hero_api_og_hero_dota2__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/og/{slug}":{"get":{"tags":["share"],"summary":"Og Image","operationId":"og_image_api_og__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"r","in":"query","required":false,"schema":{"type":"string","default":"","title":"R"}},{"name":"d","in":"query","required":false,"schema":{"type":"string","default":"","title":"D"}},{"name":"rr","in":"query","required":false,"schema":{"type":"string","default":"","title":"Rr"}},{"name":"dr","in":"query","required":false,"schema":{"type":"string","default":"","title":"Dr"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/s/deadlock":{"get":{"tags":["share"],"summary":"Deadlock Share Page","description":"Share landing for a Deadlock 6v6 draft (hero ids in t0/t1). Registered\nbefore /s/{slug} so this specific path wins. The card + CTA reproduce the same\ndraft; the win rate is recomputed server-side by /api/deadlock/og/draft.","operationId":"deadlock_share_page_s_deadlock_get","parameters":[{"name":"t0","in":"query","required":false,"schema":{"type":"string","default":"","title":"T0"}},{"name":"t1","in":"query","required":false,"schema":{"type":"string","default":"","title":"T1"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/s/{slug}":{"get":{"tags":["share"],"summary":"Share Page","operationId":"share_page_s__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"r","in":"query","required":false,"schema":{"type":"string","default":"","title":"R"}},{"name":"d","in":"query","required":false,"schema":{"type":"string","default":"","title":"D"}},{"name":"rr","in":"query","required":false,"schema":{"type":"string","default":"","title":"Rr"}},{"name":"dr","in":"query","required":false,"schema":{"type":"string","default":"","title":"Dr"}},{"name":"rt","in":"query","required":false,"schema":{"type":"string","default":"","title":"Rt"}},{"name":"dt","in":"query","required":false,"schema":{"type":"string","default":"","title":"Dt"}},{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/version":{"get":{"tags":["system"],"summary":"Get Version","description":"Build provenance of the *running* container. GIT_SHA / BUILD_TIME are\nbaked in by the GitHub Actions build (--build-arg); 'unknown' means a local\nor pre-instrumentation image. The live sha is the ground truth for what's\ndeployed -- diff it locally with `git log <sha>..HEAD` to see what changed.","operationId":"get_version_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/healthz":{"get":{"tags":["system"],"summary":"Healthz","description":"Readiness probe for the load balancer / rolling deploy.\n\nReturns 200 only once the core Dota model is loaded, so a rolling restart\nwon't route traffic to a replica that is still prefetching (or whose prefetch\nfailed). Deadlock and Marvel Rivals readiness is reported but does NOT gate\nhealth: an isolated fetch failure of one of those models must not pull the\nwhole site out of rotation (its endpoints already 503 on their own until\nthe first model set lands). The extra keys exist so an external probe can\nsee \"up but a model never loaded\" (the status code alone cannot).\n\nCheap and side-effect-free -- checks module state only, never runs a model or\nlazily constructs a predictor.","operationId":"healthz_healthz_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"head":{"tags":["system"],"summary":"Healthz","description":"Readiness probe for the load balancer / rolling deploy.\n\nReturns 200 only once the core Dota model is loaded, so a rolling restart\nwon't route traffic to a replica that is still prefetching (or whose prefetch\nfailed). Deadlock and Marvel Rivals readiness is reported but does NOT gate\nhealth: an isolated fetch failure of one of those models must not pull the\nwhole site out of rotation (its endpoints already 503 on their own until\nthe first model set lands). The extra keys exist so an external probe can\nsee \"up but a model never loaded\" (the status code alone cannot).\n\nCheap and side-effect-free -- checks module state only, never runs a model or\nlazily constructs a predictor.","operationId":"healthz_healthz_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/data/heroes":{"get":{"tags":["data"],"summary":"Get Heroes","operationId":"get_heroes_api_data_heroes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/data/presets":{"get":{"tags":["data"],"summary":"Get Presets","operationId":"get_presets_api_data_presets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/data/pro_teams":{"get":{"tags":["data"],"summary":"Get Pro Teams","operationId":"get_pro_teams_api_data_pro_teams_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/data/pro_players":{"get":{"tags":["data"],"summary":"Get Pro Players","operationId":"get_pro_players_api_data_pro_players_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/consent-region":{"get":{"tags":["privacy"],"summary":"Consent Region","description":"Return whether this request should see the analytics consent choice.\n\n`CF-IPCountry` is added by Cloudflare IP Geolocation on production traffic.\nA missing/unknown value fails closed so an edge-header outage or direct-origin\nrequest cannot silently enable analytics. Local and preview hosts never call\nthis endpoint because the client-side production-host gate runs first.\nThe response must never be shared by a CDN cache between visitors.","operationId":"consent_region_api_consent_region_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/keys":{"get":{"tags":["keys"],"summary":"Get Key","operationId":"get_key_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["keys"],"summary":"Create Key","description":"Get-or-create: idempotent, so the /developers button can't mint dupes.","operationId":"create_key_api_keys_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/keys/rotate":{"post":{"tags":["keys"],"summary":"Rotate Key","description":"Revoke every active key for this user and mint a fresh one.","operationId":"rotate_key_api_keys_rotate_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/prefs/patch-alerts/unsubscribe":{"get":{"tags":["prefs"],"summary":"Patch Alerts Unsubscribe","operationId":"patch_alerts_unsubscribe_api_prefs_patch_alerts_unsubscribe_get","parameters":[{"name":"e","in":"query","required":false,"schema":{"type":"string","default":"","title":"E"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prefs/weekly-recap/unsubscribe":{"get":{"tags":["prefs"],"summary":"Weekly Recap Unsubscribe","operationId":"weekly_recap_unsubscribe_api_prefs_weekly_recap_unsubscribe_get","parameters":[{"name":"e","in":"query","required":false,"schema":{"type":"string","default":"","title":"E"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prefs":{"get":{"tags":["prefs"],"summary":"Get Prefs","operationId":"get_prefs_api_prefs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["prefs"],"summary":"Put Prefs","operationId":"put_prefs_api_prefs_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrefsPayload"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/auth/steam/login":{"get":{"tags":["auth"],"summary":"Steam Login","operationId":"steam_login_api_auth_steam_login_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/steam/callback":{"get":{"tags":["auth"],"summary":"Steam Callback","operationId":"steam_callback_api_auth_steam_callback_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/me/dota/profile":{"get":{"tags":["me"],"summary":"My Dota Profile","operationId":"my_dota_profile_api_me_dota_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/me/steam/unlink":{"post":{"tags":["me"],"summary":"Unlink Steam","operationId":"unlink_steam_api_me_steam_unlink_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/me":{"delete":{"tags":["me"],"summary":"Delete Me","operationId":"delete_me_api_me_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/me/password":{"post":{"tags":["me"],"summary":"Change Password","description":"Set/change the password. Email-only accounts must prove the current\npassword (a stolen JWT alone must not be enough for takeover). Steam-linked\naccounts may set one without it — their stored hash is the unusable random\nfrom steam signup, and Steam login itself is the strong proof.","operationId":"change_password_api_me_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordChange"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/me/email":{"post":{"tags":["me"],"summary":"Request Email Change","operationId":"request_email_change_api_me_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/me/email/confirm":{"post":{"tags":["me"],"summary":"Confirm Email Change","operationId":"confirm_email_change_api_me_email_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailConfirm"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/me/newsletter":{"get":{"tags":["me"],"summary":"Newsletter Status","operationId":"newsletter_status_api_me_newsletter_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["me"],"summary":"Newsletter Toggle","operationId":"newsletter_toggle_api_me_newsletter_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterToggle"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/dota2/scout":{"post":{"tags":["scout"],"summary":"Scout Report","operationId":"scout_report_api_dota2_scout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/dota2/plans":{"get":{"tags":["plans"],"summary":"List Plans","operationId":"list_plans_api_dota2_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["plans"],"summary":"Create Plan","operationId":"create_plan_api_dota2_plans_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/dota2/plans/{plan_id}":{"delete":{"tags":["plans"],"summary":"Delete Plan","operationId":"delete_plan_api_dota2_plans__plan_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"integer","title":"Plan Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/{full_path}":{"head":{"summary":"Serve Frontend","description":"Two-in-One Architecture:\nServe Nuxt SSG files directly from FastAPI. No Nginx required.","operationId":"serve_frontend__full_path__head","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Serve Frontend","description":"Two-in-One Architecture:\nServe Nuxt SSG files directly from FastAPI. No Nginx required.","operationId":"serve_frontend__full_path__head","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BPAutoplayRequest":{"properties":{"fp_picks":{"items":{"type":"string"},"type":"array","title":"Fp Picks"},"sp_picks":{"items":{"type":"string"},"type":"array","title":"Sp Picks"},"banned_heroes":{"items":{"type":"string"},"type":"array","title":"Banned Heroes"},"current_step_idx":{"type":"integer","title":"Current Step Idx","default":0},"target_step_idx":{"type":"integer","title":"Target Step Idx","default":0},"radiant_is_fp":{"type":"boolean","title":"Radiant Is Fp","default":true},"user_team":{"anyOf":[{"type":"string","enum":["FP","SP"]},{"type":"null"}],"title":"User Team"},"hero_pool":{"items":{"type":"string"},"type":"array","maxItems":150,"title":"Hero Pool"},"opp_team":{"anyOf":[{"type":"string","enum":["FP","SP"]},{"type":"null"}],"title":"Opp Team"},"opp_pool":{"items":{"type":"string"},"type":"array","maxItems":150,"title":"Opp Pool"}},"type":"object","title":"BPAutoplayRequest","description":"Fast-forward (deep-play ②, 2026-09-10): the model plays its top pick for\nevery step from current up to (not including) target, one server round-trip.\nClient-side this is CONFIRMED by the user first (owner: never guess intent\nfrom a bare timeline tap) and replayed through the same path a ?seq= URL\ntakes, so rollback keeps working."},"BPTreeRequest":{"properties":{"fp_picks":{"items":{"type":"string"},"type":"array","title":"Fp Picks"},"sp_picks":{"items":{"type":"string"},"type":"array","title":"Sp Picks"},"banned_heroes":{"items":{"type":"string"},"type":"array","title":"Banned Heroes"},"current_step_idx":{"type":"integer","title":"Current Step Idx","default":0},"radiant_is_fp":{"type":"boolean","title":"Radiant Is Fp","default":true},"depth":{"type":"integer","title":"Depth","default":2},"branching_factor":{"type":"integer","title":"Branching Factor","default":3},"user_team":{"anyOf":[{"type":"string","enum":["FP","SP"]},{"type":"null"}],"title":"User Team"},"hero_pool":{"items":{"type":"string"},"type":"array","maxItems":150,"title":"Hero Pool"},"opp_team":{"anyOf":[{"type":"string","enum":["FP","SP"]},{"type":"null"}],"title":"Opp Team"},"opp_pool":{"items":{"type":"string"},"type":"array","maxItems":150,"title":"Opp Pool"}},"type":"object","title":"BPTreeRequest"},"BaselineRecommendRequest":{"properties":{"radiant":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Radiant"},"dire":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Dire"},"is_our_team_dire":{"type":"boolean","title":"Is Our Team Dire","default":false},"hero_pool":{"items":{"type":"string"},"type":"array","maxItems":150,"title":"Hero Pool"}},"type":"object","required":["radiant","dire"],"title":"BaselineRecommendRequest"},"Body_login_api_auth_token_post":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"password"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_login_api_auth_token_post"},"ContactRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"email":{"type":"string","maxLength":200,"minLength":3,"title":"Email"},"organization":{"type":"string","maxLength":160,"title":"Organization","default":""},"subject":{"type":"string","maxLength":200,"title":"Subject","default":""},"message":{"type":"string","maxLength":5000,"minLength":1,"title":"Message"},"website":{"type":"string","maxLength":200,"title":"Website","default":""}},"type":"object","required":["name","email","message"],"title":"ContactRequest"},"DraftReq":{"properties":{"team0_heroes":{"items":{"type":"integer"},"type":"array","maxItems":6,"minItems":6,"title":"Team0 Heroes"},"team1_heroes":{"items":{"type":"integer"},"type":"array","maxItems":6,"minItems":6,"title":"Team1 Heroes"}},"type":"object","required":["team0_heroes","team1_heroes"],"title":"DraftReq"},"EmailConfirm":{"properties":{"code":{"type":"string","title":"Code"}},"type":"object","required":["code"],"title":"EmailConfirm"},"EmailRequest":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"EmailRequest"},"ExplainRequest":{"properties":{"hero_key":{"type":"string","title":"Hero Key"},"ally":{"items":{"type":"string"},"type":"array","title":"Ally","default":[]},"enemy":{"items":{"type":"string"},"type":"array","title":"Enemy","default":[]},"win_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Win Rate"},"lang":{"type":"string","enum":["en","ru","zh"],"title":"Lang","default":"en"}},"type":"object","required":["hero_key"],"title":"ExplainRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LiveReq":{"properties":{"team0_heroes":{"items":{"type":"integer"},"type":"array","maxItems":6,"minItems":6,"title":"Team0 Heroes"},"team1_heroes":{"items":{"type":"integer"},"type":"array","maxItems":6,"minItems":6,"title":"Team1 Heroes"},"state":{"$ref":"#/components/schemas/LiveState"}},"type":"object","required":["team0_heroes","team1_heroes","state"],"title":"LiveReq"},"LiveSnapshot":{"properties":{"radiant_heroes":{"items":{"type":"integer"},"type":"array","maxItems":5,"minItems":1,"title":"Radiant Heroes"},"dire_heroes":{"items":{"type":"integer"},"type":"array","maxItems":5,"minItems":1,"title":"Dire Heroes"},"my_index":{"type":"integer","maximum":9.0,"minimum":0.0,"title":"My Index"},"my_items":{"items":{"type":"integer"},"type":"array","title":"My Items"},"minute":{"type":"number","title":"Minute","default":0.0},"my_gold":{"type":"number","title":"My Gold","default":0.0},"my_net_worth":{"type":"number","title":"My Net Worth","default":0.0},"my_level":{"type":"number","title":"My Level","default":1.0},"my_last_hits":{"type":"number","title":"My Last Hits","default":0.0},"my_kills":{"type":"number","title":"My Kills","default":0.0},"my_deaths":{"type":"number","title":"My Deaths","default":0.0},"my_assists":{"type":"number","title":"My Assists","default":0.0},"team_kill_lead":{"type":"number","title":"Team Kill Lead","default":0.0},"my_ability_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"My Ability Ids"},"top_k":{"type":"integer","maximum":15.0,"minimum":1.0,"title":"Top K","default":5}},"type":"object","required":["radiant_heroes","dire_heroes","my_index"],"title":"LiveSnapshot","description":"Self-contained GSI-observable snapshot (the overlay's reduced state).\n\nEvery field is derivable from live Game State Integration. `team_kill_lead`\nis my team's kills minus the enemy team's (public scoreboard). `my_index` is\n0-4 for a Radiant slot, 5-9 for a Dire slot (index into radiant+dire). Items\nand ability ids are the raw Dota ids (== what GSI emits)."},"LiveState":{"properties":{"game_time_s":{"type":"number","title":"Game Time S"},"nw_diff":{"type":"number","title":"Nw Diff","default":0},"kills_diff":{"type":"number","title":"Kills Diff","default":0},"tower_diff":{"type":"number","title":"Tower Diff","default":0},"midboss_diff":{"type":"number","title":"Midboss Diff","default":0}},"type":"object","required":["game_time_s"],"title":"LiveState"},"NewsletterToggle":{"properties":{"subscribed":{"type":"boolean","title":"Subscribed"}},"type":"object","required":["subscribed"],"title":"NewsletterToggle"},"PasswordChange":{"properties":{"current_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Password"},"new_password":{"type":"string","title":"New Password"}},"type":"object","required":["new_password"],"title":"PasswordChange"},"PlanCreate":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"},"seq":{"type":"string","maxLength":2000,"title":"Seq","default":""},"fp":{"type":"boolean","title":"Fp","default":true},"side_radiant":{"type":"boolean","title":"Side Radiant","default":true},"opp_pool":{"type":"string","maxLength":2000,"title":"Opp Pool","default":""}},"type":"object","required":["name"],"title":"PlanCreate"},"PlusRecommendRequest":{"properties":{"radiant":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Radiant"},"dire":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Dire"},"radiant_roles":{"items":{"type":"integer"},"type":"array","title":"Radiant Roles"},"dire_roles":{"items":{"type":"integer"},"type":"array","title":"Dire Roles"},"is_our_team_dire":{"type":"boolean","title":"Is Our Team Dire","default":false},"hero_pool":{"items":{"type":"string"},"type":"array","maxItems":150,"title":"Hero Pool"}},"type":"object","required":["radiant","dire","radiant_roles","dire_roles"],"title":"PlusRecommendRequest"},"PlusWinRateRequest":{"properties":{"radiant":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Radiant"},"dire":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Dire"},"radiant_roles":{"items":{"type":"integer"},"type":"array","title":"Radiant Roles"},"dire_roles":{"items":{"type":"integer"},"type":"array","title":"Dire Roles"}},"type":"object","required":["radiant","dire","radiant_roles","dire_roles"],"title":"PlusWinRateRequest"},"PredictReq":{"properties":{"blue":{"items":{"type":"integer"},"type":"array","maxItems":5,"minItems":5,"title":"Blue"},"red":{"items":{"type":"integer"},"type":"array","maxItems":5,"minItems":5,"title":"Red"}},"type":"object","required":["blue","red"],"title":"PredictReq"},"PrefsPayload":{"properties":{"fav_heroes":{"anyOf":[{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Fav Heroes"},"bpsim_history":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Bpsim History"},"patch_alerts":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Patch Alerts"},"weekly_recap":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekly Recap"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"}},"type":"object","title":"PrefsPayload"},"ProRecommendRequest":{"properties":{"radiant":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Radiant"},"dire":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Dire"},"radiant_players":{"items":{"type":"integer"},"type":"array","title":"Radiant Players"},"dire_players":{"items":{"type":"integer"},"type":"array","title":"Dire Players"},"is_our_team_dire":{"type":"boolean","title":"Is Our Team Dire","default":false}},"type":"object","required":["radiant","dire","radiant_players","dire_players"],"title":"ProRecommendRequest"},"ProWinRateRequest":{"properties":{"radiant":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Radiant"},"dire":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Dire"},"radiant_players":{"items":{"type":"integer"},"type":"array","title":"Radiant Players"},"dire_players":{"items":{"type":"integer"},"type":"array","title":"Dire Players"}},"type":"object","required":["radiant","dire","radiant_players","dire_players"],"title":"ProWinRateRequest"},"RankWinRateRequest":{"properties":{"radiant":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Radiant"},"dire":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Dire"},"rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rank","default":0}},"type":"object","title":"RankWinRateRequest"},"RecommendReq":{"properties":{"team0_heroes":{"items":{"type":"integer"},"type":"array","maxItems":6,"minItems":6,"title":"Team0 Heroes"},"team1_heroes":{"items":{"type":"integer"},"type":"array","maxItems":6,"minItems":6,"title":"Team1 Heroes"},"team":{"anyOf":[{"type":"integer","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Team"}},"type":"object","required":["team0_heroes","team1_heroes"],"title":"RecommendReq"},"ScoutRequest":{"properties":{"players":{"items":{"type":"string"},"type":"array","title":"Players"}},"type":"object","required":["players"],"title":"ScoutRequest"},"SubscribeRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"game":{"type":"string","title":"Game","default":""}},"type":"object","required":["email"],"title":"SubscribeRequest"},"Token":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type"}},"type":"object","required":["access_token","token_type"],"title":"Token"},"UserCreate":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"}},"type":"object","required":["email","password"],"title":"UserCreate"},"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"},"VerifyRequest":{"properties":{"email":{"type":"string","title":"Email"},"code":{"type":"string","title":"Code"},"newsletter":{"type":"boolean","title":"Newsletter","default":false},"game":{"type":"string","title":"Game","default":""}},"type":"object","required":["email","code"],"title":"VerifyRequest"},"WinRateBatchRequest":{"properties":{"drafts":{"items":{"$ref":"#/components/schemas/WinRateRequest"},"type":"array","maxItems":150,"minItems":1,"title":"Drafts"}},"type":"object","required":["drafts"],"title":"WinRateBatchRequest"},"WinRateRequest":{"properties":{"radiant":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Radiant"},"dire":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Dire"}},"type":"object","required":["radiant","dire"],"title":"WinRateRequest"},"_ForgotRequest":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"_ForgotRequest"},"_ResetRequest":{"properties":{"email":{"type":"string","title":"Email"},"code":{"type":"string","title":"Code"},"new_password":{"type":"string","title":"New Password"}},"type":"object","required":["email","code","new_password"],"title":"_ResetRequest"}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"token"}}}}}}