{"openapi":"3.1.0","info":{"title":"ParsiTrade Scanner API","description":"Signal logging • Performance analytics • Backtesting • ML-driven self-improvement. Interactive docs use the same Dark/Gold theme as the dashboard.","version":"0.2.0"},"paths":{"/signals/":{"get":{"tags":["Signals"],"summary":"List Signals","operationId":"list_signals_signals__get","parameters":[{"name":"symbol","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Symbol"}},{"name":"session","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session"}},{"name":"node_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Type"}},{"name":"outcome","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome"}},{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/signals/pending":{"get":{"tags":["Signals"],"summary":"List Pending","operationId":"list_pending_signals_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/signals/complete":{"get":{"tags":["Signals"],"summary":"List Complete","operationId":"list_complete_signals_complete_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/signals/{signal_id}":{"get":{"tags":["Signals"],"summary":"Get Signal","operationId":"get_signal_signals__signal_id__get","parameters":[{"name":"signal_id","in":"path","required":true,"schema":{"type":"string","title":"Signal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stats/summary":{"get":{"tags":["Stats"],"summary":"Get Summary","description":"Dashboard summary. During scan, returns last-good cache instead of blocking DuckDB.","operationId":"get_summary_stats_summary_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":3650,"minimum":1},{"type":"null"}],"description":"Limit to last N days","title":"Days"},"description":"Limit to last N days"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stats/breakdown/{dimension}":{"get":{"tags":["Stats"],"summary":"Get Breakdown","operationId":"get_breakdown_stats_breakdown__dimension__get","parameters":[{"name":"dimension","in":"path","required":true,"schema":{"type":"string","title":"Dimension"}},{"name":"days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":3650,"minimum":1},{"type":"null"}],"description":"Limit to last N days","title":"Days"},"description":"Limit to last N days"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/backtest/run":{"post":{"tags":["Backtest"],"summary":"Run Backtest","description":"Run backtest on all complete signals (admin only).","operationId":"run_backtest_backtest_run_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"max_bars","in":"query","required":false,"schema":{"type":"integer","default":300,"title":"Max Bars"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/backtest/generate":{"post":{"tags":["Backtest"],"summary":"Generate Signals","description":"Detect signals from historical OHLCV and simulate their outcomes.\nOptionally store generated rows into the signal store (store_results=true).","operationId":"generate_signals_backtest_generate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"symbol","in":"query","required":false,"schema":{"type":"string","default":"EURUSD","title":"Symbol"}},{"name":"start","in":"query","required":false,"schema":{"type":"string","default":"2024-01-01","title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"type":"string","default":"2024-06-01","title":"End"}},{"name":"structure_tf","in":"query","required":false,"schema":{"type":"string","default":"H1","title":"Structure Tf"}},{"name":"trigger_tf","in":"query","required":false,"schema":{"type":"string","default":"M5","title":"Trigger Tf"}},{"name":"sl_atr_mult","in":"query","required":false,"schema":{"type":"number","default":1.5,"title":"Sl Atr Mult"}},{"name":"tp_atr_mult","in":"query","required":false,"schema":{"type":"number","default":2.0,"title":"Tp Atr Mult"}},{"name":"store_results","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Store Results"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/backtest/signal/{signal_id}":{"get":{"tags":["Backtest"],"summary":"Backtest Signal","description":"Run backtest for a single signal.","operationId":"backtest_signal_backtest_signal__signal_id__get","parameters":[{"name":"signal_id","in":"path","required":true,"schema":{"type":"string","title":"Signal Id"}},{"name":"max_bars","in":"query","required":false,"schema":{"type":"integer","default":300,"title":"Max Bars"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ml/train":{"post":{"tags":["ML"],"summary":"Trigger Training","description":"Manually trigger a training run (admin only).","operationId":"trigger_training_ml_train_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/ml/model/status":{"get":{"tags":["ML"],"summary":"Model Status","description":"Check if a trained model exists.","operationId":"model_status_ml_model_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ml/explain/global":{"get":{"tags":["ML"],"summary":"Global Explanation","description":"Return SHAP global feature importance.","operationId":"global_explanation_ml_explain_global_get","parameters":[{"name":"top_n","in":"query","required":false,"schema":{"type":"integer","default":15,"title":"Top N"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ml/optimize":{"post":{"tags":["ML"],"summary":"Run Optimization","description":"Run the full optimization cycle (admin only).","operationId":"run_optimization_ml_optimize_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/ml/feedback":{"get":{"tags":["ML"],"summary":"Get Feedback","description":"Return the current feedback parameters written to the EA.","operationId":"get_feedback_ml_feedback_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sync/status":{"get":{"tags":["Sync"],"summary":"Supabase Status","description":"Check whether Supabase is configured and reachable.","operationId":"supabase_status_sync_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sync/supabase":{"post":{"tags":["Sync"],"summary":"Sync Supabase","description":"Push all local DuckDB signal rows to Supabase. Idempotent.","operationId":"sync_supabase_sync_supabase_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/ai/status":{"get":{"tags":["AI"],"summary":"Ai Status","description":"Return which AI provider (if any) is configured.","operationId":"ai_status_ai_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ai/market-brief":{"get":{"tags":["AI"],"summary":"Market Brief Cached","description":"Serve the cached 5-minute market brief. This endpoint never calls the AI\nprovider and never writes — a scheduler job does the generating.\n\nHonest status values, no invented content:\n  ok          — cached text available\n  pending     — job has not produced a brief yet (or no scanner data)\n  unavailable — no AI provider configured on the server\n  error       — the last generation attempt failed (last_error explains)","operationId":"market_brief_cached_ai_market_brief_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ai/hourly":{"get":{"tags":["AI"],"summary":"Hourly Cached","description":"Serve the cached hourly AI digest (24h news summary + data-backed\nwatchlist). This endpoint never calls the AI provider and never\nwrites — an hourly scheduler job does the generating.\n\nHonest status values, no invented content:\n  ok          — cached text available\n  stale       — last generation failed; previous good text kept\n  pending     — job has not produced a digest yet (or no data)\n  unavailable — no AI provider configured on the server\n  error       — the last generation attempt failed (last_error explains)","operationId":"hourly_cached_ai_hourly_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/ai/explain-signal":{"post":{"tags":["AI"],"summary":"Explain Signal","description":"Explain why a specific signal succeeded or failed (AI narrative).","operationId":"explain_signal_ai_explain_signal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalExplainRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ai/market-summary":{"post":{"tags":["AI"],"summary":"Market Summary","description":"Ask the AI for a brief educational market context for the symbols in the DB.\nOptional provider=... tried first, then failover.","operationId":"market_summary_ai_market_summary_post","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","pattern":"^(fa|en|ar)$","default":"fa","title":"Lang"}},{"name":"provider","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/scanner/status":{"get":{"tags":["Scanner"],"summary":"Scanner Status","description":"Return scanner state, active symbols, and ccxt exchange name.","operationId":"scanner_status_scanner_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/scanner/feeds":{"get":{"tags":["Scanner"],"summary":"Scanner Feeds","description":"Public catalog of market-data feeds for the signal-card dropdown.\nNo API keys or auth_fields. Reliability is historical WIN/LOSS, not a gate.","operationId":"scanner_feeds_scanner_feeds_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/scanner/run":{"post":{"tags":["Scanner"],"summary":"Scanner Run","description":"Trigger an immediate scan in the background (admin only).\n\nOptionally pass a JSON body: {\"symbols\": [\"BTC/USDT\", \"ETH/USDT\"]}\nPoll GET /scanner/status for last_scan_at / last_error progress.","operationId":"scanner_run_scanner_run_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/_ScanRunBody"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/scanner/signals":{"get":{"tags":["Scanner"],"summary":"Scanner Signals","description":"Open scanner signals enriched with:\n  leverage, position_coins, position_usdt, margin_usdt, profit_usdt,\n  risk_usdt, sl_pct, tp_pct, direction, age_minutes.\n\naccount_usdt and risk_pct are used for position sizing — pass them as\nquery params from the UI settings.","operationId":"scanner_signals_scanner_signals_get","parameters":[{"name":"account_usdt","in":"query","required":false,"schema":{"type":"number","maximum":10000000,"exclusiveMinimum":0,"description":"حساب معاملاتی به USDT","default":1000.0,"title":"Account Usdt"},"description":"حساب معاملاتی به USDT"},{"name":"risk_pct","in":"query","required":false,"schema":{"type":"number","maximum":100,"exclusiveMinimum":0,"description":"درصد ریسک هر معامله از کل حساب","default":0.5,"title":"Risk Pct"},"description":"درصد ریسک هر معامله از کل حساب"},{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/scanner/signals/history":{"get":{"tags":["Scanner"],"summary":"Scanner Signals History","description":"Closed scanner signals (outcome IS NOT NULL) — newest first.\nReturns the same shape as /signals but includes outcome, exit_price, pnl_atr.","operationId":"scanner_signals_history_scanner_signals_history_get","parameters":[{"name":"account_usdt","in":"query","required":false,"schema":{"type":"number","maximum":10000000,"exclusiveMinimum":0,"default":1000.0,"title":"Account Usdt"}},{"name":"risk_pct","in":"query","required":false,"schema":{"type":"number","maximum":100,"exclusiveMinimum":0,"default":0.5,"title":"Risk Pct"}},{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/scanner/candles":{"get":{"tags":["Scanner"],"summary":"Get Candles","description":"Return the last N stored candles for a symbol/timeframe pair.","operationId":"get_candles_scanner_candles_get","parameters":[{"name":"symbol","in":"query","required":true,"schema":{"type":"string","description":"e.g. BTC/USDT","title":"Symbol"},"description":"e.g. BTC/USDT"},{"name":"timeframe","in":"query","required":false,"schema":{"type":"string","description":"4h | 1h | 15m","default":"4h","title":"Timeframe"},"description":"4h | 1h | 15m"},{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/backfill":{"post":{"tags":["Admin"],"summary":"Start Backfill","description":"Start historical backfill in a background thread.\nFetches OHLCV from MEXC, runs detect_setups, simulates outcomes, saves to DB.\n\nReturns immediately — poll /admin/backfill/status for progress.\nOnly one backfill can run at a time.","operationId":"start_backfill_admin_panel_backfill_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"years","in":"query","required":false,"schema":{"type":"integer","maximum":5,"minimum":1,"description":"Years of history to fetch","default":2,"title":"Years"},"description":"Years of history to fetch"},{"name":"symbols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated symbols, blank = all","title":"Symbols"},"description":"Comma-separated symbols, blank = all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/backfill/status":{"get":{"tags":["Admin"],"summary":"Backfill Status","description":"Return current backfill progress.","operationId":"backfill_status_admin_panel_backfill_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/backfill/cancel":{"post":{"tags":["Admin"],"summary":"Cancel Backfill","description":"Signal the running backfill to stop after the current symbol.","operationId":"cancel_backfill_admin_panel_backfill_cancel_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/signals/stats":{"get":{"tags":["Admin"],"summary":"Signal Stats","description":"Row counts and outcome breakdown for each source.","operationId":"signal_stats_admin_panel_signals_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/signals/delete":{"post":{"tags":["Admin"],"summary":"Delete Signals","description":"Bulk-delete signals matching all provided filters.\nRequires confirm=yes to prevent accidental deletion.","operationId":"delete_signals_admin_panel_signals_delete_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by source (e.g. 'backtest')","title":"Source"},"description":"Filter by source (e.g. 'backtest')"},{"name":"symbol","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by symbol (e.g. 'BTC/USDT')","title":"Symbol"},"description":"Filter by symbol (e.g. 'BTC/USDT')"},{"name":"outcome","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by outcome (WIN/LOSS/FAILURE/OPEN)","title":"Outcome"},"description":"Filter by outcome (WIN/LOSS/FAILURE/OPEN)"},{"name":"confirm","in":"query","required":true,"schema":{"type":"string","description":"Must be 'yes' to execute deletion","title":"Confirm"},"description":"Must be 'yes' to execute deletion"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/scanner/reset":{"post":{"tags":["Admin"],"summary":"Reset Scanner","description":"Reset scanner state (clears last_scan_at and error) so next run starts fresh.","operationId":"reset_scanner_admin_panel_scanner_reset_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/scan/trigger":{"post":{"tags":["Admin"],"summary":"Trigger Scan","description":"Start a full crypto scan in the background; returns immediately (202/409).","operationId":"trigger_scan_admin_panel_scan_trigger_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/ml/train":{"post":{"tags":["Admin"],"summary":"Trigger Training","description":"Trigger model training immediately (runs synchronously, may take 10–60 s).","operationId":"trigger_training_admin_panel_ml_train_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/ml/readiness":{"get":{"tags":["Admin"],"summary":"Ml Readiness","description":"Report whether labelled scanner data is ready for HGBC training.\nOptionally consult the configured AI provider for a short admin-facing note.\nData is collected by source/outcome breakdown; training is never auto-started.","operationId":"ml_readiness_admin_panel_ml_readiness_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"consult_ai","in":"query","required":false,"schema":{"type":"boolean","description":"Ask AI for a short training recommendation","default":false,"title":"Consult Ai"},"description":"Ask AI for a short training recommendation"},{"name":"lang","in":"query","required":false,"schema":{"type":"string","pattern":"^(fa|en|ar)$","default":"fa","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/db/stats":{"get":{"tags":["Admin"],"summary":"Db Stats","description":"Return row counts for all tables in DuckDB.","operationId":"db_stats_admin_panel_db_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/db/vacuum":{"post":{"tags":["Admin"],"summary":"Db Vacuum","description":"Reclaim DuckDB storage after bulk deletes.","operationId":"db_vacuum_admin_panel_db_vacuum_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/ml/status":{"get":{"tags":["Admin"],"summary":"Ml Status","description":"Return metadata for the currently saved ML model (without retraining).","operationId":"ml_status_admin_panel_ml_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/news/suppress":{"get":{"tags":["Admin"],"summary":"Get News Suppress","description":"Return current news-suppress state (True = signals for breaking-news symbols are hidden).","operationId":"get_news_suppress_admin_panel_news_suppress_get","security":[{"HTTPBearer":[]}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Admin"],"summary":"Set News Suppress","description":"Toggle news suppression.  active=true → filter scanner signals for breaking-news symbols.","operationId":"set_news_suppress_admin_panel_news_suppress_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"active","in":"query","required":true,"schema":{"type":"boolean","title":"Active"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/telegram/test":{"post":{"tags":["Admin"],"summary":"Telegram Test","description":"Send a test Telegram message to verify bot token and chat ID are working.","operationId":"telegram_test_admin_panel_telegram_test_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/outcomes/recheck":{"post":{"tags":["Admin"],"summary":"Recheck Outcomes","description":"Force outcome_tracker for open scanner signals.\n\nDefault background=true returns immediately (202-style payload) so a backlog\nof thousands of open rows cannot hold the HTTP worker for many minutes.\nPass background=false for a synchronous summary (tests / small DBs).","operationId":"recheck_outcomes_admin_panel_outcomes_recheck_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"background","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Background"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/outcomes/backfill-failure-reasons":{"post":{"tags":["Admin"],"summary":"Backfill Failure Reasons","description":"One-shot label for historical FAILURE rows missing failure_reason.\nDoes not re-walk bars; uses age / bars_to_resolution heuristics.","operationId":"backfill_failure_reasons_admin_panel_outcomes_backfill_failure_reasons_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/ops/effectiveness":{"get":{"tags":["Admin"],"summary":"Ops Effectiveness","description":"Read-only E2/E3/E4 ops snapshot for the effectiveness backlog.\n\nUses point-in-time SQL on the live DB (no param changes).","operationId":"ops_effectiveness_admin_panel_ops_effectiveness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/scores/backfill":{"post":{"tags":["Admin"],"summary":"Backfill Scores","description":"Compute V2 structural scores for historical signals.\n\nDefault: only rows with structural_score IS NULL are touched.\nforce=true: re-scores ALL signals (use when scoring parameters change, e.g. _TIER_WR update).\nFor ~2,000 signals this completes in < 10 seconds.","operationId":"backfill_scores_admin_panel_scores_backfill_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/scores/status":{"get":{"tags":["Admin"],"summary":"Scores Status","description":"Return scoring coverage — how many signals have/lack V2 structural scores.","operationId":"scores_status_admin_panel_scores_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/optimizer/status":{"get":{"tags":["Admin"],"summary":"Optimizer Status","description":"Return current strategy parameters and last optimizer run summary.","operationId":"optimizer_status_admin_panel_optimizer_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/optimizer/proposals":{"get":{"tags":["Admin"],"summary":"Optimizer Proposals","description":"List optimizer proposals.\n?status=pending | validated | validation_failed | approved | rejected | all","operationId":"optimizer_proposals_admin_panel_optimizer_proposals_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/optimizer/validate/{proposal_id}":{"post":{"tags":["Admin"],"summary":"Validate Optimizer Proposal","description":"Run historical validation on a proposal (AI → history gate).\nDoes not apply production params. Approve only works after status=validated.","operationId":"validate_optimizer_proposal_admin_panel_optimizer_validate__proposal_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","title":"Proposal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/optimizer/approve/{proposal_id}":{"post":{"tags":["Admin"],"summary":"Approve Proposal","description":"Approve a validated proposal — applies parameter changes immediately.","operationId":"approve_proposal_admin_panel_optimizer_approve__proposal_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","title":"Proposal Id"}},{"name":"note","in":"query","required":false,"schema":{"type":"string","default":"","title":"Note"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/optimizer/reject/{proposal_id}":{"post":{"tags":["Admin"],"summary":"Reject Proposal","description":"Reject a pending proposal without applying changes.","operationId":"reject_proposal_admin_panel_optimizer_reject__proposal_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","title":"Proposal Id"}},{"name":"note","in":"query","required":false,"schema":{"type":"string","default":"","title":"Note"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/optimizer/run":{"post":{"tags":["Admin"],"summary":"Run Optimizer","description":"Trigger one optimization cycle immediately (runs synchronously — may take ~30s).","operationId":"run_optimizer_admin_panel_optimizer_run_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/tier-wr/status":{"get":{"tags":["Admin"],"summary":"Tier Wr Status","description":"Active (approved) calibration + pending proposals.","operationId":"tier_wr_status_admin_panel_tier_wr_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/tier-wr/proposals":{"get":{"tags":["Admin"],"summary":"Tier Wr Proposals","description":"List tier-WR calibration proposals. ?status=pending|approved|rejected|all","operationId":"tier_wr_proposals_admin_panel_tier_wr_proposals_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/tier-wr/approve/{proposal_id}":{"post":{"tags":["Admin"],"summary":"Approve Tier Wr","description":"Approve pending tier-WR calibration — writes tier_wr.json and reloads scoring.","operationId":"approve_tier_wr_admin_panel_tier_wr_approve__proposal_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","title":"Proposal Id"}},{"name":"note","in":"query","required":false,"schema":{"type":"string","default":"","title":"Note"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/tier-wr/reject/{proposal_id}":{"post":{"tags":["Admin"],"summary":"Reject Tier Wr","description":"Reject a pending tier-WR calibration proposal without applying it.","operationId":"reject_tier_wr_admin_panel_tier_wr_reject__proposal_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","title":"Proposal Id"}},{"name":"note","in":"query","required":false,"schema":{"type":"string","default":"","title":"Note"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/telegram/notify-open":{"post":{"tags":["Admin"],"summary":"Telegram Notify Open","description":"Send current open scanner signals to Telegram — including chart images.\n\nUse this when a scan runs but no new signals are found (total_signals=0\nsuppresses automatic notification).  Useful after a network outage or to\nre-send charts for signals that were stored before chart rendering worked.","operationId":"telegram_notify_open_admin_panel_telegram_notify_open_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/telegram/send-recent-outcomes":{"post":{"tags":["Admin"],"summary":"Send Recent Outcomes","description":"Fetch the last N resolved scanner signals, render outcome charts for those\nthat don't have one yet (e.g. resolved before this feature was deployed),\nand send Telegram notifications for each.\n\nUse this to demo the outcome-chart Telegram format on historical data.","operationId":"send_recent_outcomes_admin_panel_telegram_send_recent_outcomes_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":5,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/ml/backfill":{"post":{"tags":["Admin"],"summary":"Backfill Ml Scores","description":"Run ML inference on all signals that are missing ml_score and store results.\n\nUses the current saved model. Only blends into signal_score / signal_tier\nwhen holdout_auc reaches ml.trainer.ML_BLEND_MIN_AUC — otherwise it just\nstores ml_score for monitoring.\nSafe to call repeatedly.","operationId":"backfill_ml_scores_admin_panel_ml_backfill_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/params":{"get":{"tags":["Admin"],"summary":"Get Strategy Params","description":"Return all tunable strategy parameters with their current values and defaults.\n\nParameters are read from feedback/strategy_params.json (overrides) with\nfactory defaults applied for any missing keys.","operationId":"get_strategy_params_admin_panel_params_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Admin"],"summary":"Update Strategy Params","description":"Update one or more strategy parameters.\n\nRequest body: JSON object where each key is a parameter name and each\nvalue is the new setting, e.g. {\"RISK_REWARD\": 2.5, \"USE_NEWS_FILTER\": false}.\n\nChanges are persisted to feedback/strategy_params.json immediately and\ntake effect on the next scan/evaluation cycle — no server restart needed.","operationId":"update_strategy_params_admin_panel_params_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/params/reset":{"post":{"tags":["Admin"],"summary":"Reset Strategy Params","description":"Reset ALL strategy parameters to factory defaults.","operationId":"reset_strategy_params_admin_panel_params_reset_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/digest/weekly":{"post":{"tags":["Admin"],"summary":"Send Weekly Digest","description":"Weekly digest is not sent — Telegram is limited to signals, outcomes, and news.","operationId":"send_weekly_digest_admin_panel_digest_weekly_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/commerce/orders":{"get":{"tags":["Admin"],"summary":"Admin Commerce Orders","operationId":"admin_commerce_orders_admin_panel_commerce_orders_get","security":[{"HTTPBearer":[]}],"parameters":[{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/commerce/licenses":{"get":{"tags":["Admin"],"summary":"Admin Commerce Licenses","operationId":"admin_commerce_licenses_admin_panel_commerce_licenses_get","security":[{"HTTPBearer":[]}],"parameters":[{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/commerce/plans/{plan_id}/price":{"post":{"tags":["Admin"],"summary":"Admin Set Plan Price","description":"Set plan price on server (never trust client amount at checkout).","operationId":"admin_set_plan_price_admin_panel_commerce_plans__plan_id__price_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"string","title":"Plan Id"}},{"name":"price_irr","in":"query","required":true,"schema":{"type":"integer","minimum":0,"title":"Price Irr"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/commerce/storefront":{"get":{"tags":["Admin"],"summary":"Admin Get Storefront","operationId":"admin_get_storefront_admin_panel_commerce_storefront_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["Admin"],"summary":"Admin Put Storefront","description":"Update shop/landing copy fields (JSON body).","operationId":"admin_put_storefront_admin_panel_commerce_storefront_put","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/commerce/promo-video":{"post":{"tags":["Admin"],"summary":"Admin Upload Promo Video","description":"Upload promo video for landing box — stored under web/uploads/promo/.","operationId":"admin_upload_promo_video_admin_panel_commerce_promo_video_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/exchanges":{"get":{"tags":["Admin Exchanges"],"summary":"List Exchanges","operationId":"list_exchanges_admin_panel_exchanges_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Admin Exchanges"],"summary":"Create Exchange","operationId":"create_exchange_admin_panel_exchanges_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/exchanges/risk-settings":{"get":{"tags":["Admin Exchanges"],"summary":"Get Risk Settings","operationId":"get_risk_settings_admin_panel_exchanges_risk_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["Admin Exchanges"],"summary":"Put Risk Settings","operationId":"put_risk_settings_admin_panel_exchanges_risk_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskSettingsIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/exchanges/reorder":{"post":{"tags":["Admin Exchanges"],"summary":"Reorder Exchanges","operationId":"reorder_exchanges_admin_panel_exchanges_reorder_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/admin-panel/exchanges/{exchange_id}":{"put":{"tags":["Admin Exchanges"],"summary":"Update Exchange","operationId":"update_exchange_admin_panel_exchanges__exchange_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"exchange_id","in":"path","required":true,"schema":{"type":"string","title":"Exchange Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Admin Exchanges"],"summary":"Delete Exchange","description":"Soft delete — status=disabled (history preserved).","operationId":"delete_exchange_admin_panel_exchanges__exchange_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"exchange_id","in":"path","required":true,"schema":{"type":"string","title":"Exchange Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/exchanges/{exchange_id}/test-connection":{"post":{"tags":["Admin Exchanges"],"summary":"Test Exchange Connection","operationId":"test_exchange_connection_admin_panel_exchanges__exchange_id__test_connection_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"exchange_id","in":"path","required":true,"schema":{"type":"string","title":"Exchange Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/news/feed":{"get":{"tags":["News"],"summary":"News Feed","description":"Return recent crypto news articles ordered by publication time (newest first).","operationId":"news_feed_news_feed_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"symbol","in":"query","required":false,"schema":{"type":"string","description":"Base symbol filter, e.g. BTC or BTC/USDT","title":"Symbol"},"description":"Base symbol filter, e.g. BTC or BTC/USDT"},{"name":"min_impact","in":"query","required":false,"schema":{"type":"string","description":"Minimum impact: LOW / MEDIUM / HIGH / BREAKING","default":"LOW","title":"Min Impact"},"description":"Minimum impact: LOW / MEDIUM / HIGH / BREAKING"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/news/breaking":{"get":{"tags":["News"],"summary":"News Breaking","description":"Return base symbols with HIGH or BREAKING news in the last N hours.\nUsed by the frontend to display warning badges on open trade cards.","operationId":"news_breaking_news_breaking_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","maximum":48,"minimum":1,"description":"Look-back window in hours","default":6,"title":"Hours"},"description":"Look-back window in hours"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/news/stats":{"get":{"tags":["News"],"summary":"News Stats","description":"Row count and basic breakdown — useful for the admin panel.","operationId":"news_stats_news_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/commerce/status":{"get":{"tags":["Commerce"],"summary":"Commerce Status","operationId":"commerce_status_commerce_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/commerce/agreement":{"get":{"tags":["Commerce"],"summary":"Get Agreement","operationId":"get_agreement_commerce_agreement_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/commerce/plans":{"get":{"tags":["Commerce"],"summary":"List Plans","operationId":"list_plans_commerce_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/commerce/storefront":{"get":{"tags":["Commerce"],"summary":"Get Storefront","description":"Public landing/shop content controlled from admin.","operationId":"get_storefront_commerce_storefront_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/commerce/consent":{"post":{"tags":["Commerce"],"summary":"Record Consent","operationId":"record_consent_commerce_consent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/commerce/orders":{"post":{"tags":["Commerce"],"summary":"Create Order","operationId":"create_order_commerce_orders_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/commerce/zarinpal/callback":{"get":{"tags":["Commerce"],"summary":"Zarinpal Callback","description":"Browser return from Zarinpal. Idempotent license issuance on OK.","operationId":"zarinpal_callback_commerce_zarinpal_callback_get","parameters":[{"name":"Authority","in":"query","required":false,"schema":{"type":"string","default":"","title":"Authority"}},{"name":"Status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/commerce/license/verify":{"post":{"tags":["Commerce"],"summary":"License Verify","operationId":"license_verify_commerce_license_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseVerifyBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/commerce/licenses/lookup":{"post":{"tags":["Commerce"],"summary":"Licenses Lookup","description":"Return issued licenses for exact user_ref (no cross-user leak).","operationId":"licenses_lookup_commerce_licenses_lookup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseLookupBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/config":{"get":{"tags":["Auth","auth"],"summary":"Auth Config","description":"Feature flags for the shared login modal + CSRF cookie handshake.","operationId":"auth_config_auth_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/signup":{"post":{"tags":["Auth","auth"],"summary":"Auth Signup","operationId":"auth_signup_auth_signup_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/password/forgot":{"post":{"tags":["Auth","auth"],"summary":"Auth Forgot","operationId":"auth_forgot_auth_password_forgot_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/verify":{"post":{"tags":["Auth","auth"],"summary":"Auth Verify","operationId":"auth_verify_auth_verify_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/login":{"post":{"tags":["Auth","auth"],"summary":"Auth Login","operationId":"auth_login_auth_login_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/resend":{"post":{"tags":["Auth","auth"],"summary":"Auth Resend","description":"Re-issue a 6-digit verification code (signup or recovery).","operationId":"auth_resend_auth_resend_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/password/reset":{"post":{"tags":["Auth","auth"],"summary":"Auth Reset","operationId":"auth_reset_auth_password_reset_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/password/change":{"post":{"tags":["Auth","auth"],"summary":"Auth Password Change","description":"Change password for an already-authenticated session (profile page).","operationId":"auth_password_change_auth_password_change_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/google/start":{"post":{"tags":["Auth","auth"],"summary":"Auth Google Start","operationId":"auth_google_start_auth_google_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/google/callback":{"get":{"tags":["Auth","auth"],"summary":"Auth Google Callback","operationId":"auth_google_callback_auth_google_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code"}},{"name":"n","in":"query","required":false,"schema":{"type":"string","default":"","title":"N"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/logout":{"post":{"tags":["Auth","auth"],"summary":"Auth Logout","operationId":"auth_logout_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/me":{"get":{"tags":["Auth","auth"],"summary":"Auth Me","operationId":"auth_me_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/overview/status":{"get":{"tags":["Overview"],"summary":"Overview Status","description":"Headline numbers for the status bar. Read-only; no admin token required.\n\naccount_usdt / risk_pct are the *user's own* position-sizing inputs. They\nare never stored server-side, so they are reported as null when the client\nhas not set them yet — the UI then asks instead of guessing.","operationId":"overview_status_overview_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/overview/history":{"get":{"tags":["Overview"],"summary":"Overview History","description":"Server-side pagination over past signals.\n\nFiltering and paging happen here so the browser never downloads the whole\ntable. Every returned row carries Persian labels next to the raw enum so\nthe UI can show readable text while keeping the raw value for filtering.","operationId":"overview_history_overview_history_get","parameters":[{"name":"outcome","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"WIN / LOSS / FAILURE / …","title":"Outcome"},"description":"WIN / LOSS / FAILURE / …"},{"name":"symbol","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Symbol"}},{"name":"node_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Type"}},{"name":"session","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session"}},{"name":"entry_logic","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entry Logic"}},{"name":"days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":3650,"minimum":1},{"type":"null"}],"description":"Look-back window","title":"Days"},"description":"Look-back window"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date, inclusive","title":"Date From"},"description":"ISO date, inclusive"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date, inclusive","title":"Date To"},"description":"ISO date, inclusive"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":25,"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/profile/me":{"get":{"tags":["Profile","profile"],"summary":"Profile Me","operationId":"profile_me_profile_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"patch":{"tags":["Profile","profile"],"summary":"Profile Update","operationId":"profile_update_profile_me_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayNameBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/profile/purchases":{"get":{"tags":["Profile","profile"],"summary":"Profile Purchases","description":"Issued indicator licenses for this user (email-matched).","operationId":"profile_purchases_profile_purchases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/profile/charges":{"get":{"tags":["Profile","profile"],"summary":"Profile Charges","description":"Order/charge history for this user (email-matched).","operationId":"profile_charges_profile_charges_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/profile/favorites":{"get":{"tags":["Profile","profile"],"summary":"Favorites List","operationId":"favorites_list_profile_favorites_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Profile","profile"],"summary":"Favorites Add","operationId":"favorites_add_profile_favorites_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/profile/favorites/{signal_id}":{"delete":{"tags":["Profile","profile"],"summary":"Favorites Remove","operationId":"favorites_remove_profile_favorites__signal_id__delete","parameters":[{"name":"signal_id","in":"path","required":true,"schema":{"type":"string","title":"Signal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/profile/reminders":{"get":{"tags":["Profile","profile"],"summary":"Reminders List","operationId":"reminders_list_profile_reminders_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Profile","profile"],"summary":"Reminders Add","operationId":"reminders_add_profile_reminders_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/profile/reminders/{reminder_id}":{"patch":{"tags":["Profile","profile"],"summary":"Reminders Patch","operationId":"reminders_patch_profile_reminders__reminder_id__patch","parameters":[{"name":"reminder_id","in":"path","required":true,"schema":{"type":"string","title":"Reminder Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderPatchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Profile","profile"],"summary":"Reminders Delete","operationId":"reminders_delete_profile_reminders__reminder_id__delete","parameters":[{"name":"reminder_id","in":"path","required":true,"schema":{"type":"string","title":"Reminder Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/testimonials/":{"get":{"tags":["Testimonials"],"summary":"List Testimonials","description":"Approved reviews only. Empty list when nothing has been approved yet.","operationId":"list_testimonials_testimonials__get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":12,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/testimonials/meta":{"get":{"tags":["Testimonials"],"summary":"Testimonials Meta","description":"Drives the section's visibility. ``visible`` is false until at least one\nreview is approved, so the page never shows an empty testimonials box.","operationId":"testimonials_meta_testimonials_meta_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin-panel/testimonials/":{"post":{"tags":["Testimonials Admin"],"summary":"Create Testimonial","description":"Submit a review. It is stored as pending and is NOT publicly visible\nuntil an admin approves it.","operationId":"create_testimonial_admin_panel_testimonials__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestimonialCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Testimonials Admin"],"summary":"List All Testimonials","description":"Moderation view — every row with its status.","operationId":"list_all_testimonials_admin_panel_testimonials__get","security":[{"HTTPBearer":[]}],"parameters":[{"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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin-panel/testimonials/{testimonial_id}":{"patch":{"tags":["Testimonials Admin"],"summary":"Set Testimonial Status","operationId":"set_testimonial_status_admin_panel_testimonials__testimonial_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"testimonial_id","in":"path","required":true,"schema":{"type":"string","title":"Testimonial Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestimonialStatusBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Testimonials Admin"],"summary":"Delete Testimonial","operationId":"delete_testimonial_admin_panel_testimonials__testimonial_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"testimonial_id","in":"path","required":true,"schema":{"type":"string","title":"Testimonial Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/supabase/url":{"get":{"summary":"Supabase Url","operationId":"supabase_url_api_supabase_url_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ConsentBody":{"properties":{"user_ref":{"type":"string","maxLength":200,"minLength":3,"title":"User Ref"},"agreement_version":{"type":"string","maxLength":64,"minLength":1,"title":"Agreement Version"}},"type":"object","required":["user_ref","agreement_version"],"title":"ConsentBody"},"DisplayNameBody":{"properties":{"display_name":{"type":"string","maxLength":80,"title":"Display Name","default":""}},"type":"object","title":"DisplayNameBody"},"ExchangeIn":{"properties":{"id":{"type":"string","title":"Id"},"display_name_fa":{"type":"string","title":"Display Name Fa"},"display_name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name En"},"kind":{"type":"string","title":"Kind"},"status":{"type":"string","title":"Status","default":"disabled"},"priority":{"type":"integer","title":"Priority","default":100},"base_url":{"type":"string","title":"Base Url"},"testnet_base_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Testnet Base Url"},"requires_iran_ip":{"type":"boolean","title":"Requires Iran Ip","default":false},"auth_type":{"type":"string","title":"Auth Type"},"auth_fields":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Auth Fields"},"capabilities":{"additionalProperties":true,"type":"object","title":"Capabilities"},"rate_limit":{"additionalProperties":true,"type":"object","title":"Rate Limit"},"fee_schedule":{"additionalProperties":true,"type":"object","title":"Fee Schedule"},"symbol_map":{"additionalProperties":true,"type":"object","title":"Symbol Map"},"min_order_rules":{"additionalProperties":true,"type":"object","title":"Min Order Rules"},"docs_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Docs Url"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["id","display_name_fa","kind","base_url","auth_type"],"title":"ExchangeIn"},"ExchangePatch":{"properties":{"display_name_fa":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name Fa"},"display_name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name En"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"priority":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priority"},"base_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Url"},"testnet_base_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Testnet Base Url"},"requires_iran_ip":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Requires Iran Ip"},"auth_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Type"},"auth_fields":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Auth Fields"},"capabilities":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Capabilities"},"rate_limit":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Rate Limit"},"fee_schedule":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Fee Schedule"},"symbol_map":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Symbol Map"},"min_order_rules":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Min Order Rules"},"docs_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Docs Url"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"ExchangePatch"},"FavoriteBody":{"properties":{"signal_id":{"type":"string","maxLength":128,"minLength":1,"title":"Signal Id"}},"type":"object","required":["signal_id"],"title":"FavoriteBody"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LicenseLookupBody":{"properties":{"user_ref":{"type":"string","maxLength":200,"minLength":3,"title":"User Ref"}},"type":"object","required":["user_ref"],"title":"LicenseLookupBody"},"LicenseVerifyBody":{"properties":{"license_id":{"type":"string","maxLength":80,"minLength":8,"title":"License Id"},"mt_account":{"type":"string","maxLength":64,"minLength":1,"title":"Mt Account"},"mt_company":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Mt Company"}},"type":"object","required":["license_id","mt_account"],"title":"LicenseVerifyBody"},"OrderBody":{"properties":{"user_ref":{"type":"string","maxLength":200,"minLength":3,"title":"User Ref"},"plan_id":{"type":"string","maxLength":64,"minLength":1,"title":"Plan Id"},"consent_id":{"type":"string","maxLength":64,"minLength":1,"title":"Consent Id"}},"type":"object","required":["user_ref","plan_id","consent_id"],"title":"OrderBody"},"ReminderBody":{"properties":{"symbol":{"type":"string","maxLength":32,"minLength":1,"title":"Symbol"},"target_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Target Price"},"direction":{"type":"string","maxLength":8,"title":"Direction","default":"above"},"note":{"type":"string","maxLength":500,"title":"Note","default":""}},"type":"object","required":["symbol"],"title":"ReminderBody"},"ReminderPatchBody":{"properties":{"is_done":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Done"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note"}},"type":"object","title":"ReminderPatchBody"},"ReorderIn":{"properties":{"ids":{"items":{"type":"string"},"type":"array","title":"Ids"}},"type":"object","required":["ids"],"title":"ReorderIn"},"RiskSettingsIn":{"properties":{"max_risk_pct_per_trade":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Risk Pct Per Trade"},"max_concurrent_trades":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Concurrent Trades"},"min_tier_for_autotrade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Min Tier For Autotrade"},"min_tier_wr":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Tier Wr"},"min_ml_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Ml Confidence"},"require_ml_holdout_auc":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Require Ml Holdout Auc"},"kill_switch":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Kill Switch"}},"type":"object","title":"RiskSettingsIn"},"SignalExplainRequest":{"properties":{"signal_id":{"type":"string","title":"Signal Id"},"lang":{"type":"string","title":"Lang","default":"fa"}},"type":"object","required":["signal_id"],"title":"SignalExplainRequest"},"TestimonialCreate":{"properties":{"author_name":{"type":"string","maxLength":80,"minLength":1,"title":"Author Name"},"body":{"type":"string","maxLength":1000,"minLength":1,"title":"Body"},"avatar_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Avatar Url"}},"type":"object","required":["author_name","body"],"title":"TestimonialCreate"},"TestimonialStatusBody":{"properties":{"status":{"type":"string","pattern":"^(pending|approved|rejected)$","title":"Status"}},"type":"object","required":["status"],"title":"TestimonialStatusBody"},"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"},"_ScanRunBody":{"properties":{"symbols":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Symbols"}},"type":"object","title":"_ScanRunBody"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}