{"openapi":"3.1.0","info":{"title":"Sport Cash Combi","description":"Sport Cash Combi — système intelligent de pari sportif EV+ multi-sport","version":"0.1.0"},"paths":{"/healthcheck":{"get":{"tags":["health"],"summary":"Liveness probe","description":"Vérifie que le process est vivant. Pas de check dépendances.","operationId":"healthcheck_healthcheck_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness probe","description":"Vérifie que le service ET ses dépendances sont prêts.","operationId":"readiness_readiness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}}}}},"/version":{"get":{"tags":["health"],"summary":"Version info","description":"Retourne la version de l'app.","operationId":"version_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Version Version Get"}}}}}}},"/admin/ml/clv-by-model":{"get":{"tags":["admin-ml"],"summary":"CLV moyen agrégé par modèle (admin)","description":"Retourne la liste agrégée + récap global.","operationId":"clv_by_model_admin_ml_clv_by_model_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":90,"title":"Since Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Clv By Model Admin Ml Clv By Model Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/model-versions":{"get":{"tags":["admin-ml"],"summary":"Toutes les versions de modèles + métriques","operationId":"list_all_model_versions_admin_ml_model_versions_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"}},{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","description":"Si true, retourne seulement is_active=true","default":false,"title":"Active Only"},"description":"Si true, retourne seulement is_active=true"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModelVersionRead"},"title":"Response List All Model Versions Admin Ml Model Versions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/calibration":{"get":{"tags":["admin-ml"],"summary":"Calibration metrics (bins + Brier + log-loss + ECE)","description":"Bins de calibration + Brier + log-loss + ECE + MCE.\n\nRéférence : `architecture_traitement_mlops.md` §11.","operationId":"calibration_metrics_admin_ml_calibration_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"model_type","in":"query","required":false,"schema":{"type":"string","default":"dixon_coles","title":"Model Type"}},{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"n_bins","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":2,"default":10,"title":"N Bins"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calibration Metrics Admin Ml Calibration Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/feature-importance":{"get":{"tags":["admin-ml"],"summary":"Feature importance — params Dixon-Coles attack/defense","description":"Renvoie attack/defense Dixon-Coles depuis ModelVersion.params.\n\nPour le robot Lot 11 : à étendre avec SHAP global pour les modèles\nboostés (XGBoost player props).","operationId":"feature_importance_admin_ml_feature_importance_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"type":"string","default":"football","title":"Sport Code"}},{"name":"model_type","in":"query","required":false,"schema":{"type":"string","default":"dixon_coles","title":"Model Type"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Feature Importance Admin Ml Feature Importance Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/sharp-agreement":{"get":{"tags":["admin-ml"],"summary":"Accord modèle vs sharp consensus (Pinnacle dévigé)","description":"Compare proba modèle vs proba implicite Pinnacle dévigée.\n\nPour chaque event où on a la fois une Prediction et une cote\nPinnacle, on compare. Retourne :\n- n_compared\n- agreement_pct : % où |p_model - p_sharp_devig| < 5%\n- scatter : liste de points (p_model, p_sharp_devig)","operationId":"sharp_agreement_admin_ml_sharp_agreement_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"type":"string","default":"football","title":"Sport Code"}},{"name":"model_type","in":"query","required":false,"schema":{"type":"string","default":"dixon_coles","title":"Model Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sharp Agreement Admin Ml Sharp Agreement Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/retrain":{"post":{"tags":["admin-ml"],"summary":"Déclenche un retraining du modèle (stub MVP — Phase 3 prod)","description":"Déclenche un retraining. En MVP, on log juste et on retourne\nune task_id factice. Phase 3 : émettre via Prefect.","operationId":"trigger_retrain_admin_ml_retrain_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"type":"string","default":"football","title":"Sport Code"}},{"name":"model_type","in":"query","required":false,"schema":{"type":"string","default":"dixon_coles","title":"Model Type"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Trigger Retrain Admin Ml Retrain Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/model-versions/{sport_code}/{model_type}/{league_slug}/{version}/promote":{"post":{"tags":["admin-ml"],"summary":"Promouvoir un candidate -> active (atomic swap + audit log).","description":"Promote un model_version candidate -> active.\n\nWorkflow :\n1. Verifier que le model_version cible existe ET est candidate.\n2. Snapshot des metriques de l'ancien champion (audit).\n3. Transaction : ancien champion is_active=false, candidate is_active=true\n   + is_candidate=false, promoted_at + promoted_by_user_id.\n4. NOTIFY 'model_promoted' (Brique F future : workers vont LISTEN).\n5. Audit log via admin_alert kind='ml_model_promoted'.","operationId":"promote_model_version_admin_ml_model_versions__sport_code___model_type___league_slug___version__promote_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"path","required":true,"schema":{"type":"string","title":"Sport Code"}},{"name":"model_type","in":"path","required":true,"schema":{"type":"string","title":"Model Type"}},{"name":"league_slug","in":"path","required":true,"schema":{"type":"string","title":"League Slug"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Promote Model Version Admin Ml Model Versions  Sport Code   Model Type   League Slug   Version  Promote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/model-versions/{sport_code}/{model_type}/{league_slug}/{version}/reject":{"post":{"tags":["admin-ml"],"summary":"Rejeter un candidate (is_candidate=false + audit).","description":"Rejette un candidate. Pas de DELETE : garde la trace en DB.","operationId":"reject_model_version_admin_ml_model_versions__sport_code___model_type___league_slug___version__reject_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"path","required":true,"schema":{"type":"string","title":"Sport Code"}},{"name":"model_type","in":"path","required":true,"schema":{"type":"string","title":"Model Type"}},{"name":"league_slug","in":"path","required":true,"schema":{"type":"string","title":"League Slug"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reject Model Version Admin Ml Model Versions  Sport Code   Model Type   League Slug   Version  Reject Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/model-versions/{sport_code}/{model_type}/{league_slug}/{version}/demote":{"post":{"tags":["admin-ml"],"summary":"Retrograder un active recemment promu (PLAN F5 - rollback urgent).","description":"Retrograde un active -> inactive + reactive l'ancien champion (PLAN F5).\n\nUse case : detection ROI dégradé 24h post-promote. Admin clique\nRétrograder sur la page arena.\n\nCherche l'ancien champion (rang 2 par trained_at desc, is_active=false)\net le re-active. Si aucun -> reject silencieux le current sans\nre-activer (admin doit manuellement promote autre chose).","operationId":"demote_model_version_admin_ml_model_versions__sport_code___model_type___league_slug___version__demote_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"path","required":true,"schema":{"type":"string","title":"Sport Code"}},{"name":"model_type","in":"path","required":true,"schema":{"type":"string","title":"Model Type"}},{"name":"league_slug","in":"path","required":true,"schema":{"type":"string","title":"League Slug"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemoteBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Demote Model Version Admin Ml Model Versions  Sport Code   Model Type   League Slug   Version  Demote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/probability-distribution":{"get":{"tags":["admin-ml"],"summary":"Histogramme des probabilites predites pour une version donnee (R2 sparkline champion vs candidate).","description":"Histogramme (n_bins) des probabilites predites par cette version.\n\nSi version pas presente dans predictions -> tous les bins a 0\n(cas typique d'un candidate qui n'a pas encore predit en prod\nhors shadow Phase 2.5).","operationId":"probability_distribution_admin_ml_probability_distribution_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":true,"schema":{"type":"string","title":"Sport Code"}},{"name":"model_type","in":"query","required":true,"schema":{"type":"string","title":"Model Type"}},{"name":"league_slug","in":"query","required":true,"schema":{"type":"string","title":"League Slug"}},{"name":"version","in":"query","required":true,"schema":{"type":"string","title":"Version"}},{"name":"n_bins","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":2,"default":10,"title":"N Bins"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":10,"default":5000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Probability Distribution Admin Ml Probability Distribution Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/candidates":{"get":{"tags":["admin-ml"],"summary":"Liste tous les candidates en attente de validation.","description":"Liste les model_versions is_candidate=true (en attente humaine).\n\nSert pour l'UI arena qui doit afficher les candidates + leurs metriques\na cote de leur champion respectif.","operationId":"list_candidates_admin_ml_candidates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Candidates Admin Ml Candidates Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/ml/audit-log":{"get":{"tags":["admin-ml"],"summary":"Historique immuable des actions admin ML (R5 PLAN_ML_AUTO_RETRAIN).","description":"Liste les entrees du audit log, plus recent d'abord.","operationId":"list_audit_log_admin_ml_audit_log_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par action (ml_promote_model_version, etc.)","title":"Action"},"description":"Filtre par action (ml_promote_model_version, etc.)"},{"name":"target_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par type de cible (model_version)","title":"Target Type"},"description":"Filtre par type de cible (model_version)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Audit Log Admin Ml Audit Log Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/sessions":{"get":{"tags":["admin-security"],"summary":"Listing sessions actives toutes users","operationId":"list_sessions_admin_sessions_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"}},{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Active Only"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/src__routers__admin_security__SessionRead"},"title":"Response List Sessions Admin Sessions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/sessions/{session_id}":{"delete":{"tags":["admin-security"],"summary":"Révoque une session (force logout user)","operationId":"revoke_session_admin_sessions__session_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/security/rbac":{"get":{"tags":["admin-security"],"summary":"Matrice RBAC roles × permissions","operationId":"get_rbac_admin_security_rbac_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RbacMatrix"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/security/audit-log":{"get":{"tags":["admin-security"],"summary":"Viewer admin_audit_log avec filtres (action, target_type, since).","operationId":"get_audit_log_admin_security_audit_log_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Since Days"}},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Action"}},{"name":"target_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Target Type"}},{"name":"actor_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/security/rotate-encryption-key":{"post":{"tags":["admin-security"],"summary":"Trigger rotation ENCRYPTION_MASTER_KEY (stub MVP)","operationId":"rotate_encryption_key_admin_security_rotate_encryption_key_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Rotate Encryption Key Admin Security Rotate Encryption Key Post"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/security/2fa-policy":{"get":{"tags":["admin-security"],"summary":"Lecture policy 2FA admin + statut enforcement.","operationId":"get_2fa_policy_admin_security_2fa_policy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorPolicyOut"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["admin-security"],"summary":"Active/desactive policy 2FA admin. Anti self-lock : active toujours avec grace period (default 24h) pour laisser les admins sans 2FA temps de setup. Audit log obligatoire.","operationId":"update_2fa_policy_admin_security_2fa_policy_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorPolicyUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorPolicyOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/security/ip-whitelist":{"get":{"tags":["admin-security"],"summary":"Liste les IP/CIDR whitelistes + statut enforcement.","operationId":"list_ip_whitelist_admin_security_ip_whitelist_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhitelistResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["admin-security"],"summary":"Ajoute une entree IP/CIDR a la whitelist.","operationId":"add_ip_whitelist_admin_security_ip_whitelist_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhitelistAdd"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhitelistEntryOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/security/ip-whitelist/{entry_id}":{"delete":{"tags":["admin-security"],"summary":"Supprime une entree IP whitelist.","operationId":"delete_ip_whitelist_admin_security_ip_whitelist__entry_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/security/ip-whitelist/enforce":{"put":{"tags":["admin-security"],"summary":"Toggle ip whitelist enforcement. Anti self-lock : si activation, on auto-add l'IP fournie (typiquement celle du request admin).","operationId":"toggle_ip_whitelist_enforce_admin_security_ip_whitelist_enforce_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhitelistEnforceUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhitelistResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/sources/health":{"get":{"tags":["admin-sources"],"summary":"Liste toutes les sources avec etat circuit + metrics derives","operationId":"get_sources_health_admin_sources_health_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"status_filter","in":"query","required":false,"schema":{"enum":["all","healthy","degraded","silent","open"],"type":"string","default":"all","title":"Status Filter"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcesHealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/sources/{source}/reset_circuit":{"post":{"tags":["admin-sources"],"summary":"Reset circuit breaker d'une source (admin)","operationId":"reset_circuit_admin_sources__source__reset_circuit_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string","minLength":2,"maxLength":50,"title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CircuitResetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/sources/raw/recent":{"get":{"tags":["admin-sources"],"summary":"Derniers raw_source_payloads (debug, max 50)","operationId":"get_recent_raw_payloads_admin_sources_raw_recent_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"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 Get Recent Raw Payloads Admin Sources Raw Recent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/summary":{"get":{"tags":["analytics"],"summary":"KPI cards globales pour le filtre courant","operationId":"value_bets_summary_me_analytics_value_bets_summary_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"}},{"name":"bet_result","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"won/lost/push/void/half_won/half_lost/pending","title":"Bet Result"},"description":"won/lost/push/void/half_won/half_lost/pending"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"min_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Ev"}},{"name":"max_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Ev"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","description":"Filtre accessibility FR : anj_only / with_brokers / all","default":"all","title":"Access Mode"},"description":"Filtre accessibility FR : anj_only / with_brokers / all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KpiSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/items":{"get":{"tags":["analytics"],"summary":"Liste paginee des value bets pour la table BI","operationId":"value_bets_items_me_analytics_value_bets_items_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"}},{"name":"bet_result","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bet Result"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"min_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Ev"}},{"name":"max_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Ev"}},{"name":"settled_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Settled Only"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Access Mode"}},{"name":"order_by","in":"query","required":false,"schema":{"type":"string","description":"opened_at_desc/opened_at_asc/ev_desc/pnl_desc","default":"opened_at_desc","title":"Order By"},"description":"opened_at_desc/opened_at_asc/ev_desc/pnl_desc"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"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":"array","items":{"$ref":"#/components/schemas/ValueBetItem"},"title":"Response Value Bets Items Me Analytics Value Bets Items Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/equity-curve":{"get":{"tags":["analytics"],"summary":"Courbe d'equity (PnL cumulative + drawdown) jour par jour","operationId":"value_bets_equity_curve_me_analytics_value_bets_equity_curve_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Access Mode"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/src__routers__analytics__EquityPoint"},"title":"Response Value Bets Equity Curve Me Analytics Value Bets Equity Curve Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/export.csv":{"get":{"tags":["analytics"],"summary":"Export CSV de TOUS les value bets filtres (pas limite 500)","description":"Export CSV streaming. Filtres identiques aux endpoints items/summary.\n\nPas de pagination — on retourne tout (jusqu'a max_rows=200k).","operationId":"value_bets_export_csv_me_analytics_value_bets_export_csv_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"}},{"name":"bet_result","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bet Result"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"min_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Ev"}},{"name":"max_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Ev"}},{"name":"settled_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Settled Only"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Access Mode"}},{"name":"max_rows","in":"query","required":false,"schema":{"type":"integer","maximum":200000,"minimum":1,"default":50000,"title":"Max Rows"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/equity-curve-by-model":{"get":{"tags":["analytics"],"summary":"Equity curve avec overlay 1 ligne par model_type (Phase F.11)","description":"Renvoie 1 serie d'equity curve par model_type pour comparaison visuelle.","operationId":"value_bets_equity_curve_by_model_me_analytics_value_bets_equity_curve_by_model_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Access Mode"}},{"name":"min_samples_per_model","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"default":20,"title":"Min Samples Per Model"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EquitySeries"},"title":"Response Value Bets Equity Curve By Model Me Analytics Value Bets Equity Curve By Model Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/equity-curve-by-sport":{"get":{"tags":["analytics"],"summary":"Equity curve avec overlay 1 ligne par sport_code (Phase G.6.2)","description":"Renvoie 1 serie d'equity curve par sport_code pour comparaison visuelle.\n\nSi sport_code unique fourni : la query filtre sur ce sport, retourne\n1 seule serie. Si comma-separated (filtre multi-select), splitte par sport.","operationId":"value_bets_equity_curve_by_sport_me_analytics_value_bets_equity_curve_by_sport_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Access Mode"}},{"name":"min_samples_per_sport","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"default":20,"title":"Min Samples Per Sport"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EquitySeries"},"title":"Response Value Bets Equity Curve By Sport Me Analytics Value Bets Equity Curve By Sport Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/model-comparison":{"get":{"tags":["analytics"],"summary":"Compare le ROI/Sharpe des differents model_type (Phase F.6 auto-tuning)","description":"Compare les performances des differents model_type pour identifier\nle 'champion' a privilegier sur cette categorie.\n\nSert de base au futur cron auto-tuning : reconfigure les weights ensemble\nou desactive un model qui sous-performe.","operationId":"value_bets_model_comparison_me_analytics_value_bets_model_comparison_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"min_samples","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"N min pour inclure le model dans le classement","default":20,"title":"Min Samples"},"description":"N min pour inclure le model dans le classement"},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Access Mode"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelComparisonResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/admin-alerts":{"get":{"tags":["analytics"],"summary":"Liste les alertes admin (drift ML, etc.) — F.10 fix","description":"Liste les alertes admin pour affichage UI.","operationId":"list_admin_alerts_me_analytics_admin_alerts_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"pending/sent/acknowledged/dismissed","title":"Status"},"description":"pending/sent/acknowledged/dismissed"},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"unacknowledged_only","in":"query","required":false,"schema":{"type":"boolean","description":"Affiche seulement les alertes non acquittees (sur la colonne acknowledged_at). Plus utile que le filtre `status` vu que le worker drift_monitor cree les alertes directement en status='sent' (jamais 'pending').","default":false,"title":"Unacknowledged Only"},"description":"Affiche seulement les alertes non acquittees (sur la colonne acknowledged_at). Plus utile que le filtre `status` vu que le worker drift_monitor cree les alertes directement en status='sent' (jamais 'pending')."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AdminAlertRead"},"title":"Response List Admin Alerts Me Analytics Admin Alerts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/admin-alerts/{alert_id}/acknowledge":{"post":{"tags":["analytics"],"summary":"Acknowledge une alerte (admin)","description":"Marque une alerte comme acknowledged (admin l'a vue).","operationId":"acknowledge_admin_alert_me_analytics_admin_alerts__alert_id__acknowledge_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","title":"Alert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Acknowledge Admin Alert Me Analytics Admin Alerts  Alert Id  Acknowledge Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/shrinkage/refresh":{"post":{"tags":["analytics"],"summary":"Force le recalcul des facteurs shrinkage (admin)","description":"Lance one_cycle() du worker shrinkage et retourne le nb d'entrees calculees. Utile pour ne pas attendre le cron 6h apres ajout de paris settled.","operationId":"shrinkage_force_refresh_me_analytics_shrinkage_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"integer"},{"type":"string"}]},"type":"object","title":"Response Shrinkage Force Refresh Me Analytics Shrinkage Refresh Post"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/analytics/shrinkage-factors":{"get":{"tags":["analytics"],"summary":"Table des facteurs de shrinkage anti-overfitting (Phase F.3)","description":"Liste les facteurs de shrinkage calcules par categorie.\n\nShrink < 1 = on doit reduire l'EV estime par ce ratio (modele overconfident).\nShrink ~ 1 = modele bien calibre.\nShrink > 1 = modele underconfident (rare, fait remonter plus de candidates).","operationId":"shrinkage_factors_me_analytics_shrinkage_factors_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ShrinkageEntry"},"title":"Response Shrinkage Factors Me Analytics Shrinkage Factors Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/analytics/value-bets/facets":{"get":{"tags":["analytics"],"summary":"Compte des facettes (leagues/markets/bookies/...) pour l'UI filter panel","operationId":"value_bets_facets_me_analytics_value_bets_facets_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FacetCounts"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/audit-log":{"get":{"tags":["audit-log"],"summary":"Liste des entrées audit log du user","operationId":"list_entries_me_audit_log_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"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 Entries Me Audit Log Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/audit-log/verify":{"get":{"tags":["audit-log"],"summary":"Vérifie l'intégrité de la hash chain de l'user","operationId":"verify_me_audit_log_verify_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Verify Me Audit Log Verify Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/register":{"post":{"tags":["auth"],"summary":"Register a new user","description":"Enregistre un nouvel utilisateur.","operationId":"register_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/login":{"post":{"tags":["auth"],"summary":"Login","description":"Connexion : vérifie credentials, génère tokens.","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/refresh":{"post":{"tags":["auth"],"summary":"Refresh access token","description":"Refresh tokens avec rotation et reuse detection.","operationId":"refresh_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/logout":{"post":{"tags":["auth"],"summary":"Logout (revoke current session)","description":"Logout : révoque la session courante.","operationId":"logout_auth_logout_post","responses":{"204":{"description":"Successful Response"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/me":{"get":{"tags":["auth"],"summary":"Get current user info","description":"Retourne les infos de l'utilisateur courant.","operationId":"me_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/2fa/setup":{"post":{"tags":["auth"],"summary":"Setup 2FA TOTP (returns secret + backup codes)","description":"Initie la configuration 2FA.\n\nRetourne secret + backup codes à n'envoyer qu'une fois.\nL'utilisateur doit ensuite confirmer avec /2fa/verify.","operationId":"setup_2fa_auth_2fa_setup_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TOTPSetupResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/2fa/verify":{"post":{"tags":["auth"],"summary":"Verify 2FA setup and enable it","description":"Confirme l'activation 2FA en vérifiant un code TOTP.","operationId":"verify_2fa_auth_2fa_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TOTPVerifyRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/2fa/disable":{"post":{"tags":["auth"],"summary":"Disable 2FA TOTP (requires password + valid TOTP code)","description":"Désactive 2FA TOTP. Reverify password + code en cours obligatoire.\n\nAuto-audit via admin_audit_log (action=user_2fa_disabled).","operationId":"disable_2fa_auth_2fa_disable_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Disable2FARequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/change-password":{"post":{"tags":["auth"],"summary":"Change password (requires current password, revokes other sessions)","description":"Change le mot de passe et révoque les autres sessions.\n\nAuto-audit via admin_audit_log (action=user_password_changed).\nForce ré-auth sur tous les devices sauf le courant.","operationId":"change_password_auth_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/auto-bet/rules":{"get":{"tags":["auto-bet"],"summary":"List Rules","operationId":"list_rules_me_auto_bet_rules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/RuleRead"},"type":"array","title":"Response List Rules Me Auto Bet Rules Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["auto-bet"],"summary":"Create Rule","operationId":"create_rule_me_auto_bet_rules_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleUpsert"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/auto-bet/rules/{rule_id}":{"patch":{"tags":["auto-bet"],"summary":"Update Rule","operationId":"update_rule_me_auto_bet_rules__rule_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleUpsert"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["auto-bet"],"summary":"Delete Rule","operationId":"delete_rule_me_auto_bet_rules__rule_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/auto-bet/rules/{rule_id}/accept-disclaimer":{"post":{"tags":["auto-bet"],"summary":"Accepte le disclaimer juridique pour passer en mode AUTO réel","operationId":"accept_disclaimer_me_auto_bet_rules__rule_id__accept_disclaimer_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/auto-bet/kill-switch":{"get":{"tags":["auto-bet"],"summary":"Get Kill Switch","operationId":"get_kill_switch_me_auto_bet_kill_switch_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KillSwitchRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/auto-bet/kill-switch/pause":{"post":{"tags":["auto-bet"],"summary":"PAUSE GLOBAL — coupe tout l'auto-bet en < 1s","operationId":"pause_all_me_auto_bet_kill_switch_pause_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"reason","in":"query","required":false,"schema":{"type":"string","default":"manual","title":"Reason"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KillSwitchRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/auto-bet/kill-switch/resume":{"post":{"tags":["auto-bet"],"summary":"Resume All","operationId":"resume_all_me_auto_bet_kill_switch_resume_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KillSwitchRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/backtest":{"post":{"tags":["backtest"],"summary":"Backtest 1-N stratégies sur l'historique value_bet_outcomes","operationId":"run_backtest_me_backtest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BacktestBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BacktestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/backtest/save":{"post":{"tags":["backtest"],"summary":"Sauvegarder un run de backtest (M6)","operationId":"save_run_me_backtest_save_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveRunBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedRunRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/backtest/history":{"get":{"tags":["backtest"],"summary":"Historique des runs sauvegardés (M6)","operationId":"list_runs_me_backtest_history_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SavedRunRead"},"title":"Response List Runs Me Backtest History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/backtest/{run_id}":{"get":{"tags":["backtest"],"summary":"Détail d'un run sauvegardé (M6)","operationId":"get_run_me_backtest__run_id__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedRunDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["backtest"],"summary":"Supprimer un run sauvegardé (M6)","operationId":"delete_run_me_backtest__run_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Delete Run Me Backtest  Run Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/backtest/{run_id}/export":{"get":{"tags":["backtest"],"summary":"Export d'un run sauvegardé (M6) — JSON ou CSV des top bets","operationId":"export_run_me_backtest__run_id__export_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}},{"name":"format","in":"query","required":false,"schema":{"enum":["json","csv"],"type":"string","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/backtest/edge-finder":{"post":{"tags":["backtest"],"summary":"Exploration auto des slices rentables (M7)","operationId":"edge_finder_me_backtest_edge_finder_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BacktestBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Edge Finder Me Backtest Edge Finder Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/backtest/walk-forward":{"post":{"tags":["backtest"],"summary":"Walk-forward in-sample/out-of-sample (M8 — détection overfit)","operationId":"walk_forward_me_backtest_walk_forward_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalkForwardBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Walk Forward Me Backtest Walk Forward Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/bankroll/consolidated":{"get":{"tags":["bankroll"],"summary":"Bankroll consolidé multi-comptes (EUR)","operationId":"get_consolidated_bankroll_me_bankroll_consolidated_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"target_currency","in":"query","required":false,"schema":{"type":"string","minLength":3,"maxLength":3,"default":"EUR","title":"Target Currency"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsolidatedBankroll"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/bankroll/history":{"get":{"tags":["bankroll"],"summary":"Équity curve bankroll (PnL cumulé settled)","operationId":"get_bankroll_history_me_bankroll_history_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"days_back","in":"query","required":false,"schema":{"type":"integer","maximum":730,"minimum":1,"default":90,"title":"Days Back"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EquityCurveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/bankroll/allocations":{"post":{"tags":["bankroll"],"summary":"Crée/met à jour une allocation de stratégie","operationId":"upsert_allocation_me_bankroll_allocations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankrollAllocationUpsert"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankrollAllocationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/bankroll/allocations/{strategy_slug}":{"delete":{"tags":["bankroll"],"summary":"Supprime une allocation","operationId":"delete_allocation_me_bankroll_allocations__strategy_slug__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"strategy_slug","in":"path","required":true,"schema":{"type":"string","title":"Strategy Slug"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/bankroll/pause":{"post":{"tags":["bankroll"],"summary":"Met en pause une allocation (kill-switch stratégie)","operationId":"pause_allocation_me_bankroll_pause_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"strategy_slug","in":"query","required":true,"schema":{"type":"string","title":"Strategy Slug"}},{"name":"reason","in":"query","required":false,"schema":{"type":"string","default":"manual","title":"Reason"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankrollAllocationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/bets":{"post":{"tags":["bets"],"summary":"Enregistrer un pari au journal","operationId":"create_bet_me_bets_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["bets"],"summary":"Liste des paris (paginée, filtrable)","operationId":"list_my_bets_me_bets_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/BetStatus"},{"type":"null"}],"description":"Filtre par statut","title":"Status"},"description":"Filtre par statut"},{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"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":{"$ref":"#/components/schemas/BetsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/bets/{bet_id}":{"get":{"tags":["bets"],"summary":"Détail d'un pari","operationId":"get_bet_me_bets__bet_id__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"bet_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bet Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["bets"],"summary":"Mise à jour partielle","operationId":"patch_bet_me_bets__bet_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"bet_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bet Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["bets"],"summary":"Supprimer un pari","operationId":"delete_bet_me_bets__bet_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"bet_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Bet Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/me/checkout":{"post":{"tags":["billing"],"summary":"Crée une session Stripe Checkout pour upgrade","operationId":"create_checkout_billing_me_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/billing/me/portal":{"post":{"tags":["billing"],"summary":"Crée une session Stripe Customer Portal (carte, factures, annulation)","description":"Permet à l'utilisateur de gérer son abonnement (carte, factures,\ncancel) via le portail Stripe hébergé.\n\nPré-requis : avoir un stripe_customer_id (créé après un premier\ncheckout réussi). Sinon 409.","operationId":"create_billing_portal_billing_me_portal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPortalRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPortalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/billing/me/subscription":{"get":{"tags":["billing"],"summary":"Lecture de la souscription courante (plan, statut, échéance)","description":"Retourne la souscription courante du tenant du user.\n\nSi aucune sub trouvée => plan_tier='free' (cohérent avec UX).","operationId":"read_my_subscription_billing_me_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/src__routers__billing__SubscriptionRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/bookie-restrictions":{"get":{"tags":["bookie-restrictions"],"summary":"List Restrictions","description":"Liste mes restrictions. Par défaut, filtre is_active=true uniquement\n(UX : on cache les desactivees). `include_inactive=true` pour voir\nl'historique complet (panel \"Tous\").","operationId":"list_restrictions_me_bookie_restrictions_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RestrictionRead"},"title":"Response List Restrictions Me Bookie Restrictions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["bookie-restrictions"],"summary":"Add Restriction","operationId":"add_restriction_me_bookie_restrictions_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestrictionUpsert"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestrictionRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/bookie-restrictions/{restriction_id}":{"patch":{"tags":["bookie-restrictions"],"summary":"Patch Restriction","description":"Patch partiel d'une restriction. Sert notamment au soft-delete\n(`{\"is_active\": false}`) et a la re-activation\n(`{\"is_active\": true}`).","operationId":"patch_restriction_me_bookie_restrictions__restriction_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"restriction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Restriction Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestrictionPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestrictionRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["bookie-restrictions"],"summary":"Delete Restriction","description":"Hard-delete (RGPD right to erasure). Pour desactiver sans perdre\nl'historique, utiliser PATCH avec `{\"is_active\": false}`.","operationId":"delete_restriction_me_bookie_restrictions__restriction_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"restriction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Restriction Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/brokers/balances":{"get":{"tags":["brokers"],"summary":"Solde courant pour chaque broker connecté","operationId":"list_balances_me_brokers_balances_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrokerAccountSnapshotsListResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/brokers/{source_slug}/history":{"get":{"tags":["brokers"],"summary":"Historique des snapshots de solde pour un broker","operationId":"get_history_me_brokers__source_slug__history_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"source_slug","in":"path","required":true,"schema":{"type":"string","title":"Source Slug"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrokerAccountSnapshotsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/builder/analyze":{"post":{"tags":["builder"],"summary":"Analyse un combiné (EV, corrélation)","operationId":"analyze_combo_builder_analyze_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/src__routers__builder__ComboAnalyzeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/src__routers__builder__ComboAnalyzeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/builder/optimize":{"post":{"tags":["builder"],"summary":"Propose 3 combinés optimisés (greedy MVP)","description":"Sélectionne des sous-ensembles de value bets minimisant la\ncorrélation et maximisant l'EV combinée.\n\nMVP : greedy. Phase 2 : pulp/ILP.","operationId":"optimize_combo_builder_optimize_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"target_size","in":"query","required":false,"schema":{"type":"integer","default":3,"title":"Target Size"}},{"name":"max_correlation","in":"query","required":false,"schema":{"type":"number","default":0.3,"title":"Max Correlation"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OptimizeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/coach/chat":{"post":{"tags":["coach-ia"],"summary":"Coach IA — réponse synchrone","operationId":"coach_chat_coach_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/coach/chat/stream":{"post":{"tags":["coach-ia"],"summary":"Coach IA — streaming SSE","operationId":"coach_chat_stream_coach_chat_stream_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChatRequest"}}},"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":[]}]}},"/coach/contextual":{"post":{"tags":["coach"],"summary":"Coach IA contextualisé par route (Groq llama-3.3-70b en Phase 2)","description":"En MVP : heuristique locale + tip par route.\n\nPhase 2 (Lot 9 plein) : appel Groq llama-3.3-70b avec :\n- system prompt = \"Tu es l'assistant SCC. Route: X. Stats user: ROI=Y, top sport=Z\"\n- user message = question\n- RAG sur les 11 docs SCC indexés dans pgvector","operationId":"contextual_chat_coach_contextual_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextualRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextualResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/coach/daily-suggestions":{"get":{"tags":["coach"],"summary":"3 suggestions quotidiennes contextualisées","description":"Pour le widget dashboard. Phase 2 : Groq + cache Redis 24h.","operationId":"daily_suggestions_coach_daily_suggestions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Daily Suggestions Coach Daily Suggestions Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/combo/analyze":{"post":{"tags":["combo"],"summary":"Analyse un combiné : EV combiné + Kelly stake","operationId":"analyze_combo_analyze_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/src__routers__combo__ComboAnalyzeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/src__routers__combo__ComboAnalyzeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/combo/optimize":{"get":{"tags":["combo"],"summary":"Selectionne les meilleurs combines parmi les value bets live","description":"Cherche les meilleurs combines parmi les value_bets actuellement live.\n\nApproche : enumeration sur top N candidates (par EV desc) avec filtres :\n- 1 jambe max par event (independance)\n- EV combine >= min_ev_combo\n- P(combine) >= min_proba_combo\n- Score = ev - lambda * correlation_penalty","operationId":"optimize_combo_endpoint_combo_optimize_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"min_legs","in":"query","required":false,"schema":{"type":"integer","maximum":8,"minimum":2,"default":2,"title":"Min Legs"}},{"name":"max_legs","in":"query","required":false,"schema":{"type":"integer","maximum":8,"minimum":2,"default":4,"title":"Max Legs"}},{"name":"min_ev_combo","in":"query","required":false,"schema":{"type":"number","maximum":2.0,"minimum":0,"description":"EV min combo (0.05 = 5%)","default":0.05,"title":"Min Ev Combo"},"description":"EV min combo (0.05 = 5%)"},{"name":"min_proba_combo","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0,"description":"Probabilite minimale combo (filtre les paris trop risques)","default":0.1,"title":"Min Proba Combo"},"description":"Probabilite minimale combo (filtre les paris trop risques)"},{"name":"correlation_lambda","in":"query","required":false,"schema":{"type":"number","maximum":5.0,"minimum":0,"default":0.5,"title":"Correlation Lambda"}},{"name":"n_candidates","in":"query","required":false,"schema":{"type":"integer","maximum":80,"minimum":2,"description":"Top N candidates a explorer","default":40,"title":"N Candidates"},"description":"Top N candidates a explorer"},{"name":"top_n","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":15,"title":"Top N"}},{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","description":"anj_only/with_brokers/all","default":"with_brokers","title":"Access Mode"},"description":"anj_only/with_brokers/all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OptimizeComboResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/me/profile":{"get":{"tags":["community"],"summary":"Mon profil (peut être null si non créé)","operationId":"get_my_profile_community_me_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/UserProfileRead"},{"type":"null"}],"title":"Response Get My Profile Community Me Profile Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["community"],"summary":"Crée ou met à jour mon profil","operationId":"upsert_my_profile_community_me_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileUpsert"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/community/profiles/{handle}":{"get":{"tags":["community"],"summary":"Profil public d'un user par handle","operationId":"get_public_profile_community_profiles__handle__get","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string","title":"Handle"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfilePublicRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/follow/{handle}":{"post":{"tags":["community"],"summary":"Follow le user de handle donné","operationId":"follow_user_community_follow__handle__post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string","title":"Handle"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["community"],"summary":"Unfollow","operationId":"unfollow_user_community_follow__handle__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string","title":"Handle"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/me/follow/counts":{"get":{"tags":["community"],"summary":"Mes compteurs followers / following","operationId":"my_follow_counts_community_me_follow_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FollowsCountResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/community/me/inbox":{"get":{"tags":["community"],"summary":"Mes notifications in-app (follow / forum reply / etc.)","description":"Liste les notifications inbox de l'utilisateur, par defaut 50 derniers.","operationId":"list_my_inbox_community_me_inbox_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"unread_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unread Only"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List My Inbox Community Me Inbox Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/me/inbox/{notif_id}/read":{"post":{"tags":["community"],"summary":"Marquer notification comme lue","operationId":"mark_notification_read_community_me_inbox__notif_id__read_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"notif_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Notif Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mark Notification Read Community Me Inbox  Notif Id  Read Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/me/inbox/mark-all-read":{"post":{"tags":["community"],"summary":"Marquer toutes notifications comme lues","operationId":"mark_all_notifications_read_community_me_inbox_mark_all_read_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Mark All Notifications Read Community Me Inbox Mark All Read Post"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/community/bet-shares":{"post":{"tags":["community"],"summary":"Partager un de mes paris publiquement (consent RGPD)","operationId":"create_bet_share_community_bet_shares_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetShareCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetShareRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/community/bet-shares/{slug}":{"get":{"tags":["community"],"summary":"Lecture publique d'un partage","operationId":"get_bet_share_community_bet_shares__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetShareRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/community/bet-shares/{share_id}":{"delete":{"tags":["community"],"summary":"Right to erasure : supprime mon partage","operationId":"delete_bet_share_community_bet_shares__share_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"share_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Share Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/dashboard":{"get":{"tags":["dashboard"],"summary":"Layout dashboard de l'utilisateur","operationId":"get_my_dashboard_me_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["dashboard"],"summary":"Met à jour le layout (drag-drop + show/hide)","operationId":"update_my_dashboard_me_dashboard_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/data-sources/catalog":{"get":{"tags":["data-sources"],"summary":"Catalogue des sources disponibles + disclaimers","operationId":"catalog_me_data_sources_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Catalog Me Data Sources Catalog Get"}}}}}}},"/me/data-sources/active-feeds":{"get":{"tags":["data-sources"],"summary":"Sources GRATUITES qui alimentent les modèles (lecture seule)","description":"Transparence : quelles sources publiques/gratuites (Sofascore, Understat, SportsGambler, ESPN, NHL, MLB, Bluesky, Reddit...) nourrissent les prédictions, avec leur état de santé. Non configurable (vs catalog).","operationId":"active_feeds_me_data_sources_active_feeds_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Active Feeds Me Data Sources Active Feeds Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/data-sources":{"get":{"tags":["data-sources"],"summary":"Liste mes préférences sources","operationId":"list_prefs_me_data_sources_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/DataSourceCategory"},{"type":"null"}],"title":"Category"}},{"name":"enabled_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Enabled Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDataSourcePrefsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["data-sources"],"summary":"Créer/mettre à jour une préférence source","operationId":"upsert_pref_me_data_sources_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDataSourcePrefCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDataSourcePrefRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/data-sources/{pref_id}":{"patch":{"tags":["data-sources"],"summary":"Mise à jour partielle d'une préférence source","operationId":"patch_pref_me_data_sources__pref_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"pref_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Pref Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDataSourcePrefUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDataSourcePrefRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["data-sources"],"summary":"Supprimer une préférence source","operationId":"delete_pref_me_data_sources__pref_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"pref_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Pref Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/data-sources/{pref_id}/accept-disclaimer":{"post":{"tags":["data-sources"],"summary":"Accepter le disclaimer juridique (audit horodaté + IP)","operationId":"accept_disclaimer_me_data_sources__pref_id__accept_disclaimer_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"pref_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Pref Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisclaimerAcceptance"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDataSourcePrefRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/live":{"get":{"tags":["events"],"summary":"Événements en cours (status='live'). Pour mobile LivePage.","operationId":"list_live_events_events_live_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsListResponse"}}}}}}},"/events/{event_id}":{"get":{"tags":["events"],"summary":"Détail d'un événement (header match UX §18.3-A)","operationId":"get_event_events__event_id__get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events":{"get":{"tags":["events"],"summary":"Liste des événements à venir (J+within_hours)","operationId":"list_upcoming_events_events_get","parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ex: 'football'","title":"Sport Code"},"description":"Ex: 'football'"},{"name":"league_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ex: 'fr-ligue-1'","title":"League Slug"},"description":"Ex: 'fr-ligue-1'"},{"name":"within_hours","in":"query","required":false,"schema":{"type":"integer","maximum":720,"minimum":1,"default":168,"title":"Within Hours"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/qualitative/team/{team_id}":{"get":{"tags":["events-nlp"],"summary":"Événements + event_score pour 1 équipe","operationId":"get_team_event_score_events_qualitative_team__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Team Id"}},{"name":"max_age_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":365,"title":"Max Age Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventScoreResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/qualitative/by-name":{"get":{"tags":["events-nlp"],"summary":"Score événements pour une équipe non normalisée","operationId":"get_event_score_by_team_name_events_qualitative_by_name_get","parameters":[{"name":"team_name","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":200,"title":"Team Name"}},{"name":"max_age_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":365,"title":"Max Age Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventScoreResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/{event_id}/fatigue":{"get":{"tags":["fatigue"],"summary":"Get Event Fatigue","description":"Retourne les features fatigue home/away pour un event SCC.","operationId":"get_event_fatigue_events__event_id__fatigue_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FatigueResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/fatigue/coverage":{"get":{"tags":["fatigue-admin"],"summary":"Couverture des stats physiques par competition (admin).","operationId":"get_fatigue_coverage_admin_fatigue_coverage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/fatigue/by-position":{"get":{"tags":["fatigue-admin"],"summary":"Distribution physique par poste (admin).","operationId":"get_by_position_admin_fatigue_by_position_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PositionStatRow"},"type":"array","title":"Response Get By Position Admin Fatigue By Position Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/fatigue/top-players":{"get":{"tags":["fatigue-admin"],"summary":"Top N joueurs par charge (minutes + distance) sur N jours.","operationId":"get_top_players_admin_fatigue_top_players_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Since Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"order_by","in":"query","required":false,"schema":{"type":"string","pattern":"^(distance|minutes)$","default":"distance","title":"Order By"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TopPlayerRow"},"title":"Response Get Top Players Admin Fatigue Top Players Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/fatigue/team-mappings":{"get":{"tags":["fatigue-admin"],"summary":"Liste les mappings team SCC <-> external.","operationId":"list_team_mappings_admin_fatigue_team_mappings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TeamMappingOut"},"type":"array","title":"Response List Team Mappings Admin Fatigue Team Mappings Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["fatigue-admin"],"summary":"Upsert mapping (team_id, provider) -> external_team_name + validate.","operationId":"upsert_team_mapping_admin_fatigue_team_mappings_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertMappingBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMappingOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/fatigue/team-mappings/suggestions":{"get":{"tags":["fatigue-admin"],"summary":"Suggere des mappings fuzzy pour les teams sans mapping.","operationId":"suggest_team_mappings_admin_fatigue_team_mappings_suggestions_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider","in":"query","required":false,"schema":{"type":"string","default":"statsbomb","title":"Provider"}},{"name":"min_confidence","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"default":0.6,"title":"Min Confidence"}},{"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":"array","items":{"$ref":"#/components/schemas/TeamMappingSuggestion"},"title":"Response Suggest Team Mappings Admin Fatigue Team Mappings Suggestions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/fatigue/roi-bucket":{"get":{"tags":["fatigue-admin"],"summary":"ROI value bets par tranche de delta_distance_14d (home-away).","description":"Analyse empirique : la fatigue produit-elle vraiment de l'edge ?\n\nPour chaque pari settle (WON/LOST/PUSH/HALF) sur N jours :\n- compute delta_distance_14d via les services fatigue\n- bucket par tranche\n- aggrege ROI\n\nLimite a `sample_limit` events distincts pour rester rapide.","operationId":"get_roi_bucket_admin_fatigue_roi_bucket_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":7,"default":180,"title":"Since Days"}},{"name":"sample_limit","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":50,"default":500,"title":"Sample Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoiBucketResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/event/{event_id}/thread":{"get":{"tags":["forum"],"summary":"Récupère ou crée le thread de discussion pour cet event","operationId":"get_thread_for_event_forum_event__event_id__thread_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForumThreadRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/threads/{thread_id}/messages":{"get":{"tags":["forum"],"summary":"Messages du thread (pagination chronologique inverse)","operationId":"list_messages_forum_threads__thread_id__messages_get","parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Thread Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForumMessagesListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/event/{event_id}/messages":{"post":{"tags":["forum"],"summary":"Poste un message dans le thread de l'event (modération auto)","operationId":"post_message_forum_event__event_id__messages_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForumMessageCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForumMessageRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/messages/{message_id}":{"delete":{"tags":["forum"],"summary":"Supprime mon propre message","operationId":"delete_message_forum_messages__message_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Message Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/messages/{message_id}/flag":{"post":{"tags":["forum"],"summary":"Signaler un message (par n'importe quel user authentifie)","description":"User-triggered flag : ajoute reason 'user_flagged' aux moderation_reasons.\n\nLe message reste visible mais marque pour review admin. Plusieurs flags\npar message OK (deduplication par user via reasons JSONB list).","operationId":"flag_message_forum_messages__message_id__flag_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Message Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Flag Message Forum Messages  Message Id  Flag Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/admin/messages/{message_id}/hide":{"post":{"tags":["forum"],"summary":"Admin : masquer un message + broadcast WS chat.admin_action","operationId":"admin_hide_message_forum_admin_messages__message_id__hide_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Message Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Hide Message Forum Admin Messages  Message Id  Hide Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/admin/messages/{message_id}/unhide":{"post":{"tags":["forum"],"summary":"Admin : restaurer un message hide (false positive moderation)","operationId":"admin_unhide_message_forum_admin_messages__message_id__unhide_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Message Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Unhide Message Forum Admin Messages  Message Id  Unhide Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/admin/threads/{thread_id}/lock":{"post":{"tags":["forum"],"summary":"Admin : verrouille un thread (composer disabled pour tous)","operationId":"admin_lock_thread_forum_admin_threads__thread_id__lock_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Thread Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Lock Thread Forum Admin Threads  Thread Id  Lock Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/admin/threads/{thread_id}/unlock":{"post":{"tags":["forum"],"summary":"Admin : deverrouille un thread","operationId":"admin_unlock_thread_forum_admin_threads__thread_id__unlock_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Thread Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Unlock Thread Forum Admin Threads  Thread Id  Unlock Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/admin/threads":{"get":{"tags":["forum"],"summary":"Admin : liste des threads recents (panel moderation)","operationId":"admin_list_threads_forum_admin_threads_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"locked_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Locked Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin List Threads Forum Admin Threads Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/forum/admin/flagged":{"get":{"tags":["forum"],"summary":"Admin : liste des messages flagged en attente review","operationId":"admin_list_flagged_forum_admin_flagged_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin List Flagged Forum Admin Flagged Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/gdpr/export":{"post":{"tags":["gdpr"],"summary":"Right to access (art. 15 RGPD) — JSON complet","operationId":"export_my_data_me_gdpr_export_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/gdpr/delete":{"post":{"tags":["gdpr"],"summary":"Right to erasure (art. 17 RGPD) — anonymise + supprime","operationId":"delete_my_data_me_gdpr_delete_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Delete My Data Me Gdpr Delete Post"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/hedge/2way":{"post":{"tags":["hedge"],"summary":"Calcul hedge 2-way (OU, BTTS, AH demi)","operationId":"calculate_hedge_2way_hedge_2way_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Hedge2WayRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HedgeResultRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/hedge/1x2":{"post":{"tags":["hedge"],"summary":"Calcul hedge 3-way (1X2)","operationId":"calculate_hedge_1x2_hedge_1x2_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Hedge1X2Request"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HedgeResultRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/insights":{"get":{"tags":["insights"],"summary":"Insights statistiques sur le journal de paris","operationId":"get_insights_me_insights_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Insights Me Insights Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/leaderboard":{"get":{"tags":["community"],"summary":"Top users par ROI (30j ou all-time)","operationId":"get_leaderboard_leaderboard_get","parameters":[{"name":"window","in":"query","required":false,"schema":{"enum":["30d","all"],"type":"string","default":"30d","title":"Window"}},{"name":"top_k","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Top K"}},{"name":"min_bets","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"default":30,"title":"Min Bets"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Leaderboard Leaderboard Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/strategies":{"get":{"tags":["marketplace"],"summary":"Liste des stratégies publiées","operationId":"list_published_marketplace_strategies_get","parameters":[{"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 Published Marketplace Strategies Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["marketplace"],"summary":"Publier une nouvelle stratégie","operationId":"create_strategy_marketplace_strategies_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/strategies/{slug}/subscribe":{"post":{"tags":["marketplace"],"summary":"Souscrire à une stratégie","operationId":"subscribe_marketplace_strategies__slug__subscribe_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/src__routers__marketplace__SubscriptionRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["marketplace"],"summary":"Annuler son abonnement a une strategie","operationId":"unsubscribe_marketplace_strategies__slug__subscribe_delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unsubscribe Marketplace Strategies  Slug  Subscribe Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/me/subscriptions":{"get":{"tags":["marketplace"],"summary":"Mes souscriptions actives","operationId":"my_subscriptions_marketplace_me_subscriptions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response My Subscriptions Marketplace Me Subscriptions Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/marketplace/strategies/{slug}":{"patch":{"tags":["marketplace"],"summary":"Modifier sa propre strategie (changement status DRAFT->PUBLISHED notamment)","operationId":"update_strategy_marketplace_strategies__slug__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["marketplace"],"summary":"Detail d'une strategie","description":"Lecture publique. Status DRAFT/ARCHIVED accessible uniquement par auteur.","operationId":"get_strategy_detail_marketplace_strategies__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/me/strategies":{"get":{"tags":["marketplace"],"summary":"Mes strategies (en tant qu'auteur)","operationId":"my_strategies_marketplace_me_strategies_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"status_filter","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(draft|published|paused|archived)$"},{"type":"null"}],"title":"Status Filter"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response My Strategies Marketplace Me Strategies Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/me/feed":{"get":{"tags":["marketplace"],"summary":"Feed personnel : value bets matchant tes stratégies actives","description":"Applique les filtres de chaque stratégie active à laquelle l'user est\nabonné aux value bets `is_live=true` et renvoie groupé par stratégie.\n\nPermet à un abonné de voir uniquement les paris pertinents pour les\nstratégies qu'il suit (au lieu d'aller dans Hot Sheet et de filtrer à\nla main).","operationId":"my_feed_marketplace_me_feed_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response My Feed Marketplace Me Feed Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/sessions":{"get":{"tags":["me-account"],"summary":"List my active sessions (current device flagged is_current=true)","description":"Liste les sessions du user courant.\n\nPar défaut, on cache les sessions révoquées (bruit) ; include_revoked=true\npour audit forensic.","operationId":"list_my_sessions_me_sessions_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"include_revoked","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Revoked"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/src__routers__me_account__SessionRead"},"title":"Response List My Sessions Me Sessions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/sessions/{session_id}":{"delete":{"tags":["me-account"],"summary":"Revoke a session (force logout on that device)","description":"Révoque une session du user.\n\nAnti self-lock : refuser de révoquer la session courante via cet endpoint\n(l'utilisateur doit utiliser /auth/logout pour ça, plus prévisible).","operationId":"revoke_my_session_me_sessions__session_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/preferences":{"get":{"tags":["me-account"],"summary":"Read my user preferences (locale, timezone)","operationId":"get_my_preferences_me_preferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"patch":{"tags":["me-account"],"summary":"Update my user preferences (locale, timezone)","description":"Update partiel : on n'écrit que les champs fournis, et on valide\ncontre whitelist (locale/timezone connus uniquement).","operationId":"update_my_preferences_me_preferences_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/responsible-gambling/limits":{"get":{"tags":["me-account"],"summary":"Read my Responsible Gambling caps (weekly/monthly + exclusion)","operationId":"get_my_rg_limits_me_responsible_gambling_limits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RgLimitsRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["me-account"],"summary":"Update my Responsible Gambling caps. Upsert. clear_* flags pour retirer un cap (passer à NULL). self_exclude_for_days pour démarrer une auto-exclusion (>=1 jour). clear_self_exclusion uniquement si l'exclusion est déjà expirée (anti-bypass).","operationId":"update_my_rg_limits_me_responsible_gambling_limits_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RgLimitsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RgLimitsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/theme":{"get":{"tags":["me-account"],"summary":"Read my custom theme + a11y prefs","operationId":"get_my_theme_me_theme_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeSettingsRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["me-account"],"summary":"Update my custom theme + a11y prefs. PATCH-like : seuls les champs fournis sont écrits. Validation : tokens inconnus ignorés, hex obligatoire.","operationId":"update_my_theme_me_theme_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeSettingsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/notifications/devices":{"get":{"tags":["fcm-devices"],"summary":"Liste mes devices FCM enregistrés","operationId":"list_devices_me_notifications_devices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FcmDeviceRead"},"type":"array","title":"Response List Devices Me Notifications Devices Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["fcm-devices"],"summary":"Enregistre ou met à jour un token FCM device","description":"Upsert idempotent par token.\n\n- Si le token existe déjà pour un autre user (device partagé, login B\n  après logout A), on REASSIGNE le token au user courant. Évite que\n  A continue de recevoir les push de B.\n- last_seen_at toujours rafraîchi.","operationId":"register_device_me_notifications_devices_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FcmDeviceRegister"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FcmDeviceRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/notifications/devices/{device_id}":{"delete":{"tags":["fcm-devices"],"summary":"Retire un device FCM","operationId":"delete_device_me_notifications_devices__device_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/notifications/devices/touch":{"post":{"tags":["fcm-devices"],"summary":"Rafraîchit last_seen_at de tous mes devices (heartbeat)","description":"Optionnel : appelé par le mobile au démarrage pour marquer\nles devices comme actifs (le notifier ignore les devices stale 90j+).","operationId":"touch_devices_me_notifications_devices_touch_post","responses":{"204":{"description":"Successful Response"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/ml/drift":{"get":{"tags":["admin-ml"],"summary":"PSI (Population Stability Index) par feature","operationId":"drift_admin_ml_drift_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"model_type","in":"query","required":false,"schema":{"type":"string","default":"dixon_coles","title":"Model Type"}},{"name":"sport_code","in":"query","required":false,"schema":{"type":"string","default":"football","title":"Sport Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Drift Admin Ml Drift Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/arena":{"get":{"tags":["admin-ml"],"summary":"Champion vs Challenger A/B status (stub MVP)","description":"Renvoie les 2 versions actives ou candidates avec leurs métriques\npour comparer. MVP : list les ModelVersion + indique active.","operationId":"arena_admin_ml_arena_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"type":"string","default":"football","title":"Sport Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Arena Admin Ml Arena Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/ml/registry":{"get":{"tags":["admin-ml"],"summary":"Registry complet des versions de modèles (avec lineage stub)","operationId":"registry_admin_ml_registry_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Registry Admin Ml Registry Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/notification-prefs":{"get":{"tags":["notifications"],"summary":"Préférences de notifications de l'utilisateur courant","operationId":"get_my_prefs_me_notification_prefs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPrefRead"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"patch":{"tags":["notifications"],"summary":"Mise à jour des préférences","operationId":"patch_my_prefs_me_notification_prefs_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPrefUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPrefRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/notification-prefs/telegram/link-code":{"post":{"tags":["notifications"],"summary":"Génère un code de liaison Telegram one-shot","operationId":"generate_telegram_link_code_me_notification_prefs_telegram_link_code_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramLinkCodeResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/notification-prefs/telegram":{"delete":{"tags":["notifications"],"summary":"Délier le compte Telegram","operationId":"unlink_telegram_me_notification_prefs_telegram_delete","responses":{"204":{"description":"Successful Response"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/notification-prefs/test":{"post":{"tags":["notifications"],"summary":"Envoie un message de test sur les canaux activés (Telegram). Permet de vérifier la chaîne avant la 1ère vraie value bet.","operationId":"test_notification_me_notification_prefs_test_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationTestResult"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/push/vapid-public-key":{"get":{"tags":["push"],"summary":"Cle VAPID publique pour subscribe push browser","operationId":"get_vapid_public_key_me_push_vapid_public_key_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Get Vapid Public Key Me Push Vapid Public Key Get"}}}}}}},"/me/push/subscribe":{"post":{"tags":["push"],"summary":"Enregistre subscription Web Push","operationId":"subscribe_me_push_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushSubscriptionIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Subscribe Me Push Subscribe Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/push/unsubscribe":{"delete":{"tags":["push"],"summary":"Retire toutes subscriptions du user","operationId":"unsubscribe_all_me_push_unsubscribe_delete","responses":{"204":{"description":"Successful Response"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/push/subscriptions":{"get":{"tags":["push"],"summary":"Liste subscriptions du user courant","operationId":"list_my_subscriptions_me_push_subscriptions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"items":{},"type":"array"},"type":"object","title":"Response List My Subscriptions Me Push Subscriptions Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/admin/integrations/telegram":{"get":{"tags":["admin-integrations"],"summary":"Statut du bot Telegram (sans révéler le token)","operationId":"get_telegram_status_admin_integrations_telegram_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramConfigStatus"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["admin-integrations"],"summary":"Configure le bot Telegram (token via @BotFather)","operationId":"set_telegram_token_admin_integrations_telegram_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramConfigIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramConfigStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"delete":{"tags":["admin-integrations"],"summary":"Supprime le token Telegram","operationId":"delete_telegram_token_admin_integrations_telegram_delete","responses":{"204":{"description":"Successful Response"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/og/match/{event_id}.svg":{"get":{"tags":["og-images"],"summary":"OG card SVG pour 1 match","operationId":"og_match_og_match__event_id__svg_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/og/share/{slug}.svg":{"get":{"tags":["og-images"],"summary":"OG card SVG pour 1 bet share","operationId":"og_share_og_share__slug__svg_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"}}}}}}},"/me/achievements":{"get":{"tags":["gamification"],"summary":"Mes achievements unlocked","operationId":"list_my_achievements_me_achievements_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List My Achievements Me Achievements Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/quests":{"get":{"tags":["gamification"],"summary":"Catalogue + ma progression","operationId":"list_quests_me_quests_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Quests Me Quests Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/quests/{slug}/advance":{"post":{"tags":["gamification"],"summary":"Avance dans une quête (validation step)","operationId":"advance_quest_me_quests__slug__advance_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestStepBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Advance Quest Me Quests  Slug  Advance Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/webhooks":{"get":{"tags":["webhooks"],"summary":"List Webhooks","operationId":"list_webhooks_me_webhooks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Webhooks Me Webhooks Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["webhooks"],"summary":"Create Webhook","operationId":"create_webhook_me_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Webhook Me Webhooks Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/me/webhooks/{webhook_id}":{"delete":{"tags":["webhooks"],"summary":"Delete Webhook","operationId":"delete_webhook_me_webhooks__webhook_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Webhook Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/recommendations":{"get":{"tags":["recommendation"],"summary":"Value bets recommandés personnalisés","operationId":"recommend_me_me_recommendations_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"top_k","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Top K"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Recommend Me Me Recommendations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/odds/event/{event_id}/history":{"get":{"tags":["odds"],"summary":"Historique des cotes pour un événement (chart vue match)","description":"Renvoie les snapshots time-series des cotes pour un event, filtrables par market / outcome / bookie. Tri ascendant fetched_at.","operationId":"get_event_odds_history_odds_event__event_id__history_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"outcome","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome"}},{"name":"line","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"}},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO-8601 UTC, ex: 2026-05-18T00:00:00Z","title":"Since"},"description":"ISO-8601 UTC, ex: 2026-05-18T00:00:00Z"},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Until"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"default":2000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OddsHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/odds/comparator":{"get":{"tags":["odds-comparator"],"summary":"Comparateur de cotes multi-bookies par event","description":"Pour les N prochains events scheduled, renvoie toutes les cotes\npar (outcome, bookie) + best odd + vig moyen.","operationId":"odds_comparator_odds_comparator_get","parameters":[{"name":"market_code","in":"query","required":false,"schema":{"type":"string","default":"1X2","title":"Market Code"}},{"name":"limit_events","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit Events"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparatorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/{event_id}/player-props":{"get":{"tags":["player-props"],"summary":"Player props pour un event","operationId":"list_player_props_for_event_events__event_id__player_props_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"prop_kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prop Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayerPropsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/player-props/top-ev":{"get":{"tags":["player-props"],"summary":"Liste cross-events des player props avec filtres sport / prop / joueur et tri par EV décroissante. Spec PLAN §L11.11.","description":"Listing top-EV cross-events.\n\n- sport : 'football', 'basketball', etc. (filtre via League.sport_code)\n- prop_kind : 'goal_scorer', 'assist', 'card', ...\n- player_query : recherche ILIKE sur player_name\n- min_ev : seuil EV minimum (ex 0.03 = 3%)\n- only_with_odd : exclure les props sans best_bookie_odd\n- include_past : par défaut on filtre events upcoming (kickoff>=now)","operationId":"list_top_ev_player_props_player_props_top_ev_get","parameters":[{"name":"sport","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Sport"}},{"name":"prop_kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Prop Kind"}},{"name":"player_query","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Player Query"}},{"name":"min_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":1,"minimum":-1},{"type":"null"}],"title":"Min Ev"}},{"name":"only_with_odd","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Only With Odd"}},{"name":"include_past","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Past"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopEvResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/player-props/compute/{event_id}":{"post":{"tags":["player-props"],"summary":"Calcule les player props (goal_scorer) pour un event. Approche Poisson bayésienne : λ_player = λ_team × position_weight × (minutes_avg / 90). Démontre la pipe E2E sans dépendre d'une ingestion bookmaker premium.","description":"Trigger admin pour peupler `player_props` sur un event donné.","operationId":"compute_player_props_for_event_admin_player_props_compute__event_id__post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"mode","in":"query","required":false,"schema":{"const":"goal_scorer","type":"string","default":"goal_scorer","title":"Mode"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComputeResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/player-props/{prop_id}/odds":{"put":{"tags":["player-props"],"summary":"Set / update la cote bookmaker d'un player prop. Recalcule EV automatiquement (fair_prob × odd - 1). Endpoint admin générique : marche pour saisie manuelle, ou pour worker auto futur.","operationId":"set_player_prop_odds_admin_player_props__prop_id__odds_put","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"prop_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Prop Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropOddsUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayerPropRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/player-props/ingest-rosters":{"post":{"tags":["player-props"],"summary":"Ingestion rosters multi-sport via APIs gratuites (MLB StatsAPI / NHL Official / ESPN NBA). Sans clé externe. sport= baseball | hockey | basketball.","description":"Trigger ingestion roster pour un sport. Pour foot, attendre clé\nAPI-Football (Stop Condition #1, action humaine externe nécessaire).","operationId":"ingest_rosters_admin_player_props_ingest_rosters_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport","in":"query","required":true,"schema":{"enum":["baseball","hockey","basketball"],"type":"string","title":"Sport"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RosterIngestResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/player-props/sync-odds/{event_id}":{"post":{"tags":["player-props"],"summary":"Tente de récupérer auto les cotes player props depuis Sofascore (gratuit, best-effort). Fallback : message clair + saisie manuelle.","operationId":"sync_odds_for_event_admin_player_props_sync_odds__event_id__post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncOddsResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/player-props/compute-all-upcoming":{"post":{"tags":["player-props"],"summary":"Calcule les player props pour TOUS les events upcoming (next 14d). Switch automatique par sport. Idempotent.","operationId":"compute_all_upcoming_admin_player_props_compute_all_upcoming_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"max_events","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Max Events"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchComputeResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/player-props/recalc-ev/{event_id}":{"post":{"tags":["player-props"],"summary":"Recalcule l'EV de tous les player props d'un event (utile après import batch de cotes ou changement de fair_prob).","operationId":"recalc_ev_for_event_admin_player_props_recalc_ev__event_id__post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecalcEvResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/opportunities":{"get":{"tags":["opportunities"],"summary":"Liste unifiée value_bets + player_props EV+ pour le user. Trié par EV décroissante. include_fair_model=true pour inclure les player props SANS cote bookie (référence modèle uniquement).","description":"Union value_bets (live + EV > min_ev) + player_props (ev > min_ev).","operationId":"list_opportunities_me_opportunities_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Sport"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"value_bet | player_prop | None (les deux)","title":"Kind"},"description":"value_bet | player_prop | None (les deux)"},{"name":"min_ev","in":"query","required":false,"schema":{"type":"number","maximum":1,"minimum":-1,"default":0.0,"title":"Min Ev"}},{"name":"include_past","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Past"}},{"name":"include_fair_model","in":"query","required":false,"schema":{"type":"boolean","description":"Inclure les player_props SANS cote bookmaker (juste fair model). EV affichée comme 0, kind='player_prop'. Utile en attendant ingestion cotes auto.","default":false,"title":"Include Fair Model"},"description":"Inclure les player_props SANS cote bookmaker (juste fair model). EV affichée comme 0, kind='player_prop'. Utile en attendant ingestion cotes auto."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpportunitiesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/brokers/orders":{"post":{"tags":["broker-orders"],"summary":"Place un ordre chez un broker (idempotent)","operationId":"place_order_me_brokers_orders_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceOrderBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrokerOrderRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["broker-orders"],"summary":"Liste les ordres placés (filtrable)","operationId":"list_orders_me_brokers_orders_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"open | settled | rejected | all (default: open)","title":"Status"},"description":"open | settled | rejected | all (default: open)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BrokerOrderRead"},"title":"Response List Orders Me Brokers Orders Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/brokers/orders/sync":{"post":{"tags":["broker-orders"],"summary":"Force la synchronisation des ordres ouverts (sync flow manuel)","operationId":"sync_orders_me_brokers_orders_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Sync Orders Me Brokers Orders Sync Post"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/predictions/event/{event_id}":{"get":{"tags":["predictions"],"summary":"Prédictions pour un événement","description":"Retourne toutes les prédictions de modèles pour un event donné. Filtrable par market_code et model_type. Cf. ADR-038 pour le choix d'URL `/event/{id}` vs `/{id}`.","operationId":"get_event_predictions_predictions_event__event_id__get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par code de marché (ex: '1X2', 'OU')","title":"Market Code"},"description":"Filtre par code de marché (ex: '1X2', 'OU')"},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par type de modèle (ex: 'dixon_coles')","title":"Model Type"},"description":"Filtre par type de modèle (ex: 'dixon_coles')"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPredictionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predictions/models/active":{"get":{"tags":["predictions"],"summary":"Version active d'un modèle pour une ligue","description":"Retourne la version active du modèle pour (sport, type, league).","operationId":"get_active_model_predictions_models_active_get","parameters":[{"name":"sport_code","in":"query","required":true,"schema":{"type":"string","description":"Ex: 'football'","title":"Sport Code"},"description":"Ex: 'football'"},{"name":"model_type","in":"query","required":true,"schema":{"type":"string","description":"Ex: 'dixon_coles'","title":"Model Type"},"description":"Ex: 'dixon_coles'"},{"name":"league_slug","in":"query","required":true,"schema":{"type":"string","description":"Ex: 'fr-ligue-1'","title":"League Slug"},"description":"Ex: 'fr-ligue-1'"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ModelVersionRead"},{"type":"null"}],"title":"Response Get Active Model Predictions Models Active Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predictions/models/versions":{"get":{"tags":["predictions"],"summary":"Historique des versions d'un modèle","description":"Liste toutes les versions entraînées (plus récente en tête).","operationId":"list_model_versions_predictions_models_versions_get","parameters":[{"name":"sport_code","in":"query","required":true,"schema":{"type":"string","description":"Ex: 'football'","title":"Sport Code"},"description":"Ex: 'football'"},{"name":"model_type","in":"query","required":true,"schema":{"type":"string","description":"Ex: 'dixon_coles'","title":"Model Type"},"description":"Ex: 'dixon_coles'"},{"name":"league_slug","in":"query","required":true,"schema":{"type":"string","description":"Ex: 'fr-ligue-1'","title":"League Slug"},"description":"Ex: 'fr-ligue-1'"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModelVersionRead"},"title":"Response List Model Versions Predictions Models Versions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predictions/event/{event_id}/ah":{"get":{"tags":["predictions"],"summary":"Analyse Asian Handicap (probas modèle + EV vs marché)","description":"Reconstruit la score matrix Poisson Dixon-Coles depuis les lambdas stockés dans `prediction.aux_data`, calcule les probas AH pour 25 lignes standards, et compare aux cotes courantes des bookies.","operationId":"get_ah_analysis_predictions_event__event_id__ah_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"max_goals","in":"query","required":false,"schema":{"type":"integer","maximum":10,"minimum":4,"default":8,"title":"Max Goals"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Ah Analysis Predictions Event  Event Id  Ah Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predictions/event/{event_id}/explain":{"get":{"tags":["predictions"],"summary":"Explainability SHAP-like des prédictions","description":"Pour chaque prédiction Dixon-Coles, décompose la probabilité en contributions feature (attaque, défense, avantage terrain). Cf. ux_design §18.5 + modelisation_mathematique.md §15.","operationId":"explain_event_predictions_predictions_event__event_id__explain_get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventExplanationsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predictions/{event_id}":{"get":{"tags":["predictions"],"summary":"Prédictions pour un événement (alias spec ROADMAP T1.16)","description":"Alias rétro-compatible vers `/predictions/event/{event_id}` pour conserver l'URL initialement spécifiée dans ROADMAP.md T1.16. Cf. ADR-038.","operationId":"get_event_predictions_alias_predictions__event_id__get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par code de marché","title":"Market Code"},"description":"Filtre par code de marché"},{"name":"model_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par type de modèle","title":"Model Type"},"description":"Filtre par type de modèle"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPredictionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/qualitative/scoring-matrix":{"get":{"tags":["qualitative"],"summary":"Matrice amplitudes × marchés + half-lives + confiance sources","description":"Lit la matrice depuis la DB (avec cache 60s). Fallback sur les seeds\nhardcodes si tables vides.","operationId":"get_matrix_events_qualitative_scoring_matrix_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Matrix Events Qualitative Scoring Matrix Get"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/events/qualitative/scoring-matrix/amplitude":{"patch":{"tags":["qualitative"],"summary":"MAJ amplitude (event_kind, market_code). Cree si absent.","operationId":"patch_amplitude_events_qualitative_scoring_matrix_amplitude_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AmplitudePatch"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Patch Amplitude Events Qualitative Scoring Matrix Amplitude Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/events/qualitative/scoring-matrix/half-life":{"patch":{"tags":["qualitative"],"summary":"MAJ half_life_hours pour un event_kind.","operationId":"patch_half_life_events_qualitative_scoring_matrix_half_life_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HalfLifePatch"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Patch Half Life Events Qualitative Scoring Matrix Half Life Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/events/qualitative/scoring-matrix/source-confidence":{"patch":{"tags":["qualitative"],"summary":"MAJ confidence pour une source.","operationId":"patch_source_confidence_events_qualitative_scoring_matrix_source_confidence_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceConfidencePatch"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Patch Source Confidence Events Qualitative Scoring Matrix Source Confidence Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/events/qualitative/scoring-matrix/amplitude/{event_kind}/{market_code}":{"delete":{"tags":["qualitative"],"summary":"Supprime une entree amplitude (purge config).","operationId":"delete_amplitude_events_qualitative_scoring_matrix_amplitude__event_kind___market_code__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"event_kind","in":"path","required":true,"schema":{"type":"string","title":"Event Kind"}},{"name":"market_code","in":"path","required":true,"schema":{"type":"string","title":"Market Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Amplitude Events Qualitative Scoring Matrix Amplitude  Event Kind   Market Code  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/qualitative/stats":{"get":{"tags":["qualitative"],"summary":"Stats analytiques sur les events qualitatifs detectes (calibration empirique source pour amelioration value bets + strategies edge).","description":"Compteurs + distribution par event kind + impact + source pour\npermettre a l'admin de calibrer empiriquement les amplitudes /\nhalf_lives a la lumiere des events reellement detectes.","operationId":"get_qualitative_stats_events_qualitative_stats_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Since Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Qualitative Stats Events Qualitative Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/shadow-bets/recompute":{"post":{"tags":["shadow-bets-admin"],"summary":"Recompute les shadow value bets sur N jours.","description":"Re-calcule. Idempotent : upsert sur natural key\n(event, market, outcome, line, edge_threshold, model_version).","operationId":"recompute_admin_shadow_bets_recompute_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Since Days"}},{"name":"edge_threshold","in":"query","required":false,"schema":{"type":"number","maximum":0.99,"minimum":0.001,"default":0.15,"title":"Edge Threshold"}},{"name":"max_events","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":10,"default":500,"title":"Max Events"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecomputeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/shadow-bets/stats":{"get":{"tags":["shadow-bets-admin"],"summary":"Stats ROI shadow par edge_threshold.","operationId":"stats_admin_shadow_bets_stats_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"since_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":90,"title":"Since Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sharp-moves":{"get":{"tags":["sharp-moves"],"summary":"Sharp moves récents (table persistée)","operationId":"list_sharp_moves_sharp_moves_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"period_hours","in":"query","required":false,"schema":{"type":"integer","maximum":168,"minimum":1,"default":24,"title":"Period Hours"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"min_magnitude","in":"query","required":false,"schema":{"type":"string","pattern":"^(weak|strong|extreme)$","default":"weak","title":"Min Magnitude"}},{"name":"sharp_only","in":"query","required":false,"schema":{"type":"boolean","description":"Filtrer uniquement bookies sharps (Pinnacle/PS3838/SBObet/...).","default":false,"title":"Sharp Only"},"description":"Filtrer uniquement bookies sharps (Pinnacle/PS3838/SBObet/...)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Sharp Moves Sharp Moves Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sharp-moves/analytics":{"get":{"tags":["sharp-moves"],"summary":"Stats temporelles : winrate, ROI follow, distribution magnitude, top bookies","operationId":"sharp_moves_analytics_sharp_moves_analytics_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Fenêtre d'analyse en jours.","default":30,"title":"Days"},"description":"Fenêtre d'analyse en jours."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sharp Moves Analytics Sharp Moves Analytics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/stats":{"get":{"tags":["stats"],"summary":"KPIs du parieur (ROI, CLV, drawdown, streaks)","operationId":"get_my_stats_me_stats_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"period","in":"query","required":false,"schema":{"enum":["7d","30d","90d","all"],"type":"string","description":"Fenêtre : 7d / 30d / 90d / all","default":"all","title":"Period"},"description":"Fenêtre : 7d / 30d / 90d / all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/surebets":{"get":{"tags":["surebets"],"summary":"Liste des surebets live (multi-bookies, profit garanti)","operationId":"list_surebets_surebets_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport Code"}},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"}},{"name":"min_profit_pct","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Min Profit Pct"}},{"name":"surebet_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SurebetType"},{"type":"null"}],"title":"Surebet Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"only_accessible","in":"query","required":false,"schema":{"type":"boolean","description":"Si true, ne renvoie que les surebets entierement accessibles a l'user.","default":false,"title":"Only Accessible"},"description":"Si true, ne renvoie que les surebets entierement accessibles a l'user."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurebetsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/surebets/event/{event_id}":{"get":{"tags":["surebets"],"summary":"Surebets actives pour un événement","operationId":"list_surebets_for_event_surebets_event__event_id__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"live_only","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Live Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurebetsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/surebets/{surebet_id}":{"get":{"tags":["surebets"],"summary":"Détail d'un surebet","operationId":"get_surebet_surebets__surebet_id__get","parameters":[{"name":"surebet_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Surebet Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurebetRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/tax/3916":{"get":{"tags":["tax-report"],"summary":"Form 3916 (comptes étrangers) — brouillon","operationId":"get_form_3916_me_tax_3916_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"year","in":"query","required":true,"schema":{"type":"integer","maximum":2030,"minimum":2020,"title":"Year"}},{"name":"as_csv","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"As Csv"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/tax/2086":{"get":{"tags":["tax-report"],"summary":"Form 2086 (plus-values cessions) — brouillon","operationId":"get_form_2086_me_tax_2086_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"year","in":"query","required":true,"schema":{"type":"integer","maximum":2030,"minimum":2020,"title":"Year"}},{"name":"as_csv","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"As Csv"}},{"name":"include_anj","in":"query","required":false,"schema":{"type":"boolean","description":"Inclure les paris ANJ (légalement exonérés). Faux par défaut — uniquement les brokers étrangers.","default":false,"title":"Include Anj"},"description":"Inclure les paris ANJ (légalement exonérés). Faux par défaut — uniquement les brokers étrangers."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/tracked-positions":{"post":{"tags":["tracked-positions"],"summary":"Démarrer le tracking hedge sur un pari pré-match","operationId":"create_tracked_position_me_tracked_positions_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedPositionCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedPositionRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["tracked-positions"],"summary":"Liste des positions trackées de l'utilisateur","operationId":"list_my_tracked_positions_me_tracked_positions_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/TrackedPositionStatus"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedPositionsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/me/tracked-positions/{tp_id}":{"get":{"tags":["tracked-positions"],"summary":"Détail d'une position trackée","operationId":"get_tracked_position_me_tracked_positions__tp_id__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"tp_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tp Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedPositionRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["tracked-positions"],"summary":"Mise à jour d'une position trackée","operationId":"patch_tracked_position_me_tracked_positions__tp_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"tp_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tp Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedPositionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedPositionRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["tracked-positions"],"summary":"Supprimer le tracking","operationId":"delete_tracked_position_me_tracked_positions__tp_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"tp_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tp Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/value-bets/facets":{"get":{"tags":["value-bets"],"summary":"Sports / marchés / bookies présents dans les value bets live","description":"Alimente les filtres dynamiques de l'UI (multisport). Déclaré avant /{value_bet_id} pour l'ordre de routing.","operationId":"value_bets_facets_value_bets_facets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"items":{"additionalProperties":true,"type":"object"},"type":"array"},"type":"object","title":"Response Value Bets Facets Value Bets Facets Get"}}}}}}},"/value-bets":{"get":{"tags":["value-bets"],"summary":"Liste des value bets live (EV+)","description":"Retourne les value bets actuellement actives (is_live=true), triées par EV décroissante. Filtrable par sport, marché, bookmaker et EV minimum.","operationId":"list_value_bets_value_bets_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"sport_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par sport (ex: 'football')","title":"Sport Code"},"description":"Filtre par sport (ex: 'football')"},{"name":"market_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par marché (ex: '1X2', 'OU')","title":"Market Code"},"description":"Filtre par marché (ex: '1X2', 'OU')"},{"name":"bookie_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtre par bookmaker (ex: 'winamax')","title":"Bookie Slug"},"description":"Filtre par bookmaker (ex: 'winamax')"},{"name":"min_ev","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":10,"minimum":0},{"type":"null"}],"description":"EV minimum (ex: 0.05 = +5 %)","title":"Min Ev"},"description":"EV minimum (ex: 0.05 = +5 %)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Nb max de résultats","default":100,"title":"Limit"},"description":"Nb max de résultats"},{"name":"order_by_ev_desc","in":"query","required":false,"schema":{"type":"boolean","description":"True : triés par EV desc (défaut). False : par detected_at.","default":true,"title":"Order By Ev Desc"},"description":"True : triés par EV desc (défaut). False : par detected_at."},{"name":"with_event","in":"query","required":false,"schema":{"type":"boolean","description":"Si true, joint l'event (kickoff + noms équipes/ligue) pour les cartes UI Hot Sheet.","default":false,"title":"With Event"},"description":"Si true, joint l'event (kickoff + noms équipes/ligue) pour les cartes UI Hot Sheet."},{"name":"access_mode","in":"query","required":false,"schema":{"type":"string","description":"Filtre d'accessibilité : 'anj_only' = uniquement soft books ANJ (100% légal FR), 'with_brokers' = ANJ + via broker user actif (incl. AsianConnect/Sportmarket), 'all' = tous, y compris inaccessibles (pour info).","default":"all","title":"Access Mode"},"description":"Filtre d'accessibilité : 'anj_only' = uniquement soft books ANJ (100% légal FR), 'with_brokers' = ANJ + via broker user actif (incl. AsianConnect/Sportmarket), 'all' = tous, y compris inaccessibles (pour info)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValueBetsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/value-bets/event/{event_id}":{"get":{"tags":["value-bets"],"summary":"Value bets actives pour un événement","operationId":"list_value_bets_for_event_value_bets_event__event_id__get","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}},{"name":"live_only","in":"query","required":false,"schema":{"type":"boolean","description":"True (défaut) : ignore les expirées.","default":true,"title":"Live Only"},"description":"True (défaut) : ignore les expirées."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValueBetsListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/value-bets/{value_bet_id}":{"get":{"tags":["value-bets"],"summary":"Détail d'une value bet","operationId":"get_value_bet_value_bets__value_bet_id__get","parameters":[{"name":"value_bet_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Value Bet Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValueBetRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AdminAlertRead":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","title":"Kind"},"severity":{"type":"string","title":"Severity"},"title":{"type":"string","title":"Title"},"message":{"type":"string","title":"Message"},"payload":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Payload"},"dedup_key":{"type":"string","title":"Dedup Key"},"status":{"type":"string","title":"Status"},"acknowledged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Acknowledged At"},"sent_telegram_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent Telegram At"},"sent_push_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent Push At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","kind","severity","title","message","payload","dedup_key","status","acknowledged_at","sent_telegram_at","sent_push_at","created_at"],"title":"AdminAlertRead","description":"Une alerte admin (drift, calibration, ML failure)."},"AmplitudePatch":{"properties":{"event_kind":{"type":"string","maxLength":50,"minLength":2,"title":"Event Kind"},"market_code":{"type":"string","maxLength":20,"minLength":1,"title":"Market Code"},"amplitude":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Amplitude"}},"type":"object","required":["event_kind","market_code","amplitude"],"title":"AmplitudePatch"},"AuditLogEntry":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"actor_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor User Id"},"actor_email":{"type":"string","title":"Actor Email"},"action":{"type":"string","title":"Action"},"target_type":{"type":"string","title":"Target Type"},"target_key":{"type":"string","title":"Target Key"},"details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Details"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","actor_user_id","actor_email","action","target_type","target_key","details","created_at"],"title":"AuditLogEntry"},"AuditLogResponse":{"properties":{"since_days":{"type":"integer","title":"Since Days"},"total":{"type":"integer","title":"Total"},"by_action":{"items":{"$ref":"#/components/schemas/AuditLogStatsBucket"},"type":"array","title":"By Action"},"entries":{"items":{"$ref":"#/components/schemas/AuditLogEntry"},"type":"array","title":"Entries"}},"type":"object","required":["since_days","total","by_action","entries"],"title":"AuditLogResponse"},"AuditLogStatsBucket":{"properties":{"action":{"type":"string","title":"Action"},"n":{"type":"integer","title":"N"}},"type":"object","required":["action","n"],"title":"AuditLogStatsBucket"},"AutoBetMode":{"type":"string","enum":["off","pilot","auto"],"title":"AutoBetMode"},"BacktestBody":{"properties":{"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"period_from":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Period From"},"period_to":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Period To"},"sports":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sports"},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Markets"},"bookies_whitelist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies Whitelist"},"bookies_blacklist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies Blacklist"},"leagues":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Leagues"},"model_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Model Types"},"min_ev":{"type":"number","title":"Min Ev","default":0.03},"max_ev":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Ev"},"min_odd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Odd"},"max_odd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Odd"},"min_kelly":{"type":"number","title":"Min Kelly","default":0.0},"max_kelly":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Kelly"},"min_composite_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Composite Score"},"stake_strategy":{"type":"string","enum":["flat","kelly","kelly_quarter","kelly_eighth","fractional_kelly","pct_bankroll"],"title":"Stake Strategy","default":"kelly_quarter"},"stake_param":{"type":"number","title":"Stake Param","default":1.0},"max_stake_pct_bankroll":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Stake Pct Bankroll"},"use_closing_odd":{"type":"boolean","title":"Use Closing Odd","default":false},"slippage_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Slippage Pct"},"access_mode":{"type":"string","enum":["all","anj_only","with_brokers"],"title":"Access Mode","default":"all"},"stop_loss_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Stop Loss Pct"},"initial_bankroll_eur":{"type":"number","title":"Initial Bankroll Eur","default":1000.0},"configs":{"anyOf":[{"items":{"$ref":"#/components/schemas/BacktestConfigBody"},"type":"array"},{"type":"null"}],"title":"Configs"}},"type":"object","title":"BacktestBody","description":"Body — accepte SOIT une config seule (compat) SOIT une liste (A/B/N)."},"BacktestConfigBody":{"properties":{"label":{"type":"string","title":"Label","default":"Strategy A"},"period_from":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Period From"},"period_to":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Period To"},"sports":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sports"},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Markets"},"bookies_whitelist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies Whitelist"},"bookies_blacklist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies Blacklist"},"leagues":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Leagues"},"model_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Model Types"},"min_ev":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Min Ev","default":0.03},"max_ev":{"anyOf":[{"type":"number","maximum":10.0,"minimum":0.0},{"type":"null"}],"title":"Max Ev"},"min_odd":{"anyOf":[{"type":"number","maximum":100.0,"exclusiveMinimum":1.0},{"type":"null"}],"title":"Min Odd"},"max_odd":{"anyOf":[{"type":"number","maximum":100.0,"exclusiveMinimum":1.0},{"type":"null"}],"title":"Max Odd"},"min_kelly":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Min Kelly","default":0.0},"max_kelly":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Max Kelly"},"min_composite_score":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":-5.0},{"type":"null"}],"title":"Min Composite Score"},"stake_strategy":{"type":"string","enum":["flat","kelly","kelly_quarter","kelly_eighth","fractional_kelly","pct_bankroll"],"title":"Stake Strategy","default":"kelly_quarter"},"stake_param":{"type":"number","exclusiveMinimum":0.0,"title":"Stake Param","default":1.0},"max_stake_pct_bankroll":{"anyOf":[{"type":"number","maximum":100.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Max Stake Pct Bankroll"},"use_closing_odd":{"type":"boolean","title":"Use Closing Odd","default":false},"slippage_pct":{"anyOf":[{"type":"number","maximum":20.0,"minimum":0.0},{"type":"null"}],"title":"Slippage Pct"},"access_mode":{"type":"string","enum":["all","anj_only","with_brokers"],"title":"Access Mode","default":"all"},"stop_loss_pct":{"anyOf":[{"type":"number","maximum":100.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Stop Loss Pct"},"initial_bankroll_eur":{"type":"number","exclusiveMinimum":0.0,"title":"Initial Bankroll Eur","default":1000.0}},"type":"object","title":"BacktestConfigBody"},"BacktestResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BacktestResultRead"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"BacktestResponse"},"BacktestResultRead":{"properties":{"label":{"type":"string","title":"Label"},"config":{"additionalProperties":true,"type":"object","title":"Config"},"n_bets":{"type":"integer","title":"N Bets"},"n_wins":{"type":"integer","title":"N Wins"},"n_losses":{"type":"integer","title":"N Losses"},"n_half_wins":{"type":"integer","title":"N Half Wins"},"n_half_losses":{"type":"integer","title":"N Half Losses"},"n_voids":{"type":"integer","title":"N Voids"},"n_pushes":{"type":"integer","title":"N Pushes"},"total_staked":{"type":"number","title":"Total Staked"},"total_pnl":{"type":"number","title":"Total Pnl"},"roi":{"type":"number","title":"Roi"},"final_bankroll":{"type":"number","title":"Final Bankroll"},"win_rate":{"type":"number","title":"Win Rate"},"max_drawdown":{"type":"number","title":"Max Drawdown"},"max_drawdown_pct":{"type":"number","title":"Max Drawdown Pct"},"sharpe":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sharpe"},"sortino":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sortino"},"calmar":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Calmar"},"var_95":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Var 95"},"cvar_95":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cvar 95"},"ulcer_index":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ulcer Index"},"longest_losing_streak":{"type":"integer","title":"Longest Losing Streak"},"profit_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Profit Factor"},"clv_mean_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Clv Mean Pct"},"clv_positive_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Clv Positive Pct"},"equity_curve":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Equity Curve"},"top_bets":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Top Bets"},"period_from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period From"},"period_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period To"},"stopped_early":{"type":"boolean","title":"Stopped Early"}},"type":"object","required":["label","config","n_bets","n_wins","n_losses","n_half_wins","n_half_losses","n_voids","n_pushes","total_staked","total_pnl","roi","final_bankroll","win_rate","max_drawdown","max_drawdown_pct","sharpe","sortino","calmar","var_95","cvar_95","ulcer_index","longest_losing_streak","profit_factor","clv_mean_pct","clv_positive_pct","equity_curve","top_bets","period_from","period_to","stopped_early"],"title":"BacktestResultRead"},"BankrollAccountRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source_slug":{"type":"string","title":"Source Slug"},"currency":{"type":"string","title":"Currency"},"current_balance":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Current Balance"},"locked":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Locked"},"withdrawable":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Withdrawable"},"deposit_lifetime":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Deposit Lifetime"},"withdraw_lifetime":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Withdraw Lifetime"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Synced At"},"is_active":{"type":"boolean","title":"Is Active"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","required":["id","source_slug","currency","current_balance","locked","withdrawable","deposit_lifetime","withdraw_lifetime","last_synced_at","is_active","label"],"title":"BankrollAccountRead"},"BankrollAllocationRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"strategy_slug":{"type":"string","title":"Strategy Slug"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"max_pct_bankroll":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Max Pct Bankroll"},"current_pct":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Current Pct"},"drawdown_stop_pct":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Drawdown Stop Pct"},"weekly_stake_limit_eur":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Weekly Stake Limit Eur"},"is_active":{"type":"boolean","title":"Is Active"},"is_paused":{"type":"boolean","title":"Is Paused"},"paused_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Paused Reason"},"paused_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paused Until"}},"type":"object","required":["id","strategy_slug","label","max_pct_bankroll","current_pct","drawdown_stop_pct","weekly_stake_limit_eur","is_active","is_paused","paused_reason","paused_until"],"title":"BankrollAllocationRead"},"BankrollAllocationUpsert":{"properties":{"strategy_slug":{"type":"string","maxLength":50,"minLength":2,"title":"Strategy Slug"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"max_pct_bankroll":{"anyOf":[{"type":"number","maximum":1.0,"exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Max Pct Bankroll","default":"0.30"},"drawdown_stop_pct":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Drawdown Stop Pct","default":"0.08"},"weekly_stake_limit_eur":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Weekly Stake Limit Eur"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["strategy_slug"],"title":"BankrollAllocationUpsert"},"BatchComputeResult":{"properties":{"total_events_seen":{"type":"integer","title":"Total Events Seen"},"total_props_upserted":{"type":"integer","title":"Total Props Upserted"},"by_sport":{"additionalProperties":true,"type":"object","title":"By Sport"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"}},"type":"object","required":["total_events_seen","total_props_upserted","by_sport","errors"],"title":"BatchComputeResult"},"BetCreate":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"sport_code":{"type":"string","title":"Sport Code"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"bookie_slug":{"type":"string","title":"Bookie Slug"},"odd_taken":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Odd Taken"},"stake":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Stake"},"currency":{"type":"string","maxLength":3,"minLength":3,"title":"Currency","default":"EUR"},"placed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Placed At"},"value_bet_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Value Bet Id"},"notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Notes"}},"type":"object","required":["event_id","sport_code","market_code","outcome","bookie_slug","odd_taken","stake"],"title":"BetCreate","description":"Payload de création d'un pari."},"BetRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"value_bet_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Value Bet Id"},"sport_code":{"type":"string","title":"Sport Code"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"bookie_slug":{"type":"string","title":"Bookie Slug"},"odd_taken":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd Taken"},"stake":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Stake"},"currency":{"type":"string","title":"Currency"},"placed_at":{"type":"string","format":"date-time","title":"Placed At"},"status":{"$ref":"#/components/schemas/BetStatus"},"settled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Settled At"},"pnl":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Pnl"},"clv":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Clv"},"closing_odd":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Closing Odd"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"potential_payout":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Potential Payout"}},"type":"object","required":["id","user_id","event_id","sport_code","market_code","outcome","bookie_slug","odd_taken","stake","currency","placed_at","status","potential_payout"],"title":"BetRead","description":"Vue lecture."},"BetShareCreate":{"properties":{"bet_id":{"type":"string","format":"uuid","title":"Bet Id"},"caption":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Caption"}},"type":"object","required":["bet_id"],"title":"BetShareCreate"},"BetShareRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"bet_id":{"type":"string","format":"uuid","title":"Bet Id"},"public_slug":{"type":"string","title":"Public Slug"},"consent_at":{"type":"string","format":"date-time","title":"Consent At"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption"},"view_count":{"type":"integer","title":"View Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","user_id","bet_id","public_slug","consent_at","caption","view_count","created_at"],"title":"BetShareRead"},"BetStatus":{"type":"string","enum":["pending","won","lost","void","push","cashed_out"],"title":"BetStatus","description":"Statut d'un pari saisi au journal."},"BetUpdate":{"properties":{"notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Notes"},"stake":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Stake"},"odd_taken":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Odd Taken"},"status":{"anyOf":[{"$ref":"#/components/schemas/BetStatus"},{"type":"null"}]}},"type":"object","title":"BetUpdate","description":"Patch partiel."},"BetsListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"total":{"type":"integer","title":"Total"},"items":{"items":{"$ref":"#/components/schemas/BetRead"},"type":"array","title":"Items"}},"type":"object","required":["count","total","items"],"title":"BetsListResponse"},"BillingPortalRequest":{"properties":{"return_url":{"type":"string","maxLength":500,"minLength":10,"title":"Return Url"}},"type":"object","required":["return_url"],"title":"BillingPortalRequest"},"BillingPortalResponse":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"BillingPortalResponse"},"BookieAccessInfo":{"properties":{"kind":{"type":"string","enum":["direct_anj","via_broker","inaccessible_fr"],"title":"Kind"},"broker_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Broker Slug"},"available_via_brokers":{"items":{"type":"string"},"type":"array","title":"Available Via Brokers"}},"type":"object","required":["kind"],"title":"BookieAccessInfo","description":"Accessibilite du bookie (cf. bookie_accessibility.py)."},"BrokerAccountSnapshotRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"source_slug":{"type":"string","title":"Source Slug"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"},"currency":{"type":"string","title":"Currency"},"balance":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Balance"},"available":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Available"},"in_play":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"In Play"},"max_stake_typical":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Max Stake Typical"},"status":{"type":"string","title":"Status"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"has_incident":{"type":"boolean","title":"Has Incident"},"incident_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Incident Reason"}},"type":"object","required":["id","user_id","source_slug","captured_at","currency","balance","available","in_play","max_stake_typical","status","last_login_at","has_incident","incident_reason"],"title":"BrokerAccountSnapshotRead"},"BrokerAccountSnapshotsListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/BrokerAccountSnapshotRead"},"type":"array","title":"Items"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["items","count"],"title":"BrokerAccountSnapshotsListResponse"},"BrokerOrderRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"broker_slug":{"type":"string","title":"Broker Slug"},"external_order_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Order Id"},"event_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Event Id"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"stake":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Stake"},"odd_taken":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd Taken"},"currency":{"type":"string","title":"Currency"},"status":{"type":"string","title":"Status"},"placed_at":{"type":"string","format":"date-time","title":"Placed At"},"accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Accepted At"},"settled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Settled At"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"},"settled_pnl":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Settled Pnl"},"placement_mode":{"type":"string","title":"Placement Mode"}},"type":"object","required":["id","broker_slug","external_order_id","event_id","market_code","outcome","line","stake","odd_taken","currency","status","placed_at","accepted_at","settled_at","cancelled_at","settled_pnl","placement_mode"],"title":"BrokerOrderRead"},"BrokerRouting":{"type":"string","enum":["cheapest","fixed","best_odd"],"title":"BrokerRouting"},"BucketRow":{"properties":{"edge_threshold":{"type":"number","title":"Edge Threshold"},"n_bets":{"type":"integer","title":"N Bets"},"n_won":{"type":"integer","title":"N Won"},"won_rate":{"type":"number","title":"Won Rate"},"total_stake":{"type":"number","title":"Total Stake"},"total_pnl":{"type":"number","title":"Total Pnl"},"roi_pct":{"type":"number","title":"Roi Pct"}},"type":"object","required":["edge_threshold","n_bets","n_won","won_rate","total_stake","total_pnl","roi_pct"],"title":"BucketRow"},"ChangePasswordRequest":{"properties":{"old_password":{"type":"string","maxLength":128,"minLength":1,"title":"Old Password"},"new_password":{"type":"string","maxLength":128,"minLength":12,"title":"New Password"}},"type":"object","required":["old_password","new_password"],"title":"ChangePasswordRequest","description":"Changement de mot de passe utilisateur.\n\nRe-vérifie l'ancien mot de passe avant d'accepter le nouveau,\npour bloquer un attaquant qui aurait volé un token d'accès."},"CheckoutCreateRequest":{"properties":{"plan_tier":{"type":"string","pattern":"^(pro|premium)$","title":"Plan Tier"},"success_url":{"type":"string","maxLength":500,"minLength":10,"title":"Success Url"},"cancel_url":{"type":"string","maxLength":500,"minLength":10,"title":"Cancel Url"}},"type":"object","required":["plan_tier","success_url","cancel_url"],"title":"CheckoutCreateRequest"},"CheckoutCreateResponse":{"properties":{"session_id":{"type":"string","title":"Session Id"},"url":{"type":"string","title":"Url"}},"type":"object","required":["session_id","url"],"title":"CheckoutCreateResponse"},"CircuitResetResponse":{"properties":{"source_provider":{"type":"string","title":"Source Provider"},"previous_state":{"type":"string","title":"Previous State"},"new_state":{"type":"string","const":"closed","title":"New State"}},"type":"object","required":["source_provider","previous_state","new_state"],"title":"CircuitResetResponse"},"CitationRead":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","title":"Kind"},"score":{"type":"number","title":"Score"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["id","kind","score","metadata"],"title":"CitationRead"},"CoachChatRequest":{"properties":{"message":{"type":"string","maxLength":4000,"minLength":1,"title":"Message"},"history":{"items":{"$ref":"#/components/schemas/CoachMessageRead"},"type":"array","title":"History"},"event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Id"},"top_k":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Top K","default":5}},"type":"object","required":["message"],"title":"CoachChatRequest"},"CoachChatResponse":{"properties":{"text":{"type":"string","title":"Text"},"citations":{"items":{"$ref":"#/components/schemas/CitationRead"},"type":"array","title":"Citations"},"blocked":{"type":"boolean","title":"Blocked","default":false},"block_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Block Reason"}},"type":"object","required":["text"],"title":"CoachChatResponse"},"CoachMessageRead":{"properties":{"role":{"type":"string","pattern":"^(user|assistant)$","title":"Role"},"content":{"type":"string","maxLength":4000,"minLength":1,"title":"Content"}},"type":"object","required":["role","content"],"title":"CoachMessageRead"},"ComboLegRead":{"properties":{"event_id":{"type":"string","title":"Event Id"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd"},"probability":{"type":"number","title":"Probability"}},"type":"object","required":["event_id","market_code","outcome","odd","probability"],"title":"ComboLegRead"},"ComboLegRequest":{"properties":{"event_id":{"type":"string","title":"Event Id"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"odd":{"anyOf":[{"type":"number","exclusiveMinimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Odd"},"probability":{"type":"number","exclusiveMaximum":1.0,"exclusiveMinimum":0.0,"title":"Probability"}},"type":"object","required":["event_id","market_code","outcome","odd","probability"],"title":"ComboLegRequest"},"ComparatorResponse":{"properties":{"market_code":{"type":"string","title":"Market Code"},"n_events":{"type":"integer","title":"N Events"},"items":{"items":{"$ref":"#/components/schemas/EventComparatorRow"},"type":"array","title":"Items"}},"type":"object","required":["market_code","n_events","items"],"title":"ComparatorResponse"},"ComputeResult":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"n_props_upserted":{"type":"integer","title":"N Props Upserted"},"n_players_considered":{"type":"integer","title":"N Players Considered"},"skipped_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Skipped Reason"},"lambda_home_team":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lambda Home Team"},"lambda_away_team":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lambda Away Team"}},"type":"object","required":["event_id","n_props_upserted","n_players_considered"],"title":"ComputeResult"},"ConsolidatedBankroll":{"properties":{"target_currency":{"type":"string","title":"Target Currency"},"total_balance":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Balance"},"accounts":{"items":{"$ref":"#/components/schemas/BankrollAccountRead"},"type":"array","title":"Accounts"},"allocations":{"items":{"$ref":"#/components/schemas/BankrollAllocationRead"},"type":"array","title":"Allocations"}},"type":"object","required":["target_currency","total_balance","accounts","allocations"],"title":"ConsolidatedBankroll"},"ContextualRequest":{"properties":{"current_route":{"type":"string","title":"Current Route"},"question":{"type":"string","maxLength":500,"minLength":1,"title":"Question"},"user_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"User Context"}},"type":"object","required":["current_route","question"],"title":"ContextualRequest"},"ContextualResponse":{"properties":{"answer":{"type":"string","title":"Answer"},"citations":{"items":{"type":"string"},"type":"array","title":"Citations"},"confidence":{"type":"number","title":"Confidence"}},"type":"object","required":["answer","citations","confidence"],"title":"ContextualResponse"},"CoverageResponse":{"properties":{"total_rows":{"type":"integer","title":"Total Rows"},"distinct_matches":{"type":"integer","title":"Distinct Matches"},"distinct_players":{"type":"integer","title":"Distinct Players"},"distinct_teams":{"type":"integer","title":"Distinct Teams"},"by_competition":{"items":{"$ref":"#/components/schemas/CoverageRow"},"type":"array","title":"By Competition"}},"type":"object","required":["total_rows","distinct_matches","distinct_players","distinct_teams","by_competition"],"title":"CoverageResponse"},"CoverageRow":{"properties":{"competition_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Competition Name"},"provider":{"type":"string","title":"Provider"},"n_matches":{"type":"integer","title":"N Matches"},"n_players":{"type":"integer","title":"N Players"},"n_teams":{"type":"integer","title":"N Teams"},"first_match":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"First Match"},"last_match":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Match"}},"type":"object","required":["competition_name","provider","n_matches","n_players","n_teams","first_match","last_match"],"title":"CoverageRow"},"DashboardLayoutRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"version":{"type":"integer","title":"Version"},"widgets":{"items":{"$ref":"#/components/schemas/WidgetConfig"},"type":"array","title":"Widgets"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","version","widgets","created_at","updated_at"],"title":"DashboardLayoutRead"},"DashboardLayoutUpdate":{"properties":{"widgets":{"items":{"$ref":"#/components/schemas/WidgetConfig"},"type":"array","title":"Widgets"}},"type":"object","required":["widgets"],"title":"DashboardLayoutUpdate"},"DataSourceCategory":{"type":"string","enum":["anj_operator","sharp_book","broker","aggregator","llm"],"title":"DataSourceCategory","description":"Catégorie de source de données."},"DemoteBody":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason","description":"Raison de la retrograde (audit log)."}},"type":"object","required":["reason"],"title":"DemoteBody"},"Disable2FARequest":{"properties":{"password":{"type":"string","maxLength":128,"minLength":1,"title":"Password"},"totp_code":{"type":"string","maxLength":6,"minLength":6,"title":"Totp Code"}},"type":"object","required":["password","totp_code"],"title":"Disable2FARequest","description":"Désactivation 2FA.\n\nRe-vérifie password ET code TOTP courant pour bloquer un attaquant\nqui aurait volé un token sans avoir l'app authenticator."},"DisclaimerAcceptance":{"properties":{"version":{"type":"string","maxLength":20,"minLength":1,"title":"Version"},"accept":{"type":"boolean","title":"Accept","default":true}},"type":"object","required":["version"],"title":"DisclaimerAcceptance"},"EquityCurveResponse":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"days_back":{"type":"integer","title":"Days Back"},"points":{"items":{"$ref":"#/components/schemas/src__routers__bankroll__EquityPoint"},"type":"array","title":"Points"}},"type":"object","required":["user_id","days_back","points"],"title":"EquityCurveResponse"},"EquitySeries":{"properties":{"label":{"type":"string","title":"Label"},"points":{"items":{"$ref":"#/components/schemas/src__routers__analytics__EquityPoint"},"type":"array","title":"Points"}},"type":"object","required":["label","points"],"title":"EquitySeries","description":"Une serie d'equity curve (un model_type ou strategy)."},"EventComparatorRow":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"kickoff":{"type":"string","format":"date-time","title":"Kickoff"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"league_slug":{"type":"string","title":"League Slug"},"league_name":{"type":"string","title":"League Name"},"outcomes":{"additionalProperties":{"items":{"$ref":"#/components/schemas/OddCell"},"type":"array"},"type":"object","title":"Outcomes"},"best_odds":{"additionalProperties":{"$ref":"#/components/schemas/OddCell"},"type":"object","title":"Best Odds"},"vig":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vig"}},"type":"object","required":["event_id","kickoff","home_team","away_team","league_slug","league_name","outcomes","best_odds","vig"],"title":"EventComparatorRow"},"EventExplanationsResponse":{"properties":{"event_id":{"type":"string","title":"Event Id"},"count":{"type":"integer","title":"Count"},"explanations":{"items":{"$ref":"#/components/schemas/PredictionExplanationRead"},"type":"array","title":"Explanations"}},"type":"object","required":["event_id","count","explanations"],"title":"EventExplanationsResponse"},"EventPredictionsResponse":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"count":{"type":"integer","title":"Count"},"predictions":{"items":{"$ref":"#/components/schemas/PredictionRead"},"type":"array","title":"Predictions"}},"type":"object","required":["event_id","count","predictions"],"title":"EventPredictionsResponse","description":"Toutes les prédictions pour un événement, groupées par marché."},"EventQualitativeRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"article_url":{"type":"string","title":"Article Url"},"article_source":{"type":"string","title":"Article Source"},"article_published_at":{"type":"string","format":"date-time","title":"Article Published At"},"detected_at":{"type":"string","format":"date-time","title":"Detected At"},"kind":{"type":"string","title":"Kind"},"impact":{"type":"string","title":"Impact"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"},"team_name_raw":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Name Raw"},"player_name_raw":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player Name Raw"},"confidence":{"type":"number","title":"Confidence"},"severity":{"type":"number","title":"Severity"},"ttl_days":{"type":"integer","title":"Ttl Days"},"rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rationale"}},"type":"object","required":["id","article_url","article_source","article_published_at","detected_at","kind","impact","team_id","team_name_raw","player_name_raw","confidence","severity","ttl_days","rationale"],"title":"EventQualitativeRead"},"EventRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","title":"Status"},"kickoff":{"type":"string","format":"date-time","title":"Kickoff"},"league":{"$ref":"#/components/schemas/LeagueInline"},"home_team":{"$ref":"#/components/schemas/TeamInline"},"away_team":{"$ref":"#/components/schemas/TeamInline"},"home_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score"},"away_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score"},"home_score_ht":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score Ht"},"away_score_ht":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score Ht"},"venue":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Venue"},"referee":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Referee"},"attendance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Attendance"},"round_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Round Name"},"season":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Season"}},"type":"object","required":["id","status","kickoff","league","home_team","away_team"],"title":"EventRead","description":"Vue détaillée d'un événement (cf. UX §18.3-A)."},"EventScoreBreakdownItemRead":{"properties":{"kind":{"type":"string","title":"Kind"},"impact":{"type":"string","title":"Impact"},"severity":{"type":"number","title":"Severity"},"confidence":{"type":"number","title":"Confidence"},"age_days":{"type":"number","title":"Age Days"},"ttl_days":{"type":"integer","title":"Ttl Days"},"contribution":{"type":"number","title":"Contribution"},"rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rationale"}},"type":"object","required":["kind","impact","severity","confidence","age_days","ttl_days","contribution","rationale"],"title":"EventScoreBreakdownItemRead"},"EventScoreResponse":{"properties":{"team_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Name"},"n_events":{"type":"integer","title":"N Events"},"event_score":{"type":"number","title":"Event Score"},"breakdown":{"items":{"$ref":"#/components/schemas/EventScoreBreakdownItemRead"},"type":"array","title":"Breakdown"},"events":{"items":{"$ref":"#/components/schemas/EventQualitativeRead"},"type":"array","title":"Events"}},"type":"object","required":["team_name","n_events","event_score","breakdown"],"title":"EventScoreResponse"},"EventsListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"items":{"items":{"$ref":"#/components/schemas/EventRead"},"type":"array","title":"Items"}},"type":"object","required":["count","items"],"title":"EventsListResponse"},"FacetCounts":{"properties":{"leagues":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Leagues"},"markets":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Markets"},"bookies":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Bookies"},"sports":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sports"},"model_types":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Model Types"},"years":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Years"}},"type":"object","required":["leagues","markets","bookies","sports","model_types","years"],"title":"FacetCounts","description":"Compte par facette (utile pour les filtres a chips dans l'UI)."},"FatigueResponse":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"home":{"$ref":"#/components/schemas/TeamFatigueOut"},"away":{"$ref":"#/components/schemas/TeamFatigueOut"},"delta_distance_14d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Distance 14D"},"delta_key_player_fatigue":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Key Player Fatigue"},"note":{"type":"string","title":"Note"},"home_proxy":{"$ref":"#/components/schemas/ProxyCompositeOut"},"away_proxy":{"$ref":"#/components/schemas/ProxyCompositeOut"},"delta_proxy":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Proxy"}},"type":"object","required":["event_id","home","away","delta_distance_14d","delta_key_player_fatigue","note","home_proxy","away_proxy","delta_proxy"],"title":"FatigueResponse"},"FcmDeviceRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"token":{"type":"string","title":"Token"},"platform":{"type":"string","title":"Platform"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"app_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Version"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_seen_at":{"type":"string","format":"date-time","title":"Last Seen At"}},"type":"object","required":["id","user_id","token","platform","device_name","app_version","created_at","last_seen_at"],"title":"FcmDeviceRead"},"FcmDeviceRegister":{"properties":{"token":{"type":"string","maxLength":512,"minLength":10,"title":"Token"},"platform":{"type":"string","enum":["ios","android","web"],"title":"Platform"},"device_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Device Name"},"app_version":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"App Version"}},"type":"object","required":["token","platform"],"title":"FcmDeviceRegister","description":"Payload register / upsert d'un token FCM mobile."},"FeatureContributionRead":{"properties":{"name":{"type":"string","title":"Name"},"label":{"type":"string","title":"Label"},"value":{"type":"number","title":"Value"},"log_contribution":{"type":"number","title":"Log Contribution"},"contribution_pct":{"type":"number","title":"Contribution Pct"},"side":{"type":"string","pattern":"^(home|away)$","title":"Side"}},"type":"object","required":["name","label","value","log_contribution","contribution_pct","side"],"title":"FeatureContributionRead"},"FollowsCountResponse":{"properties":{"followers":{"type":"integer","title":"Followers"},"following":{"type":"integer","title":"Following"}},"type":"object","required":["followers","following"],"title":"FollowsCountResponse"},"ForumMessageCreate":{"properties":{"body":{"type":"string","maxLength":2000,"minLength":1,"title":"Body"},"reply_to_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Reply To Id"}},"type":"object","required":["body"],"title":"ForumMessageCreate"},"ForumMessageRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"thread_id":{"type":"string","format":"uuid","title":"Thread Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"body":{"type":"string","title":"Body"},"moderation_verdict":{"type":"string","title":"Moderation Verdict"},"is_hidden":{"type":"boolean","title":"Is Hidden"},"reply_to_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Reply To Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","thread_id","user_id","body","moderation_verdict","is_hidden","reply_to_id","created_at"],"title":"ForumMessageRead"},"ForumMessagesListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"messages":{"items":{"$ref":"#/components/schemas/ForumMessageRead"},"type":"array","title":"Messages"}},"type":"object","required":["count","messages"],"title":"ForumMessagesListResponse"},"ForumThreadRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"is_locked":{"type":"boolean","title":"Is Locked"},"message_count":{"type":"integer","title":"Message Count"},"last_message_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Message At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","event_id","title","is_locked","message_count","last_message_at","created_at"],"title":"ForumThreadRead"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HalfLifePatch":{"properties":{"event_kind":{"type":"string","maxLength":50,"minLength":2,"title":"Event Kind"},"half_life_hours":{"type":"number","maximum":10000.0,"exclusiveMinimum":0.0,"title":"Half Life Hours"}},"type":"object","required":["event_kind","half_life_hours"],"title":"HalfLifePatch"},"HealthResponse":{"properties":{"status":{"type":"string","title":"Status"},"service":{"type":"string","title":"Service"},"version":{"type":"string","title":"Version"},"environment":{"type":"string","title":"Environment"},"timestamp":{"type":"string","title":"Timestamp"}},"type":"object","required":["status","service","version","environment","timestamp"],"title":"HealthResponse","description":"Réponse healthcheck."},"Hedge1X2Request":{"properties":{"bet_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Bet Id"},"initial_outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Initial Outcome"},"initial_odd":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Initial Odd"},"initial_stake":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Initial Stake"},"home_odd":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Home Odd"},"home_bookie":{"type":"string","title":"Home Bookie"},"draw_odd":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Draw Odd"},"draw_bookie":{"type":"string","title":"Draw Bookie"},"away_odd":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Away Odd"},"away_bookie":{"type":"string","title":"Away Bookie"},"min_profit_pct":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Min Profit Pct","default":0.0}},"type":"object","required":["home_odd","home_bookie","draw_odd","draw_bookie","away_odd","away_bookie"],"title":"Hedge1X2Request","description":"Hedge 3-way pour pari 1X2."},"Hedge2WayRequest":{"properties":{"bet_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Bet Id","description":"ID du bet existant — sinon fournir tous les champs"},"market_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Code"},"initial_outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Initial Outcome"},"initial_odd":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Initial Odd"},"initial_stake":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Initial Stake"},"initial_line":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Initial Line"},"opposite_odd":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Opposite Odd"},"opposite_bookie":{"type":"string","title":"Opposite Bookie"},"min_profit_pct":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Min Profit Pct","default":0.0}},"type":"object","required":["opposite_odd","opposite_bookie"],"title":"Hedge2WayRequest","description":"Hedge pour marché 2-way (OU, BTTS, AH demi-entier).\n\nL'user fournit son pari initial (bet_id ou détails) + la cote\nopposée trouvée chez un bookie."},"HedgeLegRead":{"properties":{"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd"},"stake":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Stake"},"bookie_slug":{"type":"string","title":"Bookie Slug"}},"type":"object","required":["outcome","odd","stake","bookie_slug"],"title":"HedgeLegRead"},"HedgeResultRead":{"properties":{"market_code":{"type":"string","title":"Market Code"},"initial_outcome":{"type":"string","title":"Initial Outcome"},"initial_odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Initial Odd"},"initial_stake":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Initial Stake"},"hedge_legs":{"items":{"$ref":"#/components/schemas/HedgeLegRead"},"type":"array","title":"Hedge Legs"},"guaranteed_profit":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Guaranteed Profit"},"guaranteed_profit_pct":{"type":"number","title":"Guaranteed Profit Pct"},"payout_per_outcome":{"additionalProperties":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},"type":"object","title":"Payout Per Outcome"},"total_invested":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Invested"},"analyzed_at":{"type":"string","format":"date-time","title":"Analyzed At"},"accepted":{"type":"boolean","title":"Accepted"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"}},"type":"object","required":["market_code","initial_outcome","initial_odd","initial_stake","hedge_legs","guaranteed_profit","guaranteed_profit_pct","payout_per_outcome","total_invested","analyzed_at","accepted"],"title":"HedgeResultRead"},"IpWhitelistAdd":{"properties":{"cidr":{"type":"string","title":"Cidr"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"expires_hours":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expires Hours"}},"type":"object","required":["cidr"],"title":"IpWhitelistAdd"},"IpWhitelistEnforceUpdate":{"properties":{"enforced":{"type":"boolean","title":"Enforced"},"auto_add_current_ip":{"type":"boolean","title":"Auto Add Current Ip","default":true},"current_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Ip"}},"type":"object","required":["enforced"],"title":"IpWhitelistEnforceUpdate"},"IpWhitelistEntryOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"cidr":{"type":"string","title":"Cidr"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"added_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Added By User Id"},"added_at":{"type":"string","format":"date-time","title":"Added At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["id","cidr","label","added_by_user_id","added_at","expires_at"],"title":"IpWhitelistEntryOut"},"IpWhitelistResponse":{"properties":{"enforced":{"type":"boolean","title":"Enforced"},"entries":{"items":{"$ref":"#/components/schemas/IpWhitelistEntryOut"},"type":"array","title":"Entries"},"n_active":{"type":"integer","title":"N Active"}},"type":"object","required":["enforced","entries","n_active"],"title":"IpWhitelistResponse"},"KeyPlayerOut":{"properties":{"canonical_name":{"type":"string","title":"Canonical Name"},"position":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Position"},"total_minutes_14d":{"type":"integer","title":"Total Minutes 14D"},"total_distance_14d":{"type":"number","title":"Total Distance 14D"}},"type":"object","required":["canonical_name","position","total_minutes_14d","total_distance_14d"],"title":"KeyPlayerOut"},"KillSwitchRead":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"is_paused":{"type":"boolean","title":"Is Paused"},"paused_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Paused Reason"},"paused_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paused Until"}},"type":"object","required":["user_id","is_paused","paused_reason","paused_until"],"title":"KillSwitchRead"},"KpiSummary":{"properties":{"n_total":{"type":"integer","title":"N Total","description":"Nombre total de value bets settled"},"n_won":{"type":"integer","title":"N Won"},"n_lost":{"type":"integer","title":"N Lost"},"n_push":{"type":"integer","title":"N Push"},"n_half_won":{"type":"integer","title":"N Half Won"},"n_half_lost":{"type":"integer","title":"N Half Lost"},"n_void":{"type":"integer","title":"N Void"},"n_pending":{"type":"integer","title":"N Pending","description":"settled_at IS NULL (event pas encore termine)"},"winrate_pct":{"type":"number","title":"Winrate Pct","description":"n_won / (n_won+n_lost) * 100"},"roi_pct":{"type":"number","title":"Roi Pct","description":"profit_loss_units / stake_units * 100"},"total_pnl_units":{"type":"number","title":"Total Pnl Units"},"total_stake_units":{"type":"number","title":"Total Stake Units"},"avg_odd":{"type":"number","title":"Avg Odd","description":"cote moyenne opened_odd"},"avg_ev_pct":{"type":"number","title":"Avg Ev Pct","description":"EV moyenne predite (%)"},"avg_clv_pct":{"type":"number","title":"Avg Clv Pct","description":"CLV moyen (%)"},"brier_score":{"type":"number","title":"Brier Score","description":"Brier mean((p-y)^2) — plus bas = mieux"},"log_loss":{"type":"number","title":"Log Loss","description":"-mean(y*log(p) + (1-y)*log(1-p))"},"ece":{"type":"number","title":"Ece","description":"Expected Calibration Error"},"mce":{"type":"number","title":"Mce","description":"Maximum Calibration Error sur les bins"},"sharpe_ratio":{"type":"number","title":"Sharpe Ratio","description":"Sharpe annualise (mean/std * sqrt(252))"},"max_drawdown_pct":{"type":"number","title":"Max Drawdown Pct","description":"Max drawdown en % du peak"},"var_95_units":{"type":"number","title":"Var 95 Units","description":"Value at Risk 95% des paris settled (u)"},"largest_loss_units":{"type":"number","title":"Largest Loss Units","description":"Plus grosse perte unitaire (u)"},"period_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period Label"}},"type":"object","required":["n_total","n_won","n_lost","n_push","n_half_won","n_half_lost","n_void","n_pending","winrate_pct","roi_pct","total_pnl_units","total_stake_units","avg_odd","avg_ev_pct","avg_clv_pct","brier_score","log_loss","ece","mce","sharpe_ratio","max_drawdown_pct","var_95_units","largest_loss_units"],"title":"KpiSummary","description":"KPI agreges pour la periode/filtre courant."},"LeagueInline":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"sport_code":{"type":"string","title":"Sport Code"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"}},"type":"object","required":["id","slug","name","sport_code"],"title":"LeagueInline"},"Leg":{"properties":{"event_id":{"type":"string","title":"Event Id"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"odd":{"type":"number","title":"Odd"},"probability":{"type":"number","title":"Probability"}},"type":"object","required":["event_id","market_code","outcome","odd","probability"],"title":"Leg"},"LoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","title":"Password"},"totp_code":{"anyOf":[{"type":"string","maxLength":6,"minLength":6},{"type":"null"}],"title":"Totp Code"}},"type":"object","required":["email","password"],"title":"LoginRequest","description":"Connexion."},"ModelComparisonEntry":{"properties":{"model_type":{"type":"string","title":"Model Type"},"n_total":{"type":"integer","title":"N Total"},"n_won":{"type":"integer","title":"N Won"},"n_lost":{"type":"integer","title":"N Lost"},"winrate_pct":{"type":"number","title":"Winrate Pct"},"roi_pct":{"type":"number","title":"Roi Pct"},"total_pnl_units":{"type":"number","title":"Total Pnl Units"},"total_stake_units":{"type":"number","title":"Total Stake Units"},"avg_odd":{"type":"number","title":"Avg Odd"},"avg_ev_pct":{"type":"number","title":"Avg Ev Pct"},"sharpe_ratio":{"type":"number","title":"Sharpe Ratio"},"max_drawdown_pct":{"type":"number","title":"Max Drawdown Pct"},"rank":{"type":"integer","title":"Rank","description":"1 = meilleur ROI, 2 = ..."}},"type":"object","required":["model_type","n_total","n_won","n_lost","winrate_pct","roi_pct","total_pnl_units","total_stake_units","avg_odd","avg_ev_pct","sharpe_ratio","max_drawdown_pct","rank"],"title":"ModelComparisonEntry","description":"ROI/winrate aggregat pour un model_type donne."},"ModelComparisonResponse":{"properties":{"period_label":{"type":"string","title":"Period Label"},"models":{"items":{"$ref":"#/components/schemas/ModelComparisonEntry"},"type":"array","title":"Models"},"best_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Best Model"},"recommendation":{"type":"string","title":"Recommendation"}},"type":"object","required":["period_label","models","best_model","recommendation"],"title":"ModelComparisonResponse"},"ModelVersionRead":{"properties":{"sport_code":{"type":"string","title":"Sport Code"},"model_type":{"type":"string","title":"Model Type"},"league_slug":{"type":"string","title":"League Slug"},"version":{"type":"string","title":"Version"},"n_matches_trained":{"type":"integer","title":"N Matches Trained"},"trained_at":{"type":"string","format":"date-time","title":"Trained At"},"is_active":{"type":"boolean","title":"Is Active"},"storage_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Storage Path"},"metrics":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metrics"}},"type":"object","required":["sport_code","model_type","league_slug","version","n_matches_trained","trained_at","is_active"],"title":"ModelVersionRead","description":"Version d'un modèle entraîné."},"NotificationPrefRead":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"min_ev":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Min Ev"},"sports":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sports"},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Markets"},"bookies":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies"},"hours_active_utc":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Hours Active Utc"},"max_per_hour":{"type":"integer","title":"Max Per Hour"},"channels":{"additionalProperties":true,"type":"object","title":"Channels"},"telegram_linked":{"type":"boolean","title":"Telegram Linked","default":false},"quiet_hours_start_utc":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Quiet Hours Start Utc"},"quiet_hours_end_utc":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Quiet Hours End Utc"},"min_ev_during_quiet":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Min Ev During Quiet"},"vacation_from":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Vacation From"},"vacation_until":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Vacation Until"},"focus_mode_enabled":{"type":"boolean","title":"Focus Mode Enabled","default":false},"focus_mode_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Focus Mode Until"}},"type":"object","required":["enabled","min_ev","max_per_hour","channels"],"title":"NotificationPrefRead","description":"Vue des préférences (réponse GET /me/notification-prefs)."},"NotificationPrefUpdate":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"min_ev":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Min Ev"},"sports":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sports"},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Markets"},"bookies":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies"},"hours_active_utc":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Hours Active Utc","description":"Liste d'heures UTC (0..23). None = 24/24."},"max_per_hour":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":0.0},{"type":"null"}],"title":"Max Per Hour"},"channels":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Channels"},"quiet_hours_start_utc":{"anyOf":[{"type":"integer","maximum":23.0,"minimum":0.0},{"type":"null"}],"title":"Quiet Hours Start Utc"},"quiet_hours_end_utc":{"anyOf":[{"type":"integer","maximum":23.0,"minimum":0.0},{"type":"null"}],"title":"Quiet Hours End Utc"},"min_ev_during_quiet":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Min Ev During Quiet"},"clear_quiet_hours":{"type":"boolean","title":"Clear Quiet Hours","default":false},"vacation_from":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Vacation From"},"vacation_until":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Vacation Until"},"clear_vacation":{"type":"boolean","title":"Clear Vacation","default":false},"focus_mode_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Focus Mode Enabled"},"focus_mode_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Focus Mode Until"},"clear_focus_until":{"type":"boolean","title":"Clear Focus Until","default":false}},"type":"object","title":"NotificationPrefUpdate","description":"Patch partiel des préférences."},"NotificationTestResult":{"properties":{"telegram":{"type":"string","title":"Telegram"},"push":{"type":"string","title":"Push"}},"type":"object","required":["telegram","push"],"title":"NotificationTestResult","description":"Résultat d'un envoi de test (par canal)."},"OddCell":{"properties":{"bookie_slug":{"type":"string","title":"Bookie Slug"},"odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"fetched_at":{"type":"string","format":"date-time","title":"Fetched At"}},"type":"object","required":["bookie_slug","odd","line","fetched_at"],"title":"OddCell"},"OddsHistoryPoint":{"properties":{"fetched_at":{"type":"string","title":"Fetched At"},"bookie_slug":{"type":"string","title":"Bookie Slug"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Line"},"odd_decimal":{"type":"number","title":"Odd Decimal"}},"type":"object","required":["fetched_at","bookie_slug","market_code","outcome","line","odd_decimal"],"title":"OddsHistoryPoint"},"OddsHistoryResponse":{"properties":{"event_id":{"type":"string","title":"Event Id"},"count":{"type":"integer","title":"Count"},"points":{"items":{"$ref":"#/components/schemas/OddsHistoryPoint"},"type":"array","title":"Points"}},"type":"object","required":["event_id","count","points"],"title":"OddsHistoryResponse"},"OpportunitiesResponse":{"properties":{"count":{"type":"integer","title":"Count"},"n_value_bets":{"type":"integer","title":"N Value Bets"},"n_player_props":{"type":"integer","title":"N Player Props"},"filters_applied":{"additionalProperties":true,"type":"object","title":"Filters Applied"},"items":{"items":{"$ref":"#/components/schemas/OpportunityItem"},"type":"array","title":"Items"}},"type":"object","required":["count","n_value_bets","n_player_props","filters_applied","items"],"title":"OpportunitiesResponse"},"OpportunityItem":{"properties":{"kind":{"type":"string","title":"Kind"},"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"event_kickoff":{"type":"string","format":"date-time","title":"Event Kickoff"},"home_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team"},"away_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team"},"league":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League"},"sport":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"fair_prob":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Fair Prob"},"odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd"},"bookie_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"},"ev":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Ev"},"kelly_fraction":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Kelly Fraction"},"model_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"},"player_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player Name"}},"type":"object","required":["kind","id","event_id","event_kickoff","home_team","away_team","league","sport","market_code","outcome","line","fair_prob","odd","bookie_slug","ev"],"title":"OpportunityItem","description":"Une opportunité EV+ unifiée. `kind` discrimine value_bet vs player_prop."},"OptimizeComboRead":{"properties":{"legs":{"items":{"$ref":"#/components/schemas/OptimizeLegRead"},"type":"array","title":"Legs"},"combined_odd":{"type":"number","title":"Combined Odd"},"combined_probability":{"type":"number","title":"Combined Probability"},"expected_value":{"type":"number","title":"Expected Value"},"expected_value_pct":{"type":"number","title":"Expected Value Pct"},"correlation_penalty":{"type":"number","title":"Correlation Penalty"},"score":{"type":"number","title":"Score"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["legs","combined_odd","combined_probability","expected_value","expected_value_pct","correlation_penalty","score","warnings"],"title":"OptimizeComboRead"},"OptimizeComboResponse":{"properties":{"n_candidates_considered":{"type":"integer","title":"N Candidates Considered"},"combos":{"items":{"$ref":"#/components/schemas/OptimizeComboRead"},"type":"array","title":"Combos"}},"type":"object","required":["n_candidates_considered","combos"],"title":"OptimizeComboResponse"},"OptimizeLegRead":{"properties":{"value_bet_id":{"type":"string","title":"Value Bet Id"},"event_id":{"type":"string","title":"Event Id"},"league_slug":{"type":"string","title":"League Slug"},"home_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team"},"away_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team"},"kickoff":{"type":"string","format":"date-time","title":"Kickoff"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"odd":{"type":"number","title":"Odd"},"probability":{"type":"number","title":"Probability"},"ev_pct":{"type":"number","title":"Ev Pct"},"bookie_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bookie Slug"}},"type":"object","required":["value_bet_id","event_id","league_slug","kickoff","market_code","outcome","odd","probability","ev_pct"],"title":"OptimizeLegRead"},"OptimizeResponse":{"properties":{"candidates":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Candidates"}},"type":"object","required":["candidates"],"title":"OptimizeResponse"},"PlaceOrderBody":{"properties":{"broker_slug":{"type":"string","maxLength":50,"minLength":2,"title":"Broker Slug"},"event_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Event Id"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"stake":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Stake"},"odd_taken":{"anyOf":[{"type":"number","minimum":1.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Odd Taken"},"currency":{"type":"string","title":"Currency","default":"EUR"},"value_bet_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Value Bet Id"},"placement_mode":{"type":"string","title":"Placement Mode","default":"manual"}},"type":"object","required":["broker_slug","market_code","outcome","stake","odd_taken"],"title":"PlaceOrderBody"},"PlayerPropRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"player_name":{"type":"string","title":"Player Name"},"player_external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Player External Id"},"prop_kind":{"type":"string","title":"Prop Kind"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"fair_prob":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Fair Prob"},"fair_odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Fair Odd"},"best_bookie_odd":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Best Bookie Odd"},"best_bookie_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Best Bookie Slug"},"ev":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Ev"},"last_updated_at":{"type":"string","format":"date-time","title":"Last Updated At"}},"type":"object","required":["id","event_id","player_name","player_external_id","prop_kind","line","fair_prob","fair_odd","best_bookie_odd","best_bookie_slug","ev","last_updated_at"],"title":"PlayerPropRead"},"PlayerPropsResponse":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"count":{"type":"integer","title":"Count"},"items":{"items":{"$ref":"#/components/schemas/PlayerPropRead"},"type":"array","title":"Items"}},"type":"object","required":["event_id","count","items"],"title":"PlayerPropsResponse"},"PositionStatRow":{"properties":{"position":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Position"},"n_player_matches":{"type":"integer","title":"N Player Matches"},"avg_minutes":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Minutes"},"avg_distance_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Distance Km"},"avg_intensity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Intensity"}},"type":"object","required":["position","n_player_matches","avg_minutes","avg_distance_km","avg_intensity"],"title":"PositionStatRow"},"PredictionExplanationRead":{"properties":{"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"probability":{"type":"number","title":"Probability"},"fair_odd":{"type":"number","title":"Fair Odd"},"lambda_home":{"type":"number","title":"Lambda Home"},"lambda_away":{"type":"number","title":"Lambda Away"},"features":{"items":{"$ref":"#/components/schemas/FeatureContributionRead"},"type":"array","title":"Features"},"baseline_lambda_home":{"type":"number","title":"Baseline Lambda Home"},"baseline_lambda_away":{"type":"number","title":"Baseline Lambda Away"},"summary":{"type":"string","title":"Summary"}},"type":"object","required":["market_code","outcome","probability","fair_odd","lambda_home","lambda_away","features","baseline_lambda_home","baseline_lambda_away","summary"],"title":"PredictionExplanationRead"},"PredictionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"sport_code":{"type":"string","title":"Sport Code"},"model_type":{"type":"string","title":"Model Type"},"model_version":{"type":"string","title":"Model Version"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"probability":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Probability"},"fair_odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Fair Odd"},"predicted_at":{"type":"string","format":"date-time","title":"Predicted At"},"aux_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Aux Data"}},"type":"object","required":["id","event_id","sport_code","model_type","model_version","market_code","outcome","probability","fair_odd","predicted_at"],"title":"PredictionRead","description":"Prédiction renvoyée par l'API."},"PreferencesRead":{"properties":{"locale":{"type":"string","title":"Locale"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["locale","timezone"],"title":"PreferencesRead"},"PreferencesUpdate":{"properties":{"locale":{"anyOf":[{"type":"string","maxLength":5,"minLength":2},{"type":"null"}],"title":"Locale"},"timezone":{"anyOf":[{"type":"string","maxLength":50,"minLength":3},{"type":"null"}],"title":"Timezone"}},"type":"object","title":"PreferencesUpdate","description":"Update partiel : seuls les champs fournis sont modifiés."},"PromoteBody":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Reason","description":"Note libre justifiant la promotion (audit log)."}},"type":"object","title":"PromoteBody","description":"Optional context fourni par l'admin lors de la promotion."},"PropOddsUpdate":{"properties":{"best_bookie_odd":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Best Bookie Odd"},"best_bookie_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Best Bookie Slug"}},"type":"object","required":["best_bookie_odd"],"title":"PropOddsUpdate","description":"Set best_bookie_odd + best_bookie_slug manuellement. Pour clear,\npasser null sur best_bookie_odd."},"ProxyComponentOut":{"properties":{"name":{"type":"string","title":"Name"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"weight":{"type":"number","title":"Weight"},"raw":{"additionalProperties":true,"type":"object","title":"Raw"}},"type":"object","required":["name","value","weight","raw"],"title":"ProxyComponentOut"},"ProxyCompositeOut":{"properties":{"composite_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Composite Score"},"confidence":{"type":"number","title":"Confidence"},"components":{"items":{"$ref":"#/components/schemas/ProxyComponentOut"},"type":"array","title":"Components"},"sources_used":{"items":{"type":"string"},"type":"array","title":"Sources Used"}},"type":"object","required":["composite_score","confidence","components","sources_used"],"title":"ProxyCompositeOut"},"PushKeys":{"properties":{"p256dh":{"type":"string","title":"P256Dh"},"auth":{"type":"string","title":"Auth"}},"type":"object","required":["p256dh","auth"],"title":"PushKeys"},"PushSubscriptionIn":{"properties":{"endpoint":{"type":"string","title":"Endpoint"},"keys":{"$ref":"#/components/schemas/PushKeys"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"}},"type":"object","required":["endpoint","keys"],"title":"PushSubscriptionIn"},"QuestStepBody":{"properties":{"step":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Step"}},"type":"object","required":["step"],"title":"QuestStepBody"},"RbacMatrix":{"properties":{"roles":{"items":{"type":"string"},"type":"array","title":"Roles"},"permissions":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Permissions"}},"type":"object","required":["roles","permissions"],"title":"RbacMatrix"},"ReadinessResponse":{"properties":{"status":{"type":"string","title":"Status"},"service":{"type":"string","title":"Service"},"version":{"type":"string","title":"Version"},"environment":{"type":"string","title":"Environment"},"timestamp":{"type":"string","title":"Timestamp"},"dependencies":{"additionalProperties":{"type":"string"},"type":"object","title":"Dependencies"},"latencies_ms":{"additionalProperties":{"type":"number"},"type":"object","title":"Latencies Ms"}},"type":"object","required":["status","service","version","environment","timestamp","dependencies","latencies_ms"],"title":"ReadinessResponse","description":"Réponse readiness avec dépendances."},"RecalcEvResult":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"n_recalculated":{"type":"integer","title":"N Recalculated"},"n_with_ev_positive":{"type":"integer","title":"N With Ev Positive"}},"type":"object","required":["event_id","n_recalculated","n_with_ev_positive"],"title":"RecalcEvResult"},"RecomputeOut":{"properties":{"edge_threshold":{"type":"number","title":"Edge Threshold"},"n_events_scanned":{"type":"integer","title":"N Events Scanned"},"n_predictions_evaluated":{"type":"integer","title":"N Predictions Evaluated"},"n_shadow_bets_inserted":{"type":"integer","title":"N Shadow Bets Inserted"},"n_shadow_bets_settled":{"type":"integer","title":"N Shadow Bets Settled"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"}},"type":"object","required":["edge_threshold","n_events_scanned","n_predictions_evaluated","n_shadow_bets_inserted","n_shadow_bets_settled","errors"],"title":"RecomputeOut"},"RefreshRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshRequest","description":"Demande de refresh."},"RegisterRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","maxLength":128,"minLength":12,"title":"Password"},"username":{"anyOf":[{"type":"string","maxLength":50,"minLength":3},{"type":"null"}],"title":"Username"}},"type":"object","required":["email","password"],"title":"RegisterRequest","description":"Inscription d'un nouvel utilisateur."},"RejectBody":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason","description":"Raison du rejet (obligatoire pour audit log)."}},"type":"object","required":["reason"],"title":"RejectBody"},"RestrictionPatch":{"properties":{"market_codes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Market Codes"},"max_stake_eur":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Max Stake Eur"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"RestrictionPatch","description":"Patch partiel : tous les champs optionnels.\n\nPermet de toggle is_active (soft-delete / re-activate) ou d'editer\nmarket_codes / max_stake_eur / notes sans recreer la ligne."},"RestrictionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"bookie_slug":{"type":"string","title":"Bookie Slug"},"market_codes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Market Codes"},"max_stake_eur":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Max Stake Eur"},"declared_at":{"type":"string","format":"date-time","title":"Declared At"},"source":{"type":"string","title":"Source"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["id","bookie_slug","market_codes","max_stake_eur","declared_at","source","notes","is_active"],"title":"RestrictionRead"},"RestrictionUpsert":{"properties":{"bookie_slug":{"type":"string","maxLength":50,"minLength":2,"title":"Bookie Slug"},"market_codes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Market Codes"},"max_stake_eur":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Max Stake Eur"},"source":{"type":"string","title":"Source","default":"manual"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["bookie_slug"],"title":"RestrictionUpsert"},"RgLimitsRead":{"properties":{"weekly_stake_max_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weekly Stake Max Eur"},"weekly_loss_max_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weekly Loss Max Eur"},"monthly_loss_max_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Monthly Loss Max Eur"},"auto_exclude_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Auto Exclude Until"},"last_acknowledged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Acknowledged At"},"is_currently_excluded":{"type":"boolean","title":"Is Currently Excluded"}},"type":"object","required":["weekly_stake_max_eur","weekly_loss_max_eur","monthly_loss_max_eur","auto_exclude_until","last_acknowledged_at","is_currently_excluded"],"title":"RgLimitsRead","description":"Caps Jeu Responsable (NULL = pas de cap configuré)."},"RgLimitsUpdate":{"properties":{"weekly_stake_max_eur":{"anyOf":[{"type":"number","maximum":1000000.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Weekly Stake Max Eur"},"weekly_loss_max_eur":{"anyOf":[{"type":"number","maximum":1000000.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Weekly Loss Max Eur"},"monthly_loss_max_eur":{"anyOf":[{"type":"number","maximum":1000000.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Monthly Loss Max Eur"},"self_exclude_for_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Self Exclude For Days"},"clear_weekly_stake":{"type":"boolean","title":"Clear Weekly Stake","default":false},"clear_weekly_loss":{"type":"boolean","title":"Clear Weekly Loss","default":false},"clear_monthly_loss":{"type":"boolean","title":"Clear Monthly Loss","default":false},"clear_self_exclusion":{"type":"boolean","title":"Clear Self Exclusion","default":false},"acknowledge":{"type":"boolean","title":"Acknowledge","default":false}},"type":"object","title":"RgLimitsUpdate","description":"Update PUT. Tous les champs optionnels :\n- `None` = on n'écrit pas ce champ\n- explicite `null` JSON dans le body = on retire le cap (mais notre\n  Pydantic ne distingue pas null vs absent ; pour 'retirer' on\n  utilise le champ `clear_*` parallèle)."},"RoiBucketResponse":{"properties":{"since_days":{"type":"integer","title":"Since Days"},"total_settled_bets":{"type":"integer","title":"Total Settled Bets"},"n_with_fatigue_data":{"type":"integer","title":"N With Fatigue Data"},"n_without_fatigue_data":{"type":"integer","title":"N Without Fatigue Data"},"coverage_pct":{"type":"number","title":"Coverage Pct"},"buckets":{"items":{"$ref":"#/components/schemas/RoiBucketRow"},"type":"array","title":"Buckets"},"note":{"type":"string","title":"Note"}},"type":"object","required":["since_days","total_settled_bets","n_with_fatigue_data","n_without_fatigue_data","coverage_pct","buckets","note"],"title":"RoiBucketResponse"},"RoiBucketRow":{"properties":{"bucket_label":{"type":"string","title":"Bucket Label"},"delta_km_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Km Min"},"delta_km_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Km Max"},"n_bets":{"type":"integer","title":"N Bets"},"n_won":{"type":"integer","title":"N Won"},"won_rate":{"type":"number","title":"Won Rate"},"total_stake":{"type":"number","title":"Total Stake"},"total_pnl":{"type":"number","title":"Total Pnl"},"roi_pct":{"type":"number","title":"Roi Pct"}},"type":"object","required":["bucket_label","delta_km_min","delta_km_max","n_bets","n_won","won_rate","total_stake","total_pnl","roi_pct"],"title":"RoiBucketRow"},"RosterIngestResult":{"properties":{"sport":{"type":"string","title":"Sport"},"n_teams_matched":{"type":"integer","title":"N Teams Matched"},"n_teams_unmatched":{"type":"integer","title":"N Teams Unmatched"},"n_players_upserted":{"type":"integer","title":"N Players Upserted"},"n_players_skipped":{"type":"integer","title":"N Players Skipped"},"unmatched_team_names":{"items":{"type":"string"},"type":"array","title":"Unmatched Team Names"}},"type":"object","required":["sport","n_teams_matched","n_teams_unmatched","n_players_upserted","n_players_skipped","unmatched_team_names"],"title":"RosterIngestResult"},"RuleConditions":{"properties":{"min_ev":{"type":"number","title":"Min Ev","default":0.04},"min_kelly":{"type":"number","title":"Min Kelly","default":0.005},"sports":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sports"},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Markets"},"leagues":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Leagues"},"bookies_whitelist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Bookies Whitelist"},"max_stake_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Stake Eur"},"max_total_today_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Total Today Eur"},"max_concurrent_open":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Concurrent Open"}},"type":"object","title":"RuleConditions"},"RuleRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"mode":{"type":"string","title":"Mode"},"conditions":{"additionalProperties":true,"type":"object","title":"Conditions"},"stake_strategy":{"type":"string","title":"Stake Strategy"},"stake_param":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Stake Param"},"broker_routing":{"type":"string","title":"Broker Routing"},"broker_fixed_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Broker Fixed Slug"},"strategy_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Strategy Slug"},"enabled":{"type":"boolean","title":"Enabled"},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Triggered At"},"n_triggered_total":{"type":"integer","title":"N Triggered Total"},"n_placed_total":{"type":"integer","title":"N Placed Total"},"n_rejected_total":{"type":"integer","title":"N Rejected Total"},"legal_disclaimer_accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Legal Disclaimer Accepted At"}},"type":"object","required":["id","name","description","mode","conditions","stake_strategy","stake_param","broker_routing","broker_fixed_slug","strategy_slug","enabled","last_triggered_at","n_triggered_total","n_placed_total","n_rejected_total","legal_disclaimer_accepted_at"],"title":"RuleRead"},"RuleUpsert":{"properties":{"name":{"type":"string","maxLength":80,"minLength":2,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"mode":{"$ref":"#/components/schemas/AutoBetMode","default":"pilot"},"conditions":{"$ref":"#/components/schemas/RuleConditions"},"stake_strategy":{"$ref":"#/components/schemas/StakeStrategy","default":"kelly_quarter"},"stake_param":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Stake Param","default":"10.00"},"broker_routing":{"$ref":"#/components/schemas/BrokerRouting","default":"cheapest"},"broker_fixed_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Broker Fixed Slug"},"strategy_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Strategy Slug"},"enabled":{"type":"boolean","title":"Enabled","default":true}},"type":"object","required":["name","conditions"],"title":"RuleUpsert"},"SaveRunBody":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"configs":{"items":{"$ref":"#/components/schemas/BacktestConfigBody"},"type":"array","title":"Configs"},"results":{"items":{"$ref":"#/components/schemas/BacktestResultRead"},"type":"array","title":"Results"}},"type":"object","required":["name","configs","results"],"title":"SaveRunBody"},"SavedRunDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"n_strategies":{"type":"integer","title":"N Strategies"},"configs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Configs"},"results":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Results"},"period_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period From"},"period_to":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period To"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","tags","n_strategies","configs","results","period_from","period_to","created_at"],"title":"SavedRunDetail"},"SavedRunRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"n_strategies":{"type":"integer","title":"N Strategies"},"period_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period From"},"period_to":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period To"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"headline_roi":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Headline Roi"},"headline_sharpe":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Headline Sharpe"},"headline_n_bets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Headline N Bets"}},"type":"object","required":["id","name","tags","n_strategies","period_from","period_to","created_at"],"title":"SavedRunRead"},"ShrinkageEntry":{"properties":{"sport_code":{"type":"string","title":"Sport Code"},"league_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League Slug"},"market_code":{"type":"string","title":"Market Code"},"model_type":{"type":"string","title":"Model Type"},"shrink_factor":{"type":"number","title":"Shrink Factor"},"n_samples":{"type":"integer","title":"N Samples"},"mean_implied_winrate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean Implied Winrate"},"mean_realized_winrate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean Realized Winrate"},"mean_ev_estimated":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean Ev Estimated"},"mean_ev_realized":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean Ev Realized"},"computed_at":{"type":"string","format":"date-time","title":"Computed At"}},"type":"object","required":["sport_code","league_slug","market_code","model_type","shrink_factor","n_samples","mean_implied_winrate","mean_realized_winrate","mean_ev_estimated","mean_ev_realized","computed_at"],"title":"ShrinkageEntry"},"SourceConfidencePatch":{"properties":{"source":{"type":"string","maxLength":50,"minLength":2,"title":"Source"},"confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence"}},"type":"object","required":["source","confidence"],"title":"SourceConfidencePatch"},"SourceHealthRead":{"properties":{"source_provider":{"type":"string","title":"Source Provider"},"circuit_state":{"type":"string","enum":["closed","open","half_open"],"title":"Circuit State"},"circuit_open_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Circuit Open Until"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Failure At"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures"},"total_requests":{"type":"integer","title":"Total Requests"},"total_failures":{"type":"integer","title":"Total Failures"},"last_response_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Response Status"},"last_error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error Message"},"success_rate_lifetime":{"type":"number","title":"Success Rate Lifetime"},"silent_for_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Silent For Seconds"},"status_label":{"type":"string","enum":["healthy","degraded","silent","open","unknown"],"title":"Status Label"}},"type":"object","required":["source_provider","circuit_state","circuit_open_until","last_success_at","last_failure_at","consecutive_failures","total_requests","total_failures","last_response_status","last_error_message","success_rate_lifetime","silent_for_seconds","status_label"],"title":"SourceHealthRead"},"SourcesHealthResponse":{"properties":{"fetched_at":{"type":"string","format":"date-time","title":"Fetched At"},"n_sources":{"type":"integer","title":"N Sources"},"n_healthy":{"type":"integer","title":"N Healthy"},"n_degraded":{"type":"integer","title":"N Degraded"},"n_silent":{"type":"integer","title":"N Silent"},"n_circuit_open":{"type":"integer","title":"N Circuit Open"},"sources":{"items":{"$ref":"#/components/schemas/SourceHealthRead"},"type":"array","title":"Sources"}},"type":"object","required":["fetched_at","n_sources","n_healthy","n_degraded","n_silent","n_circuit_open","sources"],"title":"SourcesHealthResponse"},"StakeStrategy":{"type":"string","enum":["flat","kelly","kelly_quarter","kelly_eighth","confidence_weighted"],"title":"StakeStrategy"},"StatsOut":{"properties":{"since_days":{"type":"integer","title":"Since Days"},"buckets":{"items":{"$ref":"#/components/schemas/BucketRow"},"type":"array","title":"Buckets"}},"type":"object","required":["since_days","buckets"],"title":"StatsOut"},"StrategyCreate":{"properties":{"slug":{"type":"string","maxLength":80,"minLength":2,"pattern":"^[a-z0-9_-]+$","title":"Slug"},"name":{"type":"string","maxLength":120,"minLength":2,"title":"Name"},"description":{"type":"string","maxLength":2000,"minLength":10,"title":"Description"},"filters":{"additionalProperties":true,"type":"object","title":"Filters"},"price_monthly_eur":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Price Monthly Eur","default":"0"}},"type":"object","required":["slug","name","description","filters"],"title":"StrategyCreate"},"StrategyPatch":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000,"minLength":10},{"type":"null"}],"title":"Description"},"filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filters"},"price_monthly_eur":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Price Monthly Eur"},"status":{"anyOf":[{"type":"string","pattern":"^(draft|published|paused|archived)$"},{"type":"null"}],"title":"Status"}},"type":"object","title":"StrategyPatch","description":"Champs editable par l'auteur sur sa propre strategie."},"StrategyRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"author_id":{"type":"string","format":"uuid","title":"Author Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"status":{"type":"string","title":"Status"},"filters":{"additionalProperties":true,"type":"object","title":"Filters"},"price_monthly_eur":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Price Monthly Eur"},"is_free":{"type":"boolean","title":"Is Free"},"n_value_bets_30d":{"type":"integer","title":"N Value Bets 30D"},"avg_ev_pct_30d":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Avg Ev Pct 30D"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","author_id","slug","name","description","status","filters","price_monthly_eur","is_free","n_value_bets_30d","avg_ev_pct_30d","created_at"],"title":"StrategyRead"},"SurebetEventInfo":{"properties":{"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"league_name":{"type":"string","title":"League Name"},"sport_code":{"type":"string","title":"Sport Code"},"kickoff":{"type":"string","format":"date-time","title":"Kickoff"},"status":{"type":"string","title":"Status"}},"type":"object","required":["home_team","away_team","league_name","sport_code","kickoff","status"],"title":"SurebetEventInfo","description":"Sous-schema enrichi : equipes + competition + statut live."},"SurebetRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"sport_code":{"type":"string","title":"Sport Code"},"market_code":{"type":"string","title":"Market Code"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"surebet_type":{"type":"string","title":"Surebet Type"},"legs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Legs"},"sum_inverse":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Sum Inverse"},"profit_pct":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Profit Pct"},"total_stake":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Stake"},"guaranteed_payout":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Guaranteed Payout"},"detected_at":{"type":"string","format":"date-time","title":"Detected At"},"is_live":{"type":"boolean","title":"Is Live"},"invalidated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Invalidated At"},"invalidation_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invalidation Reason"},"ttl_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ttl Seconds"},"extra":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Extra"},"event":{"anyOf":[{"$ref":"#/components/schemas/SurebetEventInfo"},{"type":"null"}]}},"type":"object","required":["id","event_id","sport_code","market_code","surebet_type","legs","sum_inverse","profit_pct","total_stake","guaranteed_payout","detected_at","is_live"],"title":"SurebetRead"},"SurebetType":{"type":"string","enum":["standard","ah_half","ah_quarter","delayed"],"title":"SurebetType","description":"Type de surebet détecté."},"SurebetsListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"items":{"items":{"$ref":"#/components/schemas/SurebetRead"},"type":"array","title":"Items"}},"type":"object","required":["count","items"],"title":"SurebetsListResponse"},"SyncOddsResult":{"properties":{"event_id":{"type":"string","format":"uuid","title":"Event Id"},"source_tried":{"type":"string","title":"Source Tried"},"n_props_matched":{"type":"integer","title":"N Props Matched"},"n_props_updated":{"type":"integer","title":"N Props Updated"},"message":{"type":"string","title":"Message"}},"type":"object","required":["event_id","source_tried","n_props_matched","n_props_updated","message"],"title":"SyncOddsResult"},"TOTPSetupResponse":{"properties":{"secret":{"type":"string","title":"Secret"},"provisioning_uri":{"type":"string","title":"Provisioning Uri"},"backup_codes":{"items":{"type":"string"},"type":"array","title":"Backup Codes"}},"type":"object","required":["secret","provisioning_uri","backup_codes"],"title":"TOTPSetupResponse","description":"Réponse activation 2FA TOTP."},"TOTPVerifyRequest":{"properties":{"code":{"type":"string","maxLength":6,"minLength":6,"title":"Code"}},"type":"object","required":["code"],"title":"TOTPVerifyRequest","description":"Vérification d'un code TOTP pour activer 2FA."},"TeamFatigueOut":{"properties":{"team_id":{"type":"string","format":"uuid","title":"Team Id"},"team_name":{"type":"string","title":"Team Name"},"matched_external_team":{"type":"boolean","title":"Matched External Team"},"matches_last_7d":{"type":"integer","title":"Matches Last 7D"},"matches_last_14d":{"type":"integer","title":"Matches Last 14D"},"team_distance_cumulated_7d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Team Distance Cumulated 7D"},"team_distance_cumulated_14d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Team Distance Cumulated 14D"},"avg_minutes_starters_7d":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Minutes Starters 7D"},"key_player_fatigue_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Key Player Fatigue Score"},"n_key_players_used":{"type":"integer","title":"N Key Players Used"},"top_5_fatigued":{"items":{"$ref":"#/components/schemas/KeyPlayerOut"},"type":"array","title":"Top 5 Fatigued"}},"type":"object","required":["team_id","team_name","matched_external_team","matches_last_7d","matches_last_14d","team_distance_cumulated_7d","team_distance_cumulated_14d","avg_minutes_starters_7d","key_player_fatigue_score","n_key_players_used","top_5_fatigued"],"title":"TeamFatigueOut"},"TeamInline":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"canonical_name":{"type":"string","title":"Canonical Name"},"display_name":{"type":"string","title":"Display Name"},"short_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Short Name"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"}},"type":"object","required":["id","canonical_name","display_name"],"title":"TeamInline"},"TeamMappingOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"team_id":{"type":"string","format":"uuid","title":"Team Id"},"team_name":{"type":"string","title":"Team Name"},"provider":{"type":"string","title":"Provider"},"external_team_name":{"type":"string","title":"External Team Name"},"match_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Match Confidence"},"validated":{"type":"boolean","title":"Validated"}},"type":"object","required":["id","team_id","team_name","provider","external_team_name","match_confidence","validated"],"title":"TeamMappingOut"},"TeamMappingSuggestion":{"properties":{"team_id":{"type":"string","format":"uuid","title":"Team Id"},"team_name":{"type":"string","title":"Team Name"},"suggested_external":{"type":"string","title":"Suggested External"},"confidence":{"type":"number","title":"Confidence"},"provider":{"type":"string","title":"Provider","default":"statsbomb"}},"type":"object","required":["team_id","team_name","suggested_external","confidence"],"title":"TeamMappingSuggestion"},"TelegramConfigIn":{"properties":{"bot_token":{"type":"string","maxLength":200,"minLength":20,"title":"Bot Token"}},"type":"object","required":["bot_token"],"title":"TelegramConfigIn"},"TelegramConfigStatus":{"properties":{"configured":{"type":"boolean","title":"Configured"},"bot_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Username"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["configured"],"title":"TelegramConfigStatus"},"TelegramLinkCodeResponse":{"properties":{"code":{"type":"string","title":"Code"},"bot_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Username"},"instructions":{"type":"string","title":"Instructions","default":"Envoyez « /link <code> » à notre bot Telegram pour lier votre compte."}},"type":"object","required":["code"],"title":"TelegramLinkCodeResponse","description":"Réponse de POST /me/notification-prefs/telegram/link-code."},"ThemeSettingsRead":{"properties":{"light_tokens":{"additionalProperties":{"type":"string"},"type":"object","title":"Light Tokens"},"dark_tokens":{"additionalProperties":{"type":"string"},"type":"object","title":"Dark Tokens"},"color_blind_mode":{"type":"boolean","title":"Color Blind Mode"},"density":{"type":"string","title":"Density"},"font_scale":{"type":"string","title":"Font Scale"}},"type":"object","required":["light_tokens","dark_tokens","color_blind_mode","density","font_scale"],"title":"ThemeSettingsRead"},"ThemeSettingsUpdate":{"properties":{"light_tokens":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Light Tokens"},"dark_tokens":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Dark Tokens"},"color_blind_mode":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Color Blind Mode"},"density":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Density"},"font_scale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Font Scale"}},"type":"object","title":"ThemeSettingsUpdate","description":"PUT partiel — seuls les champs fournis sont mis à jour."},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["access_token","refresh_token","expires_in"],"title":"TokenResponse","description":"Réponse contenant les tokens d'accès."},"TopEvItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"event_kickoff":{"type":"string","format":"date-time","title":"Event Kickoff"},"home_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Home Team"},"away_team":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Away Team"},"league":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"League"},"sport":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sport"},"player_name":{"type":"string","title":"Player Name"},"prop_kind":{"type":"string","title":"Prop Kind"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"fair_prob":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Fair Prob"},"fair_odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Fair Odd"},"best_bookie_odd":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Best Bookie Odd"},"best_bookie_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Best Bookie Slug"},"ev":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Ev"}},"type":"object","required":["id","event_id","event_kickoff","home_team","away_team","league","sport","player_name","prop_kind","line","fair_prob","fair_odd","best_bookie_odd","best_bookie_slug","ev"],"title":"TopEvItem","description":"Une ligne du top-EV listing — enrichie avec contexte event."},"TopEvResponse":{"properties":{"count":{"type":"integer","title":"Count"},"filters_applied":{"additionalProperties":true,"type":"object","title":"Filters Applied"},"items":{"items":{"$ref":"#/components/schemas/TopEvItem"},"type":"array","title":"Items"},"distinct_sports":{"items":{"type":"string"},"type":"array","title":"Distinct Sports"},"distinct_prop_kinds":{"items":{"type":"string"},"type":"array","title":"Distinct Prop Kinds"}},"type":"object","required":["count","filters_applied","items","distinct_sports","distinct_prop_kinds"],"title":"TopEvResponse"},"TopPlayerRow":{"properties":{"canonical_name":{"type":"string","title":"Canonical Name"},"team_name":{"type":"string","title":"Team Name"},"position":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Position"},"n_matches":{"type":"integer","title":"N Matches"},"total_minutes":{"type":"integer","title":"Total Minutes"},"total_distance_km":{"type":"number","title":"Total Distance Km"},"avg_intensity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Intensity"}},"type":"object","required":["canonical_name","team_name","position","n_matches","total_minutes","total_distance_km","avg_intensity"],"title":"TopPlayerRow"},"TrackedPositionCreate":{"properties":{"bet_id":{"type":"string","format":"uuid","title":"Bet Id"},"min_profit_pct":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Min Profit Pct","default":"0.01"},"allowed_hedge_bookies":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Hedge Bookies"},"notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Notes"}},"type":"object","required":["bet_id"],"title":"TrackedPositionCreate"},"TrackedPositionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"bet_id":{"type":"string","format":"uuid","title":"Bet Id"},"min_profit_pct":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Min Profit Pct"},"status":{"$ref":"#/components/schemas/TrackedPositionStatus"},"last_notified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Notified At"},"last_notified_profit_pct":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Last Notified Profit Pct"},"allowed_hedge_bookies":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Hedge Bookies"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","bet_id","min_profit_pct","status","created_at","updated_at"],"title":"TrackedPositionRead"},"TrackedPositionStatus":{"type":"string","enum":["active","hedged","expired","cancelled"],"title":"TrackedPositionStatus","description":"Statut d'une position trackée."},"TrackedPositionUpdate":{"properties":{"min_profit_pct":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Min Profit Pct"},"allowed_hedge_bookies":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Hedge Bookies"},"notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Notes"},"status":{"anyOf":[{"$ref":"#/components/schemas/TrackedPositionStatus"},{"type":"null"}]}},"type":"object","title":"TrackedPositionUpdate"},"TrackedPositionsListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"items":{"items":{"$ref":"#/components/schemas/TrackedPositionRead"},"type":"array","title":"Items"}},"type":"object","required":["count","items"],"title":"TrackedPositionsListResponse"},"TwoFactorPolicyOut":{"properties":{"required_for_admin":{"type":"boolean","title":"Required For Admin"},"grace_period_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Grace Period Until"},"enforcement_active_now":{"type":"boolean","title":"Enforcement Active Now"},"n_admins_total":{"type":"integer","title":"N Admins Total"},"n_admins_with_2fa":{"type":"integer","title":"N Admins With 2Fa"},"n_admins_without_2fa":{"type":"integer","title":"N Admins Without 2Fa"},"safe_to_activate":{"type":"boolean","title":"Safe To Activate"},"warning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Warning"}},"type":"object","required":["required_for_admin","grace_period_until","enforcement_active_now","n_admins_total","n_admins_with_2fa","n_admins_without_2fa","safe_to_activate","warning"],"title":"TwoFactorPolicyOut"},"TwoFactorPolicyUpdate":{"properties":{"required_for_admin":{"type":"boolean","title":"Required For Admin"},"grace_period_hours":{"type":"integer","title":"Grace Period Hours","default":24}},"type":"object","required":["required_for_admin"],"title":"TwoFactorPolicyUpdate"},"UpsertMappingBody":{"properties":{"team_id":{"type":"string","format":"uuid","title":"Team Id"},"provider":{"type":"string","title":"Provider"},"external_team_name":{"type":"string","title":"External Team Name"}},"type":"object","required":["team_id","provider","external_team_name"],"title":"UpsertMappingBody"},"UserDataSourcePrefCreate":{"properties":{"source_slug":{"type":"string","maxLength":50,"minLength":1,"title":"Source Slug"},"category":{"$ref":"#/components/schemas/DataSourceCategory"},"enabled":{"type":"boolean","title":"Enabled","default":true},"priority":{"type":"integer","maximum":999.0,"minimum":1.0,"title":"Priority","default":100},"credentials":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Credentials"},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"}},"type":"object","required":["source_slug","category"],"title":"UserDataSourcePrefCreate"},"UserDataSourcePrefRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"source_slug":{"type":"string","title":"Source Slug"},"category":{"$ref":"#/components/schemas/DataSourceCategory"},"enabled":{"type":"boolean","title":"Enabled"},"priority":{"type":"integer","title":"Priority"},"has_credentials":{"type":"boolean","title":"Has Credentials","default":false},"legal_disclaimer_accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Legal Disclaimer Accepted At"},"legal_disclaimer_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Legal Disclaimer Version"},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","source_slug","category","enabled","priority","legal_disclaimer_accepted_at","legal_disclaimer_version","config","last_used_at","created_at","updated_at"],"title":"UserDataSourcePrefRead"},"UserDataSourcePrefUpdate":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"priority":{"anyOf":[{"type":"integer","maximum":999.0,"minimum":1.0},{"type":"null"}],"title":"Priority"},"credentials":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Credentials"},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"}},"type":"object","title":"UserDataSourcePrefUpdate"},"UserDataSourcePrefsListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/UserDataSourcePrefRead"},"type":"array","title":"Items"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["items","count"],"title":"UserDataSourcePrefsListResponse"},"UserProfilePublicRead":{"properties":{"handle":{"type":"string","title":"Handle"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"followers_count":{"type":"integer","title":"Followers Count"},"following_count":{"type":"integer","title":"Following Count"}},"type":"object","required":["handle","display_name","bio","avatar_url","followers_count","following_count"],"title":"UserProfilePublicRead","description":"Vue publique d'un profil (subset selon prefs)."},"UserProfileRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"handle":{"type":"string","title":"Handle"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"is_public":{"type":"boolean","title":"Is Public"},"show_roi":{"type":"boolean","title":"Show Roi"},"show_winning_bets":{"type":"boolean","title":"Show Winning Bets"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","handle","display_name","bio","avatar_url","is_public","show_roi","show_winning_bets","created_at","updated_at"],"title":"UserProfileRead"},"UserProfileUpsert":{"properties":{"handle":{"type":"string","maxLength":32,"minLength":2,"title":"Handle"},"display_name":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Display Name"},"bio":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Bio"},"avatar_url":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Avatar Url"},"is_public":{"type":"boolean","title":"Is Public","default":false},"show_roi":{"type":"boolean","title":"Show Roi","default":false},"show_winning_bets":{"type":"boolean","title":"Show Winning Bets","default":false}},"type":"object","required":["handle"],"title":"UserProfileUpsert"},"UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","format":"email","title":"Email"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"role":{"$ref":"#/components/schemas/UserRole"},"status":{"$ref":"#/components/schemas/UserStatus"},"email_verified":{"type":"boolean","title":"Email Verified"},"totp_enabled":{"type":"boolean","title":"Totp Enabled"},"locale":{"type":"string","title":"Locale"},"timezone":{"type":"string","title":"Timezone"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"}},"type":"object","required":["id","email","username","role","status","email_verified","totp_enabled","locale","timezone","created_at","last_login_at"],"title":"UserResponse","description":"Représentation publique d'un utilisateur (whitelist stricte)."},"UserRole":{"type":"string","enum":["lite","user","pro","admin"],"title":"UserRole","description":"Rôles utilisateur (cf. securite_audit_360.md §11.1)."},"UserStatsResponse":{"properties":{"n_total":{"type":"integer","title":"N Total"},"n_won":{"type":"integer","title":"N Won"},"n_lost":{"type":"integer","title":"N Lost"},"n_void":{"type":"integer","title":"N Void"},"n_pending":{"type":"integer","title":"N Pending"},"total_staked":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Staked"},"total_pnl":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Pnl"},"roi":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Roi"},"clv_mean":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Clv Mean"},"clv_sample_size":{"type":"integer","title":"Clv Sample Size"},"max_drawdown":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Max Drawdown"},"longest_winning_streak":{"type":"integer","title":"Longest Winning Streak"},"longest_losing_streak":{"type":"integer","title":"Longest Losing Streak"}},"type":"object","required":["n_total","n_won","n_lost","n_void","n_pending","total_staked","total_pnl","roi","clv_sample_size","max_drawdown","longest_winning_streak","longest_losing_streak"],"title":"UserStatsResponse","description":"KPIs dashboard (cf. UX §17.2-A)."},"UserStatus":{"type":"string","enum":["active","pending_email","suspended","deleted"],"title":"UserStatus","description":"Statut compte utilisateur."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"ValueBetEventInfo":{"properties":{"kickoff":{"type":"string","format":"date-time","title":"Kickoff"},"home_team_name":{"type":"string","title":"Home Team Name"},"away_team_name":{"type":"string","title":"Away Team Name"},"league_name":{"type":"string","title":"League Name"},"league_slug":{"type":"string","title":"League Slug"}},"type":"object","required":["kickoff","home_team_name","away_team_name","league_name","league_slug"],"title":"ValueBetEventInfo","description":"Infos d'event jointes pour les cartes UI (Hot Sheet).\n\nÉvite le N+1 ; remplit kickoff + noms équipes/ligue, pas plus."},"ValueBetItem":{"properties":{"outcome_id":{"type":"string","title":"Outcome Id"},"value_bet_id":{"type":"string","title":"Value Bet Id"},"event_id":{"type":"string","title":"Event Id"},"opened_at":{"type":"string","format":"date-time","title":"Opened At"},"settled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Settled At"},"sport_code":{"type":"string","title":"Sport Code"},"league_slug":{"type":"string","title":"League Slug"},"league_name":{"type":"string","title":"League Name"},"home_team":{"type":"string","title":"Home Team"},"away_team":{"type":"string","title":"Away Team"},"kickoff":{"type":"string","format":"date-time","title":"Kickoff"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Line"},"bookie_slug":{"type":"string","title":"Bookie Slug"},"model_type":{"type":"string","title":"Model Type"},"opened_odd":{"type":"number","title":"Opened Odd"},"closing_odd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Closing Odd"},"clv_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Clv Pct"},"ev_pct":{"type":"number","title":"Ev Pct"},"probability_model":{"type":"number","title":"Probability Model","description":"Proba predite par le modele (0-1)"},"probability_devig":{"type":"number","title":"Probability Devig","description":"Proba implicite devigee par le bookie (0-1)"},"kelly_fraction":{"type":"number","title":"Kelly Fraction"},"bet_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bet Result"},"stake_units":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Stake Units"},"pnl_units":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pnl Units"},"home_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Home Score"},"away_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Away Score"}},"type":"object","required":["outcome_id","value_bet_id","event_id","opened_at","settled_at","sport_code","league_slug","league_name","home_team","away_team","kickoff","market_code","outcome","line","bookie_slug","model_type","opened_odd","closing_odd","clv_pct","ev_pct","probability_model","probability_devig","kelly_fraction","bet_result","stake_units","pnl_units","home_score","away_score"],"title":"ValueBetItem","description":"Une ligne settled pour la table BI."},"ValueBetRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"sport_code":{"type":"string","title":"Sport Code"},"market_code":{"type":"string","title":"Market Code"},"outcome":{"type":"string","title":"Outcome"},"line":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Line"},"bookie_slug":{"type":"string","title":"Bookie Slug"},"model_type":{"type":"string","title":"Model Type"},"model_version":{"type":"string","title":"Model Version"},"probability_model":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Probability Model"},"probability_devig":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Probability Devig"},"odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Odd"},"ev":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Ev"},"edge_prob":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Edge Prob"},"book_vig":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Book Vig"},"kelly_fraction":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Kelly Fraction"},"detected_at":{"type":"string","format":"date-time","title":"Detected At"},"is_live":{"type":"boolean","title":"Is Live"},"invalidated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Invalidated At"},"invalidation_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invalidation Reason"},"event":{"anyOf":[{"$ref":"#/components/schemas/ValueBetEventInfo"},{"type":"null"}]},"access":{"anyOf":[{"$ref":"#/components/schemas/BookieAccessInfo"},{"type":"null"}]}},"type":"object","required":["id","event_id","sport_code","market_code","outcome","bookie_slug","model_type","model_version","probability_model","probability_devig","odd","ev","edge_prob","book_vig","kelly_fraction","detected_at","is_live"],"title":"ValueBetRead","description":"Value bet renvoyée par l'API."},"ValueBetsListResponse":{"properties":{"count":{"type":"integer","title":"Count"},"items":{"items":{"$ref":"#/components/schemas/ValueBetRead"},"type":"array","title":"Items"}},"type":"object","required":["count","items"],"title":"ValueBetsListResponse","description":"Réponse listing value bets."},"WalkForwardBody":{"properties":{"config":{"$ref":"#/components/schemas/BacktestConfigBody"},"n_splits":{"type":"integer","maximum":10.0,"minimum":2.0,"title":"N Splits","default":4}},"type":"object","required":["config"],"title":"WalkForwardBody"},"WebhookCreate":{"properties":{"target_url":{"type":"string","maxLength":500,"minLength":10,"title":"Target Url"},"event_types":{"items":{"type":"string"},"type":"array","maxItems":20,"minItems":1,"title":"Event Types"}},"type":"object","required":["target_url","event_types"],"title":"WebhookCreate"},"WidgetConfig":{"properties":{"id":{"type":"string","maxLength":50,"minLength":1,"title":"Id"},"visible":{"type":"boolean","title":"Visible","default":true},"order":{"type":"integer","maximum":999.0,"minimum":0.0,"title":"Order"},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"}},"type":"object","required":["id","order"],"title":"WidgetConfig"},"src__routers__admin_security__SessionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"}},"type":"object","required":["id","user_id","user_agent","ip_address","device_name","expires_at","revoked_at","last_used_at"],"title":"SessionRead"},"src__routers__analytics__EquityPoint":{"properties":{"day":{"type":"string","format":"date","title":"Day"},"pnl_units":{"type":"number","title":"Pnl Units","description":"P&L cumulative en unites bankroll"},"n_bets":{"type":"integer","title":"N Bets"},"drawdown_pct":{"type":"number","title":"Drawdown Pct","description":"drawdown depuis le pic"}},"type":"object","required":["day","pnl_units","n_bets","drawdown_pct"],"title":"EquityPoint","description":"Un point de la courbe d'equity."},"src__routers__bankroll__EquityPoint":{"properties":{"t":{"type":"string","title":"T"},"v":{"type":"number","title":"V"}},"type":"object","required":["t","v"],"title":"EquityPoint"},"src__routers__billing__SubscriptionRead":{"properties":{"plan_tier":{"type":"string","title":"Plan Tier"},"plan_name":{"type":"string","title":"Plan Name"},"price_monthly_eur":{"type":"number","title":"Price Monthly Eur"},"status":{"type":"string","title":"Status"},"current_period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Current Period End"},"trial_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Trial End"},"has_stripe_customer":{"type":"boolean","title":"Has Stripe Customer"},"cancel_at_period_end":{"type":"boolean","title":"Cancel At Period End","default":false}},"type":"object","required":["plan_tier","plan_name","price_monthly_eur","status","current_period_end","trial_end","has_stripe_customer"],"title":"SubscriptionRead","description":"Vue de la souscription courante du user (via son tenant)."},"src__routers__builder__ComboAnalyzeRequest":{"properties":{"legs":{"items":{"$ref":"#/components/schemas/Leg"},"type":"array","title":"Legs"}},"type":"object","required":["legs"],"title":"ComboAnalyzeRequest"},"src__routers__builder__ComboAnalyzeResponse":{"properties":{"n_legs":{"type":"integer","title":"N Legs"},"combined_odd":{"type":"number","title":"Combined Odd"},"combined_prob_independent":{"type":"number","title":"Combined Prob Independent"},"combined_ev_estimate":{"type":"number","title":"Combined Ev Estimate"},"correlation":{"additionalProperties":true,"type":"object","title":"Correlation"}},"type":"object","required":["n_legs","combined_odd","combined_prob_independent","combined_ev_estimate","correlation"],"title":"ComboAnalyzeResponse"},"src__routers__combo__ComboAnalyzeRequest":{"properties":{"legs":{"items":{"$ref":"#/components/schemas/ComboLegRequest"},"type":"array","maxItems":10,"minItems":1,"title":"Legs"},"bankroll":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Bankroll"},"kelly_fraction":{"type":"number","maximum":1.0,"exclusiveMinimum":0.0,"title":"Kelly Fraction","default":0.5}},"type":"object","required":["legs"],"title":"ComboAnalyzeRequest"},"src__routers__combo__ComboAnalyzeResponse":{"properties":{"legs":{"items":{"$ref":"#/components/schemas/ComboLegRead"},"type":"array","title":"Legs"},"combined_odd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Combined Odd"},"combined_probability":{"type":"number","title":"Combined Probability"},"expected_value":{"type":"number","title":"Expected Value"},"expected_value_pct":{"type":"number","title":"Expected Value Pct"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"},"kelly_stake":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Kelly Stake"}},"type":"object","required":["legs","combined_odd","combined_probability","expected_value","expected_value_pct","warnings","kelly_stake"],"title":"ComboAnalyzeResponse"},"src__routers__marketplace__SubscriptionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"subscriber_id":{"type":"string","format":"uuid","title":"Subscriber Id"},"strategy_id":{"type":"string","format":"uuid","title":"Strategy Id"},"status":{"type":"string","title":"Status"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"next_billing_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Billing At"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Canceled At"},"commission_pct":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Commission Pct"}},"type":"object","required":["id","subscriber_id","strategy_id","status","started_at","next_billing_at","canceled_at","commission_pct"],"title":"SubscriptionRead"},"src__routers__me_account__SessionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"is_current":{"type":"boolean","title":"Is Current","default":false}},"type":"object","required":["id","user_agent","ip_address","device_name","expires_at","revoked_at","last_used_at","created_at"],"title":"SessionRead","description":"Vue safe (pas de refresh_token_hash) d'une session."}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"/auth/login"}}}}}}