{"openapi":"3.1.0","info":{"title":"Foresea Intelligence API","description":"\n## Overview\n\nThe **Foresea Intelligence API** turns market questions, linked evidence, and\nprediction-market prices into probabilistic forecasts that can sit behind\ntrading dashboards, alerting systems, and research workflows.\n\nIt supports binary, multiple-choice, numeric, and date forecasts. Each response\nincludes a structured **rationale**, typed forecast fields, optional evidence\nsources fetched from live news, and optional market-edge analysis when you pass\na market-implied probability.\n\n---\n\n## Quick start\n\n```bash\ncurl -X POST https://foresea.ink/predict \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"question\": \"Will the Fed cut rates before September 30, 2026?\",\n    \"question_type\": \"binary\",\n    \"market_platform\": \"Polymarket\",\n    \"market_probability\": 0.54,\n    \"variant\": \"variant0_neutral_baseline\"\n  }'\n```\n\n---\n\n## Question types\n\nUse `question_type` when your client already knows the shape of the question.\nIf omitted, the model will try to infer it.\n\n| Type | Response shape |\n|---|---|\n| `binary` | `predicted_answer` is `Yes`/`No`; `confidence` is 0–1 |\n| `multiple_choice` | `options` contains per-option probabilities; `predicted_answer` is the top option |\n| `numeric` | `range_forecast` contains `p10`, `p50`, `p90`, and optional `unit` |\n| `date` | `range_forecast` contains date percentiles |\n\nFor multiple-choice forecasts, pass `options` when the answer set is known.\n\n---\n\n## Prediction-market context\n\nPass `market_probability` when you know the current market-implied probability\nfor the target outcome. For binary markets this defaults to the `Yes` side; set\n`market_outcome` to compare against `No` or a named multiple-choice outcome.\n\nForesea returns `market_analysis` with model probability, market probability,\npercentage-point edge, and a stance (`model_above_market`, `model_below_market`,\n`in_line`, or `not_comparable`).\n\n---\n\n## Trading execution\n\nForesea can preview and submit guarded orders for Kalshi and Polymarket:\n\n| Endpoint | Purpose |\n|---|---|\n| `GET /trading/accounts` | Return configured/not-configured server-account status without exposing secrets |\n| `POST /trading/accounts/check` | Validate caller-supplied own-account (BYO) credentials without storing them |\n| `POST /trading/preview` | Normalize and validate an order without placing it |\n| `POST /trading/orders` | Submit a live order after explicit confirmation |\n\nLive trading is disabled unless `FORESEA_ENABLE_TRADING=true`. Every live order\nrequires a signed-in user session, `execute=true`, and the exact confirmation\nphrase `PLACE REAL ORDER`. Market/IOC/FOK-style orders are separately blocked\nunless `FORESEA_ALLOW_MARKET_ORDERS=true`.\n\nExchange credentials come from one of two sources: the shared server account\n(environment variables / Secret Manager mounts), or **per-request own-account\ncredentials** a signed-in user supplies in `venue_credentials` so they trade\ntheir own Kalshi/Polymarket account. Own-account credentials are used transiently\nto sign a single order, never persisted, logged, or echoed back; that path is\ngated by `FORESEA_ENABLE_BYO_TRADING=true` (independent of `FORESEA_ENABLE_TRADING`).\n\n`/agent/analyze` may return a directional recommendation, but it never places an\norder. Use `/trading/preview` first, review the normalized order, then call\n`/trading/orders` only when you intend to submit a real order.\n\n---\n\n## Prompt variants\n\nThe `variant` field controls how the LLM is prompted. Choose the variant that\nbest matches the information you have available:\n\n| Variant key | Focus |\n|---|---|\n| `variant0_neutral_baseline` | Control — no extra framing (default) |\n| `variant1_predicted_event` | State the concrete predicted event |\n| `variant2_key_attribute` | Highlight time / quantity / actor |\n| `variant3_reasoning_type` | Specify reasoning type (speculation, expert forecast…) |\n| `variant4_credibility` | Ground rationale in source credibility scores |\n| `variant5_key_conditions` | List 2–4 conditions that must hold |\n| `variant6_step_by_step_reasoning` | Produce 2–3 numbered reasoning steps |\n| `variant7_uncertainty_language` | Require uncertainty hedging words |\n| `variant8_temporal_anchors` | Anchor reasoning to specific dates |\n\n---\n\n## Rate limiting\n\n**`RATE_LIMIT_PER_MIN` requests per minute per IP address (default 200).** Exceeding this returns `429 Too Many Requests`\nwith a `Retry-After: 60` header.\n\n---\n\n## Authentication\n\nWhen the server is configured with `API_KEY`, all prediction endpoints require:\n\n```\nX-API-Key: <your-key>\n```\n\nThe `/health` endpoint is always unauthenticated. Per-user endpoints such as\nRAG, chat history, and trading require an `Authorization: Bearer <session-token>`\nheader returned by the sign-in endpoints.\n\n---\n\n## Source code\n\n[github.com/pareelamle/analyzing-llm-rationale](https://github.com/pareelamre/analyzing-llm-rationale)\n","contact":{"name":"Pareel Amre","url":"https://github.com/pareelamre/analyzing-llm-rationale","email":"pareel.amre@gmail.com"},"license":{"name":"MIT","url":"https://opensource.org/licenses/MIT"},"version":"1.0.0"},"paths":{"/pr-agent":{"get":{"tags":["Agents"],"summary":"Foresea PR agent outreach packet","description":"Agent-readable Foresea introduction material for opt-in outreach.","operationId":"pr_agent_packet_pr_agent_get","parameters":[{"name":"audience","in":"query","required":false,"schema":{"type":"string","default":"agent","title":"Audience"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/track-record/digest":{"get":{"tags":["System"],"summary":"Shareable track-record summary","description":"A short, shareable markdown summary of the live track record — ready to\npost (a weekly recap). Built from the resolved-forecast aggregate so it\nnever overstates.","operationId":"track_record_digest_track_record_digest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/benchmark/score":{"post":{"tags":["System"],"summary":"Score a set of resolved forecasts","description":"Grade any forecaster's resolved predictions: Brier score, accuracy, ECE\n(calibration), and — when market prices are supplied — skill vs the market.\nLets you benchmark an LLM, a person, or another model against the same yardstick\nForesea grades itself on.","operationId":"benchmark_score_benchmark_score_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchmarkRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Benchmark Score Benchmark Score Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/track-record":{"get":{"tags":["System"],"summary":"Public forecasting track record","description":"Return Foresea's resolved-forecast track record.\n\nOnce the live, point-in-time record has resolved forecasts, this returns it\n(forecasts made on live Polymarket/Kalshi markets and scored at resolution,\nwith skill-vs-market). Until then it falls back to the static backtest of\n`gpt-oss-120b` against published Metaculus outcomes: accuracy, Brier score,\ncalibration (ECE), a reliability curve, and a sample of resolved forecasts.","operationId":"track_record_track_record_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/edge-board":{"get":{"tags":["System"],"summary":"Live model-vs-market edge board","description":"Where Foresea's evidence-based fair probability most disagrees with the\nmarket price right now — and whether that kind of disagreement has paid.\n\n- ``edge_board``: open markets ranked by live disagreement, each tagged with\n  the resolved track record of gaps that size (``track_record.skill_significant``\n  flags disagreements our own history has proven beat the market).\n- ``by_edge``: realized skill-vs-market bucketed by disagreement size — the\n  proof of whether bigger gaps actually resolved in the model's favour.\n- ``lead_lag``: whether the market has historically moved *toward* the model\n  after a disagreement (the model leading the price).\n- ``paper_pnl``: hypothetical paper-trading return of betting the edge over\n  resolved snapshots (flat / edge-weighted / validated-only). Paper only — no\n  fees or slippage; not live trading.","operationId":"edge_board_edge_board_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/live-prices":{"get":{"tags":["System"],"summary":"Real-time market prices for tracked open markets","description":"Current market prices fetched directly from Polymarket/Kalshi for every\nmarket currently on the edge board. Used by the frontend to refresh market\nprices in real time without re-running model forecasts.\n\nReturns ``{prices: {ident: probability}, generated_at}``. Cached 30 s.","operationId":"live_prices_live_prices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/track-record/pending-markets":{"get":{"tags":["System"],"summary":"Agent-enrolled markets awaiting tracking","description":"Markets that agents forecast against (via /predict or /agent/analyze) that\naren't yet in the live track record. The track-record Action pulls these and\nseeds them so they get tracked + scored. Token-gated (`X-Track-Token`).","operationId":"pending_markets_track_record_pending_markets_get","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 Pending Markets Track Record Pending Markets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/track-record/mark-enrolled":{"post":{"tags":["System"],"summary":"Mark agent-enrolled markets as tracked","description":"Flip `enrolled=True` on markets the Action has started tracking (so they\nleave the pending queue), and prune old tracked/stale pointers. Token-gated.","operationId":"mark_enrolled_track_record_mark_enrolled_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkEnrolledRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Mark Enrolled Track Record Mark Enrolled Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/radar":{"get":{"tags":["Markets"],"summary":"Foresea Radar: niche prediction-market opportunities","description":"Daily niche-market radar from Reddit, Polymarket, Kalshi, and Foresea's\ncommitted live snapshots.\n\nThe endpoint serves the committed ``static/radar.json`` artifact built by\nGitHub Actions. The Action may run fresh `/predict` forecasts before\ncommitting; Cloud Run never does Radar scraping or batch forecasting on page\nload.","operationId":"radar_radar_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"include_reddit","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Reddit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["System"],"summary":"Health check","description":"Returns `{\"status\": \"ok\"}` when the server is running.\n\nUse this endpoint for liveness probes and uptime monitoring.\nIt does **not** verify that the LLM provider is reachable.","operationId":"health_health_get","responses":{"200":{"description":"Service status.","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Health Get"},"example":{"status":"ok"}}}}}}},"/ready":{"get":{"tags":["System"],"summary":"Readiness check","description":"Returns 200 when the server is initialised and accepting traffic, 503\notherwise (still booting, misconfigured, or draining on shutdown).\n\nUnlike `/health` (liveness), this verifies the forecasting provider is\nconfigured — use it for load-balancer readiness routing.","operationId":"ready_ready_get","responses":{"200":{"description":"Whether the service is ready to serve traffic.","content":{"application/json":{"schema":{}}}}}}},"/analytics/visit":{"post":{"tags":["System"],"summary":"Record anonymous page visit","description":"Record one anonymous page visit.\n\nStores no raw IP address. Unique visitors are estimated with a salted hash\nof IP address and user agent.","operationId":"record_visit_analytics_visit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Record Visit Analytics Visit Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/analytics/summary":{"get":{"tags":["System"],"summary":"Analytics Summary","description":"Return basic page-visit counts.\n\nIf `API_KEY` is configured, this endpoint requires `X-API-Key`.\n\nCounts are persisted in Cloud Datastore when available (survive deploys /\ninstance recycles); otherwise they come from the local ephemeral DuckDB.","operationId":"analytics_summary_analytics_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSummary"}}}}}}},"/feedback":{"post":{"tags":["System"],"summary":"Submit user feedback","description":"Accept feedback from the UI and forward it by email.","operationId":"submit_feedback_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Submit Feedback Feedback Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/markets/polymarket":{"get":{"tags":["Markets"],"summary":"Fetch a Polymarket market","description":"Fetch a live Polymarket quote by market `slug` (or numeric `id`).\n\nThe result is normalised so `probability` can be passed to `/predict` as\n`market_probability` (with `market_platform=\"Polymarket\"`) to compute an edge.","operationId":"market_polymarket_markets_polymarket_get","parameters":[{"name":"slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"}},{"name":"id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketQuote"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/markets/kalshi":{"get":{"tags":["Markets"],"summary":"Fetch a Kalshi market","description":"Fetch a live Kalshi quote by market `ticker` (e.g. `KXFED-26SEP-C`).","operationId":"market_kalshi_markets_kalshi_get","parameters":[{"name":"ticker","in":"query","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketQuote"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trading/accounts":{"get":{"tags":["Trading"],"summary":"Check configured trading venues","description":"Return configured/not-configured status for server-side exchange credentials.\n\nThis endpoint never returns private keys, API secrets, or passphrases. Live\norder submission still requires `/trading/orders` confirmation.","operationId":"trading_accounts_trading_accounts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradingAccountStatus"}}}}}}},"/trading/accounts/check":{"post":{"tags":["Trading"],"summary":"Validate own-account (BYO) trading credentials","description":"Report readiness for caller-supplied own-account credentials, never stored.\n\nLets the UI confirm a connected Kalshi/Polymarket account (e.g. the RSA key\nparses) before placing an order. Credentials are used transiently and never\nechoed back — only boolean readiness is returned.","operationId":"trading_accounts_check_trading_accounts_check_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradingAccountCheckRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradingAccountStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trading/preview":{"post":{"tags":["Trading"],"summary":"Preview a guarded prediction-market order","description":"Validate and normalize a Kalshi/Polymarket order without placing it.","operationId":"trading_preview_trading_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradeOrderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradeOrderPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trading/orders":{"post":{"tags":["Trading"],"summary":"Submit a confirmed prediction-market order","description":"Submit a live order after preview guardrails and exact confirmation.\n\nLive execution is disabled unless `FORESEA_ENABLE_TRADING=true`. Market/IOC\nstyle orders are separately disabled unless `FORESEA_ALLOW_MARKET_ORDERS=true`.","operationId":"trading_order_trading_orders_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradeOrderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TradeOrderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/models":{"get":{"tags":["System"],"summary":"List models from a provider base URL","description":"Fetch available models from an OpenAI-compatible or Ollama endpoint.\n\nPass `base_url` (e.g. `http://localhost:11434`). Returns `{models: [...]}`.\nCloud-metadata hosts are blocked.","operationId":"list_provider_models_providers_models_get","parameters":[{"name":"base_url","in":"query","required":true,"schema":{"type":"string","maxLength":500,"title":"Base Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/extract":{"post":{"tags":["System"],"summary":"Extract text from a PDF file or URL","description":"Extract plain text from an uploaded PDF or a web URL.\n\nReturns a dict compatible with the `news_articles` field of `/predict`:\n`{title, text, source, url}`. Pass one of `file` or `url`, not both.","operationId":"extract_attachment_extract_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_extract_attachment_extract_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Extract Attachment Extract Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/google":{"post":{"tags":["Auth"],"summary":"Sign in with Google","description":"Verify a Google One-Tap ID token, create or update the user account, and return a session token.\n\nThe browser should send the `credential` string returned by\n`google.accounts.id.initialize({ callback })` after the user grants consent.\nStore the returned `token` in `localStorage` and include it as\n`Authorization: Bearer <token>` on subsequent authenticated requests.","operationId":"auth_google_auth_google_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/github":{"post":{"tags":["Auth"],"summary":"Sign in with GitHub","description":"Exchange a GitHub OAuth `code` for the user's profile and return a session token.\n\nThe browser sends users to GitHub's authorize URL, then posts the returned\n`code` (and the same `redirect_uri`) here. Store the returned `token` like the\nGoogle flow.","operationId":"auth_github_auth_github_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/register":{"post":{"tags":["Auth"],"summary":"Create an account","description":"Create an email/password account and return a session token.\n\nThe email becomes the account ID. Passwords are stored as salted\nPBKDF2-HMAC-SHA256 hashes; the plaintext is never persisted.","operationId":"auth_register_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Sign in with email and password","description":"Verify an email/password account and return a session token.","operationId":"auth_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/SessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/me":{"get":{"tags":["Auth"],"summary":"Get current user","description":"Return the authenticated user decoded from the `Authorization: Bearer` session token.","operationId":"auth_me_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthMeResponse"}}}}}}},"/favorites":{"get":{"tags":["Auth"],"summary":"List favourited markets","description":"Return the signed-in user's favourited markets/questions (their watchlist).","operationId":"list_favorites_favorites_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteList"}}}}}}},"/favorites/{key}":{"put":{"tags":["Auth"],"summary":"Add/update a favourite","description":"Create or replace one favourite for the signed-in user.","operationId":"save_favorite_favorites__key__put","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteMarket"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteMarket"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Auth"],"summary":"Remove a favourite","description":"Delete one favourite for the signed-in user.","operationId":"remove_favorite_favorites__key__delete","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"},"title":"Response Remove Favorite Favorites  Key  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/favorites/prices":{"get":{"tags":["Auth"],"summary":"Live prices for favourited markets","description":"Fetch current market prices for the user's favourited markets (cheap, no LLM).","operationId":"favorite_prices_favorites_prices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Favorite Prices Favorites Prices Get"}}}}}}},"/market/quote":{"get":{"tags":["Markets"],"summary":"Quote a single market by platform+ident","description":"Fetch one market's current quote (question, price, 24h change, close time)\nso the watchlist can add a market pasted as a URL. Public + cached, no LLM.","operationId":"market_quote_market_quote_get","parameters":[{"name":"platform","in":"query","required":true,"schema":{"type":"string","maxLength":20,"title":"Platform"}},{"name":"ident","in":"query","required":true,"schema":{"type":"string","maxLength":200,"title":"Ident"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Market Quote Market Quote Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/market/forecast":{"post":{"tags":["Markets"],"summary":"Forecast one market now","description":"Run the model on a single market right now and return its probability, so a\nfreshly-watchlisted market shows a forecast without waiting for the next tick.\nSign-in gated (the watchlist is). Reuses the `/predict` pipeline.","operationId":"market_forecast_market_forecast_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketForecastRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Market Forecast Market Forecast Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/markets/search":{"get":{"tags":["Markets"],"summary":"Search markets to add to a watchlist","description":"Search open Polymarket + Kalshi markets by keyword and/or category (empty\n`q`+`category` = trending by volume) so the watchlist can browse-and-add with\none click. Public + cached.","operationId":"markets_search_markets_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":120,"default":"","title":"Q"}},{"name":"category","in":"query","required":false,"schema":{"type":"string","maxLength":40,"default":"","title":"Category"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":40,"minimum":1,"default":24,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Markets Search Markets Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rag/ingest":{"post":{"tags":["Knowledge"],"summary":"Add a document to your knowledge base","description":"Chunk, embed, and store a document (text or URL) in the signed-in user's\nknowledge base, so the agent can retrieve it as evidence.","operationId":"rag_ingest_rag_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RagIngestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Rag Ingest Rag Ingest Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rag/search":{"get":{"tags":["Knowledge"],"summary":"Search your knowledge base","operationId":"rag_search_rag_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","title":"Q"}},{"name":"namespace","in":"query","required":false,"schema":{"type":"string","default":"kb","title":"Namespace"}},{"name":"top_k","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Top K"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RagSearchResult"},"title":"Response Rag Search Rag Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rag/documents":{"get":{"tags":["Knowledge"],"summary":"List your knowledge-base documents","operationId":"rag_documents_rag_documents_get","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"type":"string","default":"kb","title":"Namespace"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rag Documents Rag Documents Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Knowledge"],"summary":"Delete knowledge-base documents","operationId":"rag_delete_rag_documents_delete","parameters":[{"name":"namespace","in":"query","required":false,"schema":{"type":"string","default":"kb","title":"Namespace"}},{"name":"doc_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"integer"},"title":"Response Rag Delete Rag Documents Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predict":{"post":{"tags":["Inference"],"summary":"Run a single forecasting prediction","description":"Submit a forecasting question and receive a typed structured prediction.\n\nThe model returns:\n- **`question_type`** — `binary`, `multiple_choice`, `numeric`, or `date`\n- **`predicted_answer`** — `Yes`/`No`, top option, or median estimate\n- **`confidence`** — probability (0–1) for binary and multiple-choice answers\n- **`options`** — per-option probabilities for multiple-choice questions\n- **`range_forecast`** — p10/p50/p90 bounds for numeric and date questions\n- **`rationale`** — 2–4 sentence explanation\n- **`evidence_sources`** — news articles used as context\n- **`market_analysis`** — model-vs-market edge when `market_probability` is provided\n\n### Choosing a variant\n\nStart with `variant0_neutral_baseline` (the default). Switch to other variants\nto inject additional structure into the prompt — for example, `variant3_reasoning_type`\nasks the model to identify whether the prediction is based on speculation, an expert\nforecast, or a stated plan.\n\n### Providing your own evidence\n\nPass pre-fetched articles in `news_articles` to use them directly.\nLeave the list empty to trigger automatic news retrieval (if the evidence\npipeline is configured on the server).\n\n### Example — binary request\n\n```bash\ncurl -X POST /predict \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"question\": \"Will oil prices exceed $100 per barrel in 2026?\",\n    \"question_type\": \"binary\",\n    \"market_platform\": \"Kalshi\",\n    \"market_probability\": 0.31\n  }'\n```\n\n### Example — multiple choice\n\n```bash\ncurl -X POST /predict \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"question\": \"Who will win the 2026 Formula 1 drivers championship?\",\n    \"question_type\": \"multiple_choice\",\n    \"options\": [\"Max Verstappen\", \"Lando Norris\", \"Charles Leclerc\", \"Lewis Hamilton\", \"Other\"],\n    \"attach_evidence\": false\n  }'\n```\n\n### Example — numeric forecast with context\n\n```bash\ncurl -X POST /predict \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"question\": \"What will US CPI inflation be in December 2026?\",\n    \"question_type\": \"numeric\",\n    \"resolution_criteria\": \"Use the year-over-year CPI-U inflation rate for December 2026.\",\n    \"categories\": [\"Economics\", \"United States\"],\n    \"variant\": \"variant5_key_conditions\"\n  }'\n```","operationId":"predict_predict_post","parameters":[{"name":"kb_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kb User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictRequest"}}}},"responses":{"200":{"description":"Prediction returned successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}}},"400":{"description":"Invalid request — unknown variant or malformed input."},"401":{"description":"Missing or invalid `X-API-Key` header (only when API key is configured)."},"429":{"description":"Rate limit exceeded. Retry after 60 seconds."},"503":{"description":"Server not yet initialised — LLM provider not loaded."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predict/stream":{"post":{"tags":["Inference"],"summary":"Stream a conversational forecasting response","description":"Stream model output as server-sent events, for all question types.\n\nDelta events carry raw text chunks as they arrive so the UI can render the\nrationale progressively. The final ``done`` event contains the same fully-\nparsed ``PredictResponse`` shape that ``/predict`` returns, including\nstructured fields (``predicted_answer``, ``confidence``, etc.) for binary,\nnumeric, and multiple-choice questions.","operationId":"predict_stream_predict_stream_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictRequest"}}},"required":true},"responses":{"200":{"description":"Server-sent events containing model text deltas and a final PredictResponse payload.","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/analyze":{"post":{"tags":["Agents"],"summary":"Run the analysis agent on a live question","description":"Orchestrate an end-to-end analysis of a live market question.\n\nPipeline: resolve the market (fetch a live Polymarket/Kalshi price when an\nidentifier is given) → gather evidence and forecast → compute the model-vs-market\nedge → run any custom **skills** → recommend. Returns one structured report.","operationId":"agent_analyze_agent_analyze_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAnalyzeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent/scan":{"get":{"tags":["Agents"],"summary":"Scan a venue for mispriced markets","description":"Scan live markets on one or both venues and surface the most mispriced.\n\nLists active markets (Polymarket and/or Kalshi), forecasts each, compares\nagainst the market price, and returns those whose model-vs-market gap is at\nleast `min_edge`. `platform` accepts `polymarket`, `kalshi`, or `all`/`both`.\n`query` optionally filters to markets whose question contains that keyword\n(e.g. `nba`). Bounded by `limit` per venue (max 8) since each market runs a\nfull forecast; results are cached briefly.","operationId":"agent_scan_agent_scan_get","parameters":[{"name":"platform","in":"query","required":false,"schema":{"type":"string","default":"polymarket","title":"Platform"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":4,"title":"Limit"}},{"name":"min_edge","in":"query","required":false,"schema":{"type":"number","default":0.1,"title":"Min Edge"}},{"name":"evidence_top_k","in":"query","required":false,"schema":{"type":"integer","default":3,"title":"Evidence Top K"}},{"name":"query","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Query"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScanResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AgentAnalyzeRequest":{"properties":{"question":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Question","description":"Market question. Optional if a market identifier is given."},"platform":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Platform","description":"'polymarket' or 'kalshi' to fetch a live price."},"slug":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Slug","description":"Polymarket market slug."},"market_id":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Market Id","description":"Polymarket numeric market id."},"ticker":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Ticker","description":"Kalshi market ticker."},"market_probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Probability","description":"Override market price (0..1 or 0..100) when not fetching."},"variant":{"type":"string","maxLength":64,"title":"Variant","default":"variant0_neutral_baseline"},"evidence_top_k":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Evidence Top K","default":5},"skills":{"items":{"$ref":"#/components/schemas/AgentSkill"},"type":"array","maxItems":5,"title":"Skills","description":"Up to 5 custom skills to run."},"builtin_skills":{"type":"boolean","title":"Builtin Skills","description":"Also run the built-in forecasting toolkit (base rate, scenario decomposition, red team, key drivers).","default":false},"ground_in_record":{"type":"boolean","title":"Ground In Record","description":"Condition the forecast on the model's own live track-record calibration.","default":false},"tool_loop":{"type":"boolean","title":"Tool Loop","description":"Use a ReAct tool-using loop (model plans + calls tools) instead of the fixed pipeline.","default":false},"max_tool_steps":{"type":"integer","maximum":8.0,"minimum":1.0,"title":"Max Tool Steps","description":"Max tool calls in the loop.","default":5},"history":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array","maxItems":24,"title":"History","description":"Prior conversation turns for follow-up context."},"openrouter_api_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Openrouter Api Key"},"openrouter_model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Openrouter Model"},"provider_base_url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Provider Base Url"},"ollama_base_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Ollama Base Url"}},"type":"object","title":"AgentAnalyzeRequest","description":"Ask the analysis agent to work a live question end-to-end."},"AgentReport":{"properties":{"question":{"type":"string","title":"Question"},"pipeline":{"items":{"type":"string"},"type":"array","title":"Pipeline","description":"Ordered steps the agent ran."},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"market_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Url"},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome"},"market_probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Probability"},"model_probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Model Probability"},"edge":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Edge"},"stance":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stance"},"recommendation":{"type":"string","title":"Recommendation","description":"`buy_yes`, `buy_no`, `hold`, or `no_market_price`."},"recommendation_detail":{"type":"string","title":"Recommendation Detail","default":""},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence"},"question_type":{"type":"string","title":"Question Type","default":"binary"},"thesis":{"type":"string","title":"Thesis","default":""},"evidence_sources":{"items":{"$ref":"#/components/schemas/EvidenceSource"},"type":"array","title":"Evidence Sources"},"skills":{"items":{"$ref":"#/components/schemas/AgentSkillResult"},"type":"array","title":"Skills"},"grounding":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Grounding","description":"Track-record self-calibration note applied to the forecast."},"tool_transcript":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Tool Transcript","description":"Tool calls + observations when the tool loop ran."}},"type":"object","required":["question","recommendation"],"title":"AgentReport","description":"End-to-end analysis of a live question produced by the agent."},"AgentScanResponse":{"properties":{"platform":{"type":"string","title":"Platform"},"scanned":{"type":"integer","title":"Scanned","description":"How many live markets were analysed."},"opportunities":{"items":{"$ref":"#/components/schemas/ScanOpportunity"},"type":"array","title":"Opportunities"}},"type":"object","required":["platform","scanned"],"title":"AgentScanResponse","description":"Mispriced markets surfaced by the scan agent, ranked by |edge|."},"AgentSkill":{"properties":{"name":{"type":"string","maxLength":60,"minLength":1,"title":"Name","description":"Short skill name, e.g. 'Base rate check'."},"instruction":{"type":"string","maxLength":2000,"minLength":1,"title":"Instruction","description":"What this skill should analyse."}},"type":"object","required":["name","instruction"],"title":"AgentSkill","description":"A user-defined analysis step the agent runs over the question + evidence."},"AgentSkillResult":{"properties":{"name":{"type":"string","title":"Name"},"output":{"type":"string","title":"Output"}},"type":"object","required":["name","output"],"title":"AgentSkillResult"},"AnalyticsSummary":{"properties":{"total_visits":{"type":"integer","title":"Total Visits"},"unique_visitors":{"type":"integer","title":"Unique Visitors"},"by_day":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"By Day"}},"type":"object","required":["total_visits","unique_visitors","by_day"],"title":"AnalyticsSummary"},"AuthMeResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"type":"string","title":"Email"},"name":{"type":"string","title":"Name"},"picture":{"type":"string","title":"Picture"}},"type":"object","required":["user_id","email","name","picture"],"title":"AuthMeResponse","description":"Current user decoded from a session token."},"BenchmarkForecast":{"properties":{"probability":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Probability","description":"Forecast probability of YES (0–1)."},"outcome":{"type":"integer","maximum":1.0,"minimum":0.0,"title":"Outcome","description":"Realized outcome: 1 (YES) or 0 (NO)."},"market_probability":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Market Probability","description":"Market price at forecast time, for skill-vs-market."},"question":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Question"}},"type":"object","required":["probability","outcome"],"title":"BenchmarkForecast","description":"One resolved forecast to score: a probability and the realized outcome."},"BenchmarkRequest":{"properties":{"forecasts":{"items":{"$ref":"#/components/schemas/BenchmarkForecast"},"type":"array","maxItems":5000,"minItems":1,"title":"Forecasts"},"label":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Label","description":"Optional name for this forecaster/run."}},"type":"object","required":["forecasts"],"title":"BenchmarkRequest","description":"Score any forecaster's resolved calls — an AI-forecaster benchmark."},"Body_extract_attachment_extract_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"}},"type":"object","title":"Body_extract_attachment_extract_post"},"EvidenceSource":{"properties":{"source":{"type":"string","title":"Source","description":"Publisher name."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Article headline."},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Article URL."},"publish_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publish Date","description":"ISO 8601 publish date."},"relevance_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Relevance Score","description":"Relevance to the question (0–1)."}},"type":"object","required":["source"],"title":"EvidenceSource","description":"A deduplicated citation drawn from the evidence articles."},"FavoriteList":{"properties":{"favorites":{"items":{"$ref":"#/components/schemas/FavoriteMarket"},"type":"array","title":"Favorites"}},"type":"object","required":["favorites"],"title":"FavoriteList"},"FavoriteMarket":{"properties":{"key":{"type":"string","maxLength":160,"minLength":1,"pattern":"^[A-Za-z0-9:_\\-./]+$","title":"Key"},"question":{"type":"string","maxLength":500,"title":"Question","default":""},"platform":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Platform"},"ident":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Ident"},"market_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Market Url"},"model_probability":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Model Probability"},"market_probability":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Market Probability"},"notify":{"type":"boolean","title":"Notify","default":false},"createdAt":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Createdat"},"updatedAt":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["key"],"title":"FavoriteMarket","description":"A market or question a signed-in user has favourited to watch.\n\n`key` identifies the favourite (`{platform}:{ident}` for a market, or a\nclient-chosen slug for a bare question). `notify` opts the favourite into the\nperiodic email digest (`scripts/favorites_digest.py`)."},"FeedbackRequest":{"properties":{"message":{"type":"string","maxLength":4000,"minLength":1,"title":"Message"},"rating":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Rating"},"email":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Email"},"page":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Page"}},"type":"object","required":["message"],"title":"FeedbackRequest","description":"User-submitted feedback."},"GitHubAuthRequest":{"properties":{"code":{"type":"string","maxLength":512,"title":"Code"},"redirect_uri":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Redirect Uri"}},"type":"object","required":["code"],"title":"GitHubAuthRequest","description":"GitHub OAuth authorization code returned to the browser."},"GoogleAuthRequest":{"properties":{"credential":{"type":"string","maxLength":8192,"title":"Credential"}},"type":"object","required":["credential"],"title":"GoogleAuthRequest","description":"Google One-Tap credential submitted by the browser."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoginRequest":{"properties":{"email":{"type":"string","maxLength":254,"title":"Email"},"password":{"type":"string","maxLength":128,"title":"Password"}},"type":"object","required":["email","password"],"title":"LoginRequest","description":"Email + password sign-in submitted by the browser."},"MarkEnrolledRequest":{"properties":{"idents":{"items":{"type":"string"},"type":"array","maxItems":500,"title":"Idents"}},"type":"object","title":"MarkEnrolledRequest","description":"Idents (``\"platform:ident\"``) the Action has now started tracking."},"MarketAnalysis":{"properties":{"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform","description":"Prediction market venue supplied by the caller."},"market_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Url","description":"Prediction market URL supplied by the caller."},"outcome":{"type":"string","title":"Outcome","description":"Outcome being compared against the market price."},"market_probability":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Market Probability","description":"Market-implied probability for the outcome."},"model_probability":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Model Probability","description":"Foresea probability for the same outcome (recalibrated from the live track record when warranted)."},"model_probability_raw":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Model Probability Raw","description":"Raw model probability before live calibration (only set when calibration was applied)."},"edge":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Edge","description":"Model probability minus market probability."},"stance":{"type":"string","title":"Stance","description":"`model_above_market`, `model_below_market`, `in_line`, or `not_comparable`."},"summary":{"type":"string","title":"Summary","description":"Short human-readable market comparison."}},"type":"object","required":["outcome","market_probability","stance","summary"],"title":"MarketAnalysis","description":"Deterministic comparison between Foresea's forecast and a market price."},"MarketForecastRequest":{"properties":{"question":{"type":"string","maxLength":600,"title":"Question"},"market_probability":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Market Probability"},"market_platform":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Market Platform"},"market_ident":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Market Ident"},"market_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Market Url"}},"type":"object","required":["question"],"title":"MarketForecastRequest","description":"Forecast one market immediately (e.g. just-watchlisted)."},"MarketOption":{"properties":{"label":{"type":"string","title":"Label","description":"Outcome label, e.g. 'Yes' or 'No'."},"probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Probability","description":"Market-implied probability (0..1), or null when unpriced."}},"type":"object","required":["label"],"title":"MarketOption","description":"One outcome of a fetched prediction market and its implied probability."},"MarketQuote":{"properties":{"platform":{"type":"string","title":"Platform","description":"Venue: 'Polymarket' or 'Kalshi'."},"question":{"type":"string","title":"Question","description":"Market question/title.","default":""},"market_url":{"type":"string","title":"Market Url","description":"Canonical market URL.","default":""},"outcome":{"type":"string","title":"Outcome","description":"Primary outcome (prefers 'Yes').","default":""},"probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Probability","description":"Market-implied probability for `outcome` (0..1)."},"outcomes":{"items":{"$ref":"#/components/schemas/MarketOption"},"type":"array","title":"Outcomes","description":"All outcomes with their probabilities."}},"type":"object","required":["platform"],"title":"MarketQuote","description":"A live prediction-market quote, normalised for use with `/predict`."},"NewsArticle":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Title","description":"Article headline."},"summary":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Summary","description":"Short human-written summary."},"summary_llm":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Summary Llm","description":"LLM-generated summary."},"text":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Text","description":"Full article body text."},"source":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Source","description":"Publisher name (e.g. Reuters)."},"credibility":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Credibility","description":"Credibility score breakdown."},"frs":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Frs","description":"Future-Resolution Statement metadata."},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Url","description":"Canonical article URL."},"authors":{"anyOf":[{},{"type":"null"}],"title":"Authors","description":"Author name(s)."},"publish_date":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Publish Date","description":"ISO 8601 publish timestamp."},"keywords":{"anyOf":[{},{"type":"null"}],"title":"Keywords","description":"Extracted keywords."},"relevance_score":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Relevance Score","description":"Cosine similarity to the question (0–1)."},"search_query":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Search Query","description":"Query used to retrieve this article."}},"type":"object","title":"NewsArticle","description":"A news article passed as evidence context for the prediction.","example":{"publish_date":"2025-01-15T10:30:00Z","relevance_score":0.91,"source":"Reuters","summary":"Federal Reserve officials signaled a more cautious approach to rate cuts...","title":"Fed signals rate cuts may slow in 2025","url":"https://reuters.com/example"}},"OptionProb":{"properties":{"label":{"type":"string","title":"Label","description":"The option text."},"probability":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Probability","description":"Probability assigned to this option (0–1)."}},"type":"object","required":["label","probability"],"title":"OptionProb","description":"A single option and its probability in a multiple-choice forecast."},"PredictRequest":{"properties":{"question":{"type":"string","maxLength":2000,"minLength":1,"title":"Question","description":"The forecasting question to evaluate. It should ask about a future or otherwise resolvable event, option, quantity, or date.","examples":["Will the Federal Reserve cut interest rates at least once before the end of 2025?","Who will win the 2026 Formula 1 drivers championship?","What will US CPI inflation be in December 2026?"]},"description":{"type":"string","maxLength":4000,"title":"Description","description":"Extended background context that clarifies what the question is asking.","default":""},"resolution_criteria":{"type":"string","maxLength":2000,"title":"Resolution Criteria","description":"Exact conditions or measurement source used to resolve the forecast.","default":""},"categories":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Categories","description":"Topic tags (e.g. `['Economics', 'United States']`)."},"news_articles":{"items":{"$ref":"#/components/schemas/NewsArticle"},"type":"array","maxItems":20,"title":"News Articles","description":"Pre-fetched news articles to use as evidence. If empty and the evidence pipeline is configured, articles are fetched automatically."},"variant":{"type":"string","maxLength":100,"title":"Variant","description":"Prompt variant that controls the reasoning instruction style. See the variant table in the Overview section.","default":"variant0_neutral_baseline","examples":["variant0_neutral_baseline","variant3_reasoning_type"]},"attach_evidence":{"type":"boolean","title":"Attach Evidence","description":"If `true` and `news_articles` is empty, fetch live evidence automatically.","default":true},"evidence_top_k":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Evidence Top K","description":"Maximum number of evidence articles to retrieve (1–10).","default":5},"created_time":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Created Time","description":"ISO 8601 question creation time."},"publish_time":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Publish Time","description":"ISO 8601 question publish time."},"resolve_time":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Resolve Time","description":"ISO 8601 resolution deadline."},"days_open":{"anyOf":[{"type":"integer","maximum":36500.0,"minimum":0.0},{"type":"null"}],"title":"Days Open","description":"Days the question has been open."},"history":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array","maxItems":12,"title":"History","description":"Prior conversation turns for multi-turn context, oldest first. Each item is `{\"role\": \"user\"|\"assistant\", \"content\": \"...\"}`."},"question_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Question Type","description":"Question type: `binary`, `multiple_choice`, `numeric`, or `date`. Set this explicitly for API clients; auto-detected from the question when omitted."},"options":{"items":{"type":"string"},"type":"array","maxItems":12,"title":"Options","description":"Candidate answers for `multiple_choice` questions (optional; the model can infer them)."},"market_platform":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Market Platform","description":"Prediction market venue, e.g. `Polymarket`, `Kalshi`, `Manifold`, or `Metaculus`."},"market_url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Market Url","description":"URL for the prediction market being analyzed. Must start with `http://` or `https://`."},"market_outcome":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Market Outcome","description":"Outcome whose market-implied probability is provided. Defaults to `Yes` for binary markets; set this to `No` or to a multiple-choice option label when needed."},"market_ident":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Market Ident","description":"Venue market id (Polymarket slug / Kalshi ticker). Lets Foresea fetch live odds when `market_probability` is omitted."},"market_probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Probability","description":"Current market-implied probability for `market_outcome`. Use 0-1, or pass a percentage from 0-100 and Foresea will normalize it. When omitted but the market is identifiable (`market_url` or `market_platform`+`market_ident`), Foresea fetches the current live odds."},"openrouter_api_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Openrouter Api Key","description":"User-supplied OpenRouter API key. When set, this request is routed through OpenRouter using `openrouter_model` instead of the server's default provider."},"openrouter_model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Openrouter Model","description":"OpenRouter model ID (e.g. `openai/gpt-4o`, `anthropic/claude-3.5-sonnet`)."},"model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Model","description":"Optional alternate server-hosted model to forecast with, from the allowlist (`gpt-oss-120b`, `gemma-4-31b-it`, `kimi-k2.6`). Uses the server's own key — no BYOK needed. Powers the multi-model paper-trading comparison."},"provider_base_url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Provider Base Url","description":"Optional OpenAI-compatible chat-completions endpoint (e.g. `https://api.openai.com/v1/chat/completions`). When set with `openrouter_api_key` + `openrouter_model`, the request goes to your own endpoint instead of OpenRouter. Must be public HTTPS."},"chat_mode":{"type":"boolean","title":"Chat Mode","description":"When `true`, skips the forecast output template entirely. The model responds in plain natural language with no structured JSON.","default":false},"ollama_base_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Ollama Base Url","description":"Base URL of an Ollama instance, e.g. `http://localhost:11434`. No API key required. Cloud-metadata hosts are blocked; for foresea.ink the instance must be reachable from the server."}},"type":"object","required":["question"],"title":"PredictRequest","description":"Input payload for a single forecasting prediction.","examples":[{"market_platform":"Polymarket","market_probability":0.54,"question":"Will the Federal Reserve cut interest rates at least once before the end of 2025?","question_type":"binary"},{"options":["Max Verstappen","Lando Norris","Charles Leclerc","Lewis Hamilton","Other"],"question":"Who will win the 2026 Formula 1 drivers championship?","question_type":"multiple_choice"},{"categories":["Economics","United States"],"question":"What will US CPI inflation be in December 2026?","question_type":"numeric","resolution_criteria":"Use the year-over-year CPI-U inflation rate for December 2026."}]},"PredictResponse":{"properties":{"question_type":{"type":"string","title":"Question Type","description":"Detected type: `binary`, `multiple_choice`, `numeric`, or `date`.","default":"binary"},"predicted_answer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Predicted Answer","description":"Headline answer: Yes/No, the top option, or the median estimate."},"confidence":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Confidence","description":"Confidence in the headline answer (binary/MC). Null for numeric."},"options":{"items":{"$ref":"#/components/schemas/OptionProb"},"type":"array","title":"Options","description":"Per-option probabilities for `multiple_choice`."},"range_forecast":{"anyOf":[{"$ref":"#/components/schemas/RangeForecast"},{"type":"null"}],"description":"p10/p50/p90 estimate for `numeric` and `date`."},"rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rationale","description":"2–4 sentence explanation of the prediction."},"model_rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Rationale","description":"Raw rationale as returned by the model (may differ from `rationale` after post-processing)."},"variant":{"type":"string","title":"Variant","description":"Prompt variant used for this prediction."},"model_key":{"type":"string","title":"Model Key","description":"Model identifier (e.g. `gpt-oss-120b`)."},"evidence_sources":{"items":{"$ref":"#/components/schemas/EvidenceSource"},"type":"array","title":"Evidence Sources","description":"Deduplicated citations used as evidence."},"evidence_articles":{"items":{"$ref":"#/components/schemas/NewsArticle"},"type":"array","title":"Evidence Articles","description":"Full evidence articles passed to the model."},"evidence_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evidence Error","description":"Non-null if evidence retrieval failed (prediction still returned)."},"market_analysis":{"anyOf":[{"$ref":"#/components/schemas/MarketAnalysis"},{"type":"null"}],"description":"Optional comparison against a supplied prediction-market probability."}},"type":"object","required":["variant","model_key"],"title":"PredictResponse","description":"Prediction result for a single forecasting question.","example":{"confidence":0.72,"evidence_articles":[],"evidence_sources":[{"publish_date":"2025-01-15T10:30:00Z","relevance_score":0.91,"source":"Reuters","title":"Fed signals rate cuts may slow in 2025","url":"https://reuters.com/example"}],"market_analysis":{"edge":0.18,"market_probability":0.54,"market_url":"https://polymarket.com/event/example","model_probability":0.72,"outcome":"Yes","platform":"Polymarket","stance":"model_above_market","summary":"Foresea is 18 percentage points above the market on Yes."},"model_key":"gpt-oss-120b","model_rationale":"Current Fed guidance suggests rates will remain elevated through mid-2025.","options":[],"predicted_answer":"No","question_type":"binary","rationale":"Current Fed guidance suggests rates will remain elevated through mid-2025. Recent inflation data remains above the 2% target, reducing the likelihood of a cut in the near term. However, slowing economic growth introduces some downside risk that could prompt a cut by year-end.","variant":"variant0_neutral_baseline"}},"RagIngestRequest":{"properties":{"text":{"anyOf":[{"type":"string","maxLength":200000},{"type":"null"}],"title":"Text","description":"Raw text to ingest."},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Url","description":"URL to fetch and ingest."},"title":{"type":"string","maxLength":300,"title":"Title","default":""},"namespace":{"type":"string","maxLength":40,"title":"Namespace","description":"Corpus: 'kb', 'evidence', or 'forecasts'.","default":"kb"}},"type":"object","title":"RagIngestRequest","description":"Add a document to the user's knowledge base."},"RagSearchResult":{"properties":{"text":{"type":"string","title":"Text","default":""},"title":{"type":"string","title":"Title","default":""},"url":{"type":"string","title":"Url","default":""},"source":{"type":"string","title":"Source","default":""},"score":{"type":"number","title":"Score","default":0.0}},"type":"object","title":"RagSearchResult"},"RangeForecast":{"properties":{"p10":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"P10","description":"10th-percentile (low) estimate."},"p50":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"P50","description":"50th-percentile (median) estimate."},"p90":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"P90","description":"90th-percentile (high) estimate."},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit","description":"Unit of the estimate, e.g. 'USD', '%', 'people'."}},"type":"object","title":"RangeForecast","description":"A numeric or date estimate expressed as percentile bounds."},"RegisterRequest":{"properties":{"email":{"type":"string","maxLength":254,"title":"Email","description":"Account email address."},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password","description":"At least 8 characters."},"name":{"type":"string","maxLength":120,"title":"Name","description":"Optional display name.","default":""}},"type":"object","required":["email","password"],"title":"RegisterRequest","description":"Email + password sign-up submitted by the browser."},"ScanOpportunity":{"properties":{"question":{"type":"string","title":"Question"},"market_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market Url"},"outcome":{"type":"string","title":"Outcome","default":"Yes"},"market_probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Market Probability"},"model_probability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Model Probability"},"edge":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Edge"},"stance":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stance"},"recommendation":{"type":"string","title":"Recommendation"}},"type":"object","required":["question","recommendation"],"title":"ScanOpportunity","description":"One mispriced market found by the scan agent."},"SessionResponse":{"properties":{"token":{"type":"string","title":"Token"},"user_id":{"type":"string","title":"User Id"},"email":{"type":"string","title":"Email"},"name":{"type":"string","title":"Name"},"picture":{"type":"string","title":"Picture"}},"type":"object","required":["token","user_id","email","name","picture"],"title":"SessionResponse","description":"Issued after a successful Google sign-in."},"TradeOrderPreviewResponse":{"properties":{"ok":{"type":"boolean","title":"Ok"},"platform":{"type":"string","title":"Platform"},"would_execute":{"type":"boolean","title":"Would Execute"},"requires_confirmation":{"type":"boolean","title":"Requires Confirmation"},"confirmation_phrase":{"type":"string","title":"Confirmation Phrase"},"trading_enabled":{"type":"boolean","title":"Trading Enabled"},"max_order_notional":{"type":"number","title":"Max Order Notional"},"estimated_notional":{"type":"number","title":"Estimated Notional"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"},"normalized_order":{"additionalProperties":true,"type":"object","title":"Normalized Order"}},"type":"object","required":["ok","platform","would_execute","requires_confirmation","confirmation_phrase","trading_enabled","max_order_notional","estimated_notional","normalized_order"],"title":"TradeOrderPreviewResponse"},"TradeOrderRequest":{"properties":{"platform":{"type":"string","maxLength":20,"title":"Platform","description":"`kalshi` or `polymarket`."},"action":{"type":"string","maxLength":10,"title":"Action","description":"`buy` or `sell`.","default":"buy"},"outcome":{"type":"string","maxLength":10,"title":"Outcome","description":"Outcome side: `yes` or `no`.","default":"yes"},"order_type":{"type":"string","maxLength":20,"title":"Order Type","description":"`limit` or `market`.","default":"limit"},"price":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Price","description":"Limit price, or worst acceptable price for market/IOC-style orders."},"quantity":{"type":"number","exclusiveMinimum":0.0,"title":"Quantity","description":"Contracts/shares. For Polymarket market-buy, max_cost may define spend."},"max_cost":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Max Cost","description":"Polymarket market-buy spend cap in USD."},"ticker":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Ticker","description":"Kalshi market ticker."},"token_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Token Id","description":"Polymarket CLOB outcome token id."},"slug":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Slug","description":"Polymarket market slug for token resolution."},"market_id":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Market Id","description":"Polymarket market id for token resolution."},"time_in_force":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Time In Force","description":"Venue-specific TIF, e.g. GTC/FOK or good_till_canceled."},"post_only":{"type":"boolean","title":"Post Only","description":"Reject rather than cross the book when supported.","default":false},"reduce_only":{"type":"boolean","title":"Reduce Only","description":"Kalshi reduce-only flag.","default":false},"tick_size":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Tick Size","description":"Polymarket tick size override."},"neg_risk":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Neg Risk","description":"Polymarket negative-risk market flag."},"client_order_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Client Order Id","description":"Caller-provided idempotency/order id."},"cancel_order_on_pause":{"type":"boolean","title":"Cancel Order On Pause","description":"Kalshi cancel-on-pause flag.","default":false},"subaccount":{"anyOf":[{"type":"integer","maximum":32.0,"minimum":0.0},{"type":"null"}],"title":"Subaccount","description":"Kalshi subaccount number."},"exchange_index":{"type":"integer","minimum":0.0,"title":"Exchange Index","description":"Kalshi exchange shard index; currently 0.","default":0},"execute":{"type":"boolean","title":"Execute","description":"Must be true on `/trading/orders` for live execution.","default":false},"confirmation":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Confirmation","description":"Must equal the server confirmation phrase."},"venue_credentials":{"anyOf":[{"$ref":"#/components/schemas/VenueCredentials"},{"type":"null"}],"description":"Own-account credentials to sign with; transient, never stored. Falls back to the server account when omitted."}},"type":"object","required":["platform","quantity"],"title":"TradeOrderRequest","description":"A guarded prediction-market order request.\n\n`/trading/preview` validates this without execution. `/trading/orders` only\nsubmits when `execute=true`, the confirmation phrase is exact, and server\nlive-trading env flags are enabled."},"TradeOrderResponse":{"properties":{"ok":{"type":"boolean","title":"Ok"},"platform":{"type":"string","title":"Platform"},"would_execute":{"type":"boolean","title":"Would Execute"},"requires_confirmation":{"type":"boolean","title":"Requires Confirmation"},"confirmation_phrase":{"type":"string","title":"Confirmation Phrase"},"trading_enabled":{"type":"boolean","title":"Trading Enabled"},"max_order_notional":{"type":"number","title":"Max Order Notional"},"estimated_notional":{"type":"number","title":"Estimated Notional"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"},"normalized_order":{"additionalProperties":true,"type":"object","title":"Normalized Order"},"submitted":{"type":"boolean","title":"Submitted"},"user_id":{"type":"string","title":"User Id"},"venue_response":{"additionalProperties":true,"type":"object","title":"Venue Response"}},"type":"object","required":["ok","platform","would_execute","requires_confirmation","confirmation_phrase","trading_enabled","max_order_notional","estimated_notional","normalized_order","submitted","user_id","venue_response"],"title":"TradeOrderResponse"},"TradingAccountCheckRequest":{"properties":{"venue_credentials":{"anyOf":[{"$ref":"#/components/schemas/VenueCredentials"},{"type":"null"}]}},"type":"object","title":"TradingAccountCheckRequest","description":"Validate own-account credentials without persisting them."},"TradingAccountStatus":{"properties":{"trading_enabled":{"type":"boolean","title":"Trading Enabled"},"byo_trading_enabled":{"type":"boolean","title":"Byo Trading Enabled","default":false},"max_order_notional":{"type":"number","title":"Max Order Notional"},"allow_market_orders":{"type":"boolean","title":"Allow Market Orders"},"confirmation_phrase":{"type":"string","title":"Confirmation Phrase"},"credential_source":{"type":"string","title":"Credential Source"},"venues":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Venues"}},"type":"object","required":["trading_enabled","max_order_notional","allow_market_orders","confirmation_phrase","credential_source","venues"],"title":"TradingAccountStatus","description":"Trading readiness without exposing exchange secrets."},"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"},"VenueCredentials":{"properties":{"kalshi_api_key_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Kalshi Api Key Id"},"kalshi_private_key":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}],"title":"Kalshi Private Key","description":"RSA private key PEM."},"kalshi_base_url":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Kalshi Base Url"},"polymarket_private_key":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Polymarket Private Key","description":"Wallet private key."},"polymarket_api_key":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Polymarket Api Key"},"polymarket_api_secret":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Polymarket Api Secret"},"polymarket_api_passphrase":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Polymarket Api Passphrase"},"polymarket_clob_host":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Polymarket Clob Host"},"polymarket_chain_id":{"anyOf":[{"type":"integer","maximum":1000000000.0,"minimum":0.0},{"type":"null"}],"title":"Polymarket Chain Id"},"polymarket_signature_type":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":0.0},{"type":"null"}],"title":"Polymarket Signature Type"},"polymarket_funder_address":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Polymarket Funder Address"}},"type":"object","title":"VenueCredentials","description":"Bring-your-own venue credentials supplied per request.\n\nThese let a signed-in user trade their OWN Kalshi/Polymarket account. They are\nused transiently to sign a single order and are NEVER persisted, logged, or\nechoed back. When omitted, the server falls back to its shared-account env vars."},"VisitRequest":{"properties":{"path":{"type":"string","maxLength":500,"title":"Path","default":"/"},"referrer":{"type":"string","maxLength":2000,"title":"Referrer","default":""},"timezone":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Timezone"}},"type":"object","title":"VisitRequest","description":"Anonymous browser visit event."}}},"tags":[{"name":"Inference","description":"Run forecast and market-edge analysis for binary, multiple-choice, numeric, and date questions."},{"name":"Markets","description":"Fetch live prices from prediction-market venues (Polymarket, Kalshi)."},{"name":"Trading","description":"Preview and submit guarded prediction-market orders for authenticated users."},{"name":"Agents","description":"Autonomous analysis: orchestrate market fetch, evidence, forecast, edge, and custom skills into one report."},{"name":"Knowledge","description":"Per-user RAG knowledge base: ingest documents and retrieve them as evidence."},{"name":"System","description":"Health and liveness checks."}]}