{
  "openapi": "3.1.0",
  "info": {
    "title": "SimpleFunctions",
    "version": "1.0.0",
    "description": "Context flow for prediction markets — perception to execution. Live contract prices, causal reasoning, edge detection, automated trading strategies with hard/soft conditions, and 24/7 monitoring via heartbeat engine. Use when users ask about probabilities, predictions, future events, or prediction market trading."
  },
  "servers": [
    { "url": "https://simplefunctions.dev" }
  ],
  "paths": {
    "/api/agent/world": {
      "get": {
        "operationId": "getWorldState",
        "summary": "Salience-ranked snapshot of prediction market state (SPEC-10). Self-similar Snapshot shape at every depth. 6 composable ops — drill (path), trail, dispersion, history, catalyst, explain. Each salient item carries 2-3 per-item pull threads for next call.",
        "parameters": [
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["markdown", "json"], "default": "markdown" } },
          { "name": "op", "in": "query", "schema": { "type": "string", "enum": ["snapshot", "history", "catalyst", "dispersion", "trail", "explain"], "default": "snapshot" }, "description": "View mode. snapshot (default) — salience-ranked tiles. history — index/regime timeline. catalyst — upcoming resolutions. dispersion — intra-region consensus breakdown. trail — walk linkage graph from `from=<ticker>`. explain — hypothesis candidates for `item=<id>`." },
          { "name": "dt", "in": "query", "schema": { "type": "string" }, "description": "Time window for op=history/catalyst, e.g. 6h, 24h, 7d. Defaults: history 24h, catalyst 7d." },
          { "name": "since", "in": "query", "schema": { "type": "string" }, "description": "Comparison baseline override. Relative (12h, 3d) or ISO. Default: max(12h ago, midnight UTC)." },
          { "name": "depth", "in": "query", "schema": { "type": "integer", "minimum": 0, "maximum": 3, "default": 1 }, "description": "How many levels of childRegions to expand inline." },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 30, "default": 10 }, "description": "Max salient items in response." },
          { "name": "from", "in": "query", "schema": { "type": "string" }, "description": "Source ticker for op=trail (walks linkage graph: cross-venue, contagion, series siblings)." },
          { "name": "item", "in": "query", "schema": { "type": "string" }, "description": "Salient item id for op=explain. Ids are stable within the 5-min cache window." },
          { "name": "focus", "in": "query", "schema": { "type": "string" }, "description": "Legacy: single topic → path-based drill (e.g. focus=iran → /api/agent/world/iran). Use the path form directly for new integrations." }
        ],
        "responses": { "200": { "description": "Snapshot as markdown (default) or JSON. JSON shape: { asOf, sinceBaseline, regime: { label, signals: { disagreement, geoRisk, breadth, activity } }, salient: [ { id, type, rank, label, body, pull: [ { op, url, ... } ] } ], childRegions?, op }. Legacy aliases (index, regimeSummary, movers, opportunities, divergences, traditional) also present for pre-SPEC-10 consumers." } }
      }
    },
    "/api/agent/world/{topic}": {
      "get": {
        "operationId": "getWorldDrill",
        "summary": "Drill into a topic region. Same Snapshot shape as /api/agent/world, scoped to that topic's markets. Path extends the hierarchy — /api/agent/world/iran/hormuz is a valid deeper drill.",
        "parameters": [
          { "name": "topic", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Topic key: iran, oil, fed-rate, recession, election-2026, bitcoin, ukraine, china, trump, ai-tech. Meta groups: geopolitics, economy, energy, crypto, tech, politics. Unknown segments become keyword filters." },
          { "name": "op", "in": "query", "schema": { "type": "string", "enum": ["snapshot", "history", "catalyst", "dispersion", "trail", "explain"], "default": "snapshot" } },
          { "name": "dt", "in": "query", "schema": { "type": "string" } },
          { "name": "since", "in": "query", "schema": { "type": "string" } },
          { "name": "depth", "in": "query", "schema": { "type": "integer", "minimum": 0, "maximum": 3, "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 30, "default": 10 } },
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["markdown", "json"], "default": "markdown" } }
        ],
        "responses": { "200": { "description": "Snapshot scoped to the drilled region. Same JSON shape as /api/agent/world." } }
      }
    },
    "/api/agent/world/delta": {
      "get": {
        "operationId": "getWorldDelta",
        "summary": "Incremental world state update. Returns only what changed since timestamp — typically 30-50 tokens vs 800 for full state. For long-running agents.",
        "parameters": [
          { "name": "since", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Relative (1h, 6h, 24h) or ISO timestamp" },
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["markdown", "json"], "default": "markdown" } }
        ],
        "responses": { "200": { "description": "Delta markdown or JSON with changes array" } }
      }
    },
    "/api/agent/world/feed": {
      "get": {
        "operationId": "getWorldFeed",
        "summary": "Streaming world state feed via Server-Sent Events. Pushes incremental updates as they happen — no polling needed. For agents that maintain a persistent connection.",
        "parameters": [],
        "responses": { "200": { "description": "SSE stream of world state updates" } }
      }
    },
    "/api/agent/inspect/{ticker}": {
      "get": {
        "operationId": "inspectTicker",
        "summary": "Complete ticker dossier: price, regime, indicators (IY/CRI/EE/LAS), thesis edges, contagion connections, 24h diff, 7d trend, and ACTIONABLE SUGGESTION (consider_long/short/wait/avoid/monitor). Use instead of getMarketDetail when you want a trading-oriented view with a recommendation.",
        "parameters": [
          { "name": "ticker", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Kalshi ticker or Polymarket conditionId" },
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["json", "markdown"], "default": "json" }, "description": "json = structured, markdown = human-readable dossier" },
          { "name": "contagion", "in": "query", "schema": { "type": "string", "enum": ["true", "false"], "default": "true" }, "description": "Include contagion connections from thesis causal graph" },
          { "name": "diff", "in": "query", "schema": { "type": "string", "enum": ["true", "false"], "default": "true" }, "description": "Include 24h price/volume diff" },
          { "name": "trend", "in": "query", "schema": { "type": "string", "enum": ["true", "false"], "default": "true" }, "description": "Include 7d IY/CRI trend" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": { "200": { "description": "Ticker inspection with suggestion, regime, indicators, edges, contagion, diff, trend" } }
      }
    },
    "/api/public/query": {
      "get": {
        "operationId": "query",
        "summary": "Ask any question about future events or probabilities. Returns live contract prices, X/Twitter sentiment, and an LLM-synthesized answer.",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Natural language query, e.g. 'fed rate cut probability'" },
          { "name": "mode", "in": "query", "schema": { "type": "string", "enum": ["raw", "full"], "default": "full" }, "description": "raw = data only, full = LLM synthesis included" },
          { "name": "sources", "in": "query", "schema": { "type": "string", "default": "kalshi,polymarket,x,content,traditional" }, "description": "Comma-separated data sources" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10, "maximum": 20 }, "description": "Max markets per venue" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": {
          "200": {
            "description": "Query results with live market data and LLM synthesis",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QueryResponse" } } }
          }
        }
      }
    },
    "/api/public/context": {
      "get": {
        "operationId": "getContext",
        "summary": "Global market intelligence snapshot: top edges, price movers, highlights, traditional markets. Updated every 15 min.",
        "parameters": [
          { "name": "compact", "in": "query", "schema": { "type": "boolean" }, "description": "true = edges + highlights + traditional only (7K vs 44K)" },
          { "name": "q", "in": "query", "schema": { "type": "string" }, "description": "Filter by keyword" }
        ],
        "responses": {
          "200": {
            "description": "Market intelligence snapshot",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContextResponse" } } }
          }
        }
      }
    },
    "/api/public/scan": {
      "get": {
        "operationId": "scanMarkets",
        "summary": "Cross-venue market search (Kalshi + Polymarket) with relevance ranking. Returns price, spread, volume for each market.",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Search keywords" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "maximum": 50 } },
          { "name": "venue", "in": "query", "schema": { "type": "string", "enum": ["kalshi", "polymarket"] }, "description": "Filter by venue" },
          { "name": "price_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum price filter (cents)" },
          { "name": "price_max", "in": "query", "schema": { "type": "number" }, "description": "Maximum price filter (cents)" },
          { "name": "vol_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum total volume filter" },
          { "name": "vol24h_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum 24h volume filter" },
          { "name": "expires_before", "in": "query", "schema": { "type": "string" }, "description": "ISO timestamp — only markets expiring before this date" },
          { "name": "expires_after", "in": "query", "schema": { "type": "string" }, "description": "ISO timestamp — only markets expiring after this date" },
          { "name": "include_subcent", "in": "query", "schema": { "type": "boolean" }, "description": "Include sub-cent markets (price < 1c)" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": {
          "200": { "description": "Ranked market results with price, spread, volume" }
        }
      }
    },
    "/api/public/market/{ticker}": {
      "get": {
        "operationId": "getMarketDetail",
        "summary": "Complete market profile: price, bid/ask, spread, volume, status, close time, description. Optional orderbook depth, thesis edges, regime diagnostics (AS score, label, signals), and cross-venue counterpart (Kalshi × Polymarket pair with configurable confidence threshold).",
        "parameters": [
          { "name": "ticker", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Kalshi ticker or Polymarket conditionId" },
          { "name": "depth", "in": "query", "schema": { "type": "boolean", "default": false }, "description": "Include 5-level orderbook depth" },
          { "name": "cv_preset", "in": "query", "schema": { "type": "string", "enum": ["arb", "world", "detail", "browse"], "default": "detail" }, "description": "Cross-venue counterpart filter preset. arb (conf≥0.80, |Δt|≤90d), world (conf≥0.75, |Δt|≤180d), detail (conf≥0.60, no dt cap), browse (conf≥0.50, no dt cap)." },
          { "name": "cv_min_conf", "in": "query", "schema": { "type": "number", "minimum": 0, "maximum": 1 }, "description": "Override preset's confidence floor. Example: 0.85 to see only very-high-confidence counterparts." },
          { "name": "cv_max_dt_days", "in": "query", "schema": { "type": "number" }, "description": "Override preset's close-time delta cap in days." }
        ],
        "responses": {
          "200": { "description": "Market detail with optional orderbook, thesis edges, regime, and `crossVenue` counterpart (null when filtered out)." }
        }
      }
    },
    "/api/public/market/{ticker}/history": {
      "get": {
        "operationId": "getMarketHistory",
        "summary": "Price history for a market ticker. Returns timestamped price series for charting or backtesting.",
        "parameters": [
          { "name": "ticker", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Kalshi ticker or Polymarket conditionId" }
        ],
        "responses": {
          "200": { "description": "Timestamped price history for the market" }
        }
      }
    },
    "/api/public/regime/scan": {
      "get": {
        "operationId": "scanRegime",
        "summary": "Scan markets by adverse selection regime. Real-time microstructure diagnostics: AS score (0-1), label (maker/taker/neutral), signal breakdown. Filter by score range, label, event type, venue.",
        "parameters": [
          { "name": "label", "in": "query", "schema": { "type": "string", "enum": ["maker", "taker", "neutral"] } },
          { "name": "as_min", "in": "query", "schema": { "type": "number", "minimum": 0, "maximum": 1 } },
          { "name": "as_max", "in": "query", "schema": { "type": "number", "minimum": 0, "maximum": 1 } },
          { "name": "venue", "in": "query", "schema": { "type": "string", "enum": ["kalshi", "polymarket"] } },
          { "name": "event_type", "in": "query", "schema": { "type": "string" }, "description": "data_release, political, financial, sports, weather, cultural, scientific" },
          { "name": "observability", "in": "query", "schema": { "type": "string", "enum": ["none", "low", "medium", "high", "direct"] } },
          { "name": "has_edge", "in": "query", "schema": { "type": "boolean" }, "description": "Only markets with SF thesis edge" },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["score", "edge", "spread", "volume", "catalyst"], "default": "score" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "maximum": 100 } }
        ],
        "responses": { "200": { "description": "Markets with regime scores, sorted and filtered" } }
      }
    },
    "/api/public/regime/history": {
      "get": {
        "operationId": "getRegimeHistory",
        "deprecated": true,
        "summary": "DEPRECATED (410 Gone). Use /api/public/market-microstructure-history instead for spread/depth time series, or /api/agent/inspect/{ticker} for a full trading dossier.",
        "parameters": [
          { "name": "ticker", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "410": { "description": "This endpoint is deprecated. Use /api/public/market-microstructure-history." } }
      }
    },
    "/api/public/index": {
      "get": {
        "operationId": "getMarketIndex",
        "summary": "SF Prediction Market Index v2 (2026-04-09). disagreement (median per-ticker realized vol, 0-100), geoRisk (theater-equal weighted curated geopolitical basket, 0-100, signed), breadth (up/down skew of |24h Δ| >= 10c, -1 to +1), activity (percentile rank vs trailing 30d, 0-100).",
        "parameters": [
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": { "200": { "description": "Latest index snapshot with components breakdown" } }
      }
    },
    "/api/public/index/history": {
      "get": {
        "operationId": "getIndexHistory",
        "summary": "SF Index historical data. Returns daily index snapshots for charting trends in disagreement, geoRisk, breadth, and activity.",
        "parameters": [
          { "name": "days", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 30, "default": 7 }, "description": "Number of days of history (1-30)" }
        ],
        "responses": { "200": { "description": "Array of daily index snapshots with component values" } }
      }
    },
    "/api/public/screen": {
      "get": {
        "operationId": "screenMarkets",
        "summary": "Indicator screener. Filter and sort markets by SF indicators (IY, EE, OR, LAS, CRI, tau) plus volume and price. For systematic scanning across the full universe.",
        "parameters": [
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["iy", "ee", "or", "las", "cri", "tau", "volume", "price"] }, "description": "Sort dimension" },
          { "name": "order", "in": "query", "schema": { "type": "string", "enum": ["asc", "desc"], "default": "desc" }, "description": "Sort order" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 }, "description": "Results per page" },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0 }, "description": "Pagination offset" },
          { "name": "keyword", "in": "query", "schema": { "type": "string" }, "description": "Filter by keyword in market title" },
          { "name": "venue", "in": "query", "schema": { "type": "string", "enum": ["kalshi", "polymarket"] }, "description": "Filter by venue" },
          { "name": "iy_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum implied yield" },
          { "name": "iy_max", "in": "query", "schema": { "type": "number" }, "description": "Maximum implied yield" },
          { "name": "ee_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum executable edge" },
          { "name": "las_max", "in": "query", "schema": { "type": "number" }, "description": "Maximum liquidity-adjusted spread" },
          { "name": "or_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum odds ratio" },
          { "name": "or_max", "in": "query", "schema": { "type": "number" }, "description": "Maximum odds ratio" },
          { "name": "cri_min", "in": "query", "schema": { "type": "number" }, "description": "Minimum catalyst-regime indicator" },
          { "name": "cri_max", "in": "query", "schema": { "type": "number" }, "description": "Maximum catalyst-regime indicator" },
          { "name": "tau_min_days", "in": "query", "schema": { "type": "number" }, "description": "Minimum time to expiry in days" },
          { "name": "tau_max_days", "in": "query", "schema": { "type": "number" }, "description": "Maximum time to expiry in days" },
          { "name": "has_thesis", "in": "query", "schema": { "type": "boolean" }, "description": "Only markets with an SF thesis" },
          { "name": "has_orderbook", "in": "query", "schema": { "type": "boolean" }, "description": "Only markets with live orderbook data" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": { "200": { "description": "Screened markets with indicator values, sorted and filtered" } }
      }
    },
    "/api/public/screen-by-tickers": {
      "get": {
        "operationId": "screenByTickers",
        "summary": "Screen specific tickers. Same indicator data as /screen but for a known set of tickers — skips the search/filter step.",
        "parameters": [
          { "name": "tickers", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Comma-separated list of Kalshi tickers or Polymarket conditionIds" }
        ],
        "responses": { "200": { "description": "Indicator data for the requested tickers" } }
      }
    },
    "/api/public/newmarkets": {
      "get": {
        "operationId": "getNewMarkets",
        "summary": "Recently listed markets. Surfaces newly created contracts across venues — useful for spotting opportunities before the crowd.",
        "parameters": [
          { "name": "hours", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 720, "default": 24 }, "description": "Lookback window in hours" },
          { "name": "venue", "in": "query", "schema": { "type": "string", "enum": ["kalshi", "polymarket", "all"], "default": "all" }, "description": "Filter by venue" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200 }, "description": "Max results" },
          { "name": "min_liquidity", "in": "query", "schema": { "type": "number" }, "description": "Minimum liquidity threshold" }
        ],
        "responses": { "200": { "description": "Recently listed markets with price, volume, venue, and listing time" } }
      }
    },
    "/api/public/yield-curves": {
      "get": {
        "operationId": "getYieldCurves",
        "summary": "Calendar yield curves. Shows term structure of prediction market contracts across expiry dates — reveals market expectations over time.",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer" }, "description": "Max number of yield curves to return" },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["default", "points_desc", "volume_desc"] }, "description": "Sort order for results" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": { "200": { "description": "Yield curves with contract points across expiry dates" } }
      }
    },
    "/api/public/yield-curves/{event}": {
      "get": {
        "operationId": "getYieldCurveDetail",
        "summary": "Single yield curve detail with narrative. Full term structure for one event plus LLM-generated interpretation of what the curve shape implies.",
        "parameters": [
          { "name": "event", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Event identifier for the yield curve" }
        ],
        "responses": { "200": { "description": "Yield curve detail with points, narrative, and metadata" } }
      }
    },
    "/api/public/highlights": {
      "get": {
        "operationId": "getHighlights",
        "summary": "Today's highlights and headlines. Curated top stories across prediction markets — biggest movers, notable settlements, emerging themes.",
        "parameters": [],
        "responses": { "200": { "description": "Today's market highlights and headlines" } }
      }
    },
    "/api/public/calendar": {
      "get": {
        "operationId": "getCalendar",
        "summary": "Event calendar. Upcoming catalysts, data releases, and scheduled events that could move prediction markets.",
        "parameters": [],
        "responses": { "200": { "description": "Upcoming events with dates, categories, and affected markets" } }
      }
    },
    "/api/public/databento": {
      "get": {
        "operationId": "getDatabento",
        "summary": "Traditional market real-time prices via Databento. SPY, VIX, Gold, Oil, Treasuries — same data as /markets but from the Databento feed.",
        "parameters": [],
        "responses": { "200": { "description": "Real-time traditional market prices from Databento" } }
      }
    },
    "/api/public/market-microstructure-history": {
      "get": {
        "operationId": "getMarketMicrostructureHistory",
        "summary": "Spread and depth time series for a market. Historical microstructure data — bid/ask spread, orderbook depth, and liquidity metrics over time.",
        "parameters": [
          { "name": "ticker", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Kalshi ticker or Polymarket conditionId" }
        ],
        "responses": { "200": { "description": "Time series of spread, depth, and liquidity metrics" } }
      }
    },
    "/api/public/contagion": {
      "get": {
        "operationId": "getContagion",
        "summary": "Cross-market contagion detection. Finds markets that moved, then checks causally connected markets for lagging response. Gap = potential edge.",
        "parameters": [
          { "name": "window", "in": "query", "schema": { "type": "string", "default": "6h" }, "description": "Time window: 1h, 6h, 24h, 3d" },
          { "name": "topic", "in": "query", "schema": { "type": "string" }, "description": "Filter by topic (iran, oil, fed, etc)" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": { "200": { "description": "Trigger markets with lagging connected markets and gap sizes" } }
      }
    },
    "/api/public/diff": {
      "get": {
        "operationId": "getMarketDiff",
        "summary": "Market derivatives over time: price/volume/spread/depth deltas between two timestamps. Detects divergence signals (volume spike + flat price, liquidity exit, etc).",
        "parameters": [
          { "name": "tickers", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated tickers (or use topic param)" },
          { "name": "topic", "in": "query", "schema": { "type": "string" }, "description": "Topic keyword to auto-resolve tickers (e.g. iran, oil, fed)" },
          { "name": "window", "in": "query", "schema": { "type": "string", "default": "24h" }, "description": "Time window: 1h, 6h, 24h, 3d, 1w" },
          { "name": "from", "in": "query", "schema": { "type": "string" }, "description": "ISO timestamp start (overrides window)" },
          { "name": "to", "in": "query", "schema": { "type": "string" }, "description": "ISO timestamp end (default: now)" },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["priceDelta", "volumeDelta", "spreadDelta", "signals"] }, "description": "Sort by dimension" }
        ],
        "responses": { "200": { "description": "Per-ticker diffs with velocity, divergence signals, and summary stats" } }
      }
    },
    "/api/public/briefing": {
      "get": {
        "operationId": "getBriefing",
        "summary": "Daily topic briefing: what changed today, key movers, X sentiment, outlook. LLM-synthesized, cached 1h.",
        "parameters": [
          { "name": "topic", "in": "query", "schema": { "type": "string", "enum": ["iran", "oil", "fed", "economy", "elections", "crypto", "china", "ukraine", "tech", "climate"] } },
          { "name": "window", "in": "query", "schema": { "type": "string", "default": "24h" }, "description": "Time window: 6h, 12h, 24h, 3d" }
        ],
        "responses": { "200": { "description": "Structured briefing with headline, summary, key moves, sentiment, outlook" } }
      }
    },
    "/api/changes": {
      "get": {
        "operationId": "getChanges",
        "summary": "What changed recently? Price moves >5c, new contracts, settlements. Scanned every 15 min.",
        "parameters": [
          { "name": "since", "in": "query", "schema": { "type": "string" }, "description": "ISO timestamp (default: 1 hour ago)" },
          { "name": "q", "in": "query", "schema": { "type": "string" }, "description": "Filter by keyword" },
          { "name": "type", "in": "query", "schema": { "type": "string", "enum": ["new_contract", "price_move", "removed_contract"] } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 100, "maximum": 500 } }
        ],
        "responses": {
          "200": { "description": "Market change events" }
        }
      }
    },
    "/api/changes/annotated": {
      "get": {
        "operationId": "getAnnotatedChanges",
        "summary": "Changes grouped by topic with LLM annotation. Same underlying data as /changes but clustered into coherent narratives with context on why things moved.",
        "parameters": [],
        "responses": { "200": { "description": "Topic-grouped changes with LLM-generated annotations and context" } }
      }
    },
    "/api/public/trad-markets": {
      "get": {
        "operationId": "getTraditionalMarkets",
        "summary": "Traditional market prices: SPY, VIX, Gold, Oil, Treasuries via Databento. Renamed from /api/public/markets on 2026-04-17.",
        "parameters": [
          { "name": "topic", "in": "query", "required": false, "schema": { "type": "string", "enum": ["energy", "rates", "fx", "equities", "crypto", "volatility"] } }
        ],
        "responses": {
          "200": { "description": "Traditional market snapshot" }
        }
      }
    },
    "/api/public/markets": {
      "get": {
        "operationId": "getBatchMarkets",
        "summary": "Batch prediction-market detail query (Kalshi + Polymarket, max 20 tickers per request).",
        "parameters": [
          { "name": "tickers", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Comma-separated tickers, max 20" },
          { "name": "depth", "in": "query", "required": false, "schema": { "type": "boolean" } }
        ],
        "responses": {
          "200": { "description": "Per-ticker market detail array" },
          "400": { "description": "Missing tickers parameter — use /api/public/trad-markets for traditional markets" }
        }
      }
    },
    "/api/public/theses": {
      "get": {
        "operationId": "exploreTheses",
        "summary": "Browse public prediction market theses with live edges and track records.",
        "responses": {
          "200": { "description": "List of public theses" }
        }
      }
    },
    "/api/public/thesis/{slug}": {
      "get": {
        "operationId": "getThesis",
        "summary": "Full public thesis detail: causal tree, edges, evaluation history, implied returns.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Thesis detail" }
        }
      }
    },
    "/api/public/cross-venue/pairs": {
      "get": {
        "operationId": "getCrossVenuePairs",
        "summary": "Paginated list of Kalshi × Polymarket market pairs with LLM-verified event matching. Use presets for common precision/recall tradeoffs or override with explicit filters. Powers arb surfacing, agent world-state enrichment, and UI counterpart rendering.",
        "parameters": [
          { "name": "preset", "in": "query", "schema": { "type": "string", "enum": ["arb", "world", "detail", "browse"] }, "description": "arb (conf≥0.80, |Δt|≤90d, precision-first). world (conf≥0.75, |Δt|≤180d, agent context). detail (conf≥0.60, lenient). browse (conf≥0.50, permissive). Explicit params override preset defaults." },
          { "name": "min_conf", "in": "query", "schema": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.60 }, "description": "Minimum LLM confidence score." },
          { "name": "max_dt_days", "in": "query", "schema": { "type": "number" }, "description": "Max |close_time_delta| in days. Omit for no cap." },
          { "name": "method", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated match methods: structural, fts-llm, llm-fallback, fuzzy-outcome." },
          { "name": "category", "in": "query", "schema": { "type": "string" }, "description": "Kalshi-side event category filter, e.g. Economics, Politics, Sports." },
          { "name": "ticker", "in": "query", "schema": { "type": "string" }, "description": "Filter to pairs containing this ticker on either side." },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } },
          { "name": "order_by", "in": "query", "schema": { "type": "string", "enum": ["confidence_desc", "dt_asc", "recent"], "default": "confidence_desc" }, "description": "confidence_desc — highest confidence first. dt_asc — smallest close-time gap first. recent — most recently verified first." }
        ],
        "responses": {
          "200": { "description": "{ generatedAt, filter, presets, total, limit, offset, pairs: [ { kalshiTicker, polyTicker, confidenceScore, matchMethod, direction, closeTimeDeltaSec, kalshiTitle, polyTitle, llmRationale, kalshiEventKey, polyEventKey, lastVerified, isArbReady } ] }. isArbReady is derived: confidenceScore≥0.75 AND |closeTimeDeltaSec|≤90d." }
        }
      }
    },
    "/api/public/cross-venue/stats": {
      "get": {
        "operationId": "getCrossVenueStats",
        "summary": "Cross-venue pair matching coverage statistics. Includes confidence histogram with per-bucket arb-ready fraction for threshold tuning.",
        "parameters": [],
        "responses": {
          "200": { "description": "{ generatedAt, totalPairs, lastBuiltAt, eventsByVenue, byMatchMethod, byConfidenceBucket, confidenceHistogram: [ { bucket, count, arbReady, pArbReady } ], byCategory }." }
        }
      }
    },
    "/api/public/ideas": {
      "get": {
        "operationId": "getTradeIdeas",
        "summary": "S&T-style trade ideas: actionable pitches from market data, edges, macro context. Conviction level, catalyst, direction, risk. No auth.",
        "parameters": [
          { "name": "freshness", "in": "query", "schema": { "type": "string", "enum": ["1h", "6h", "12h"], "default": "12h" } },
          { "name": "category", "in": "query", "schema": { "type": "string", "enum": ["macro", "geopolitics", "crypto", "policy", "event"] } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 5, "maximum": 10 } },
          { "name": "q", "in": "query", "schema": { "type": "string" }, "description": "On-demand idea generation for a specific query" },
          { "name": "nextActions", "in": "query", "schema": { "type": "string", "enum": ["off"] }, "description": "Set to 'off' to omit nextActions from response" }
        ],
        "responses": { "200": { "description": "Trade ideas with conviction and catalysts" } }
      }
    },
    "/api/public/ideas/{id}": {
      "get": {
        "operationId": "getTradeIdea",
        "summary": "Single trade idea by ID. Full detail including reasoning, catalyst timeline, risk factors, and related markets.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Trade idea ID" }
        ],
        "responses": { "200": { "description": "Full trade idea detail" } }
      }
    },
    "/api/public/search": {
      "get": {
        "operationId": "search",
        "summary": "Full-text site search. Searches across markets, theses, opinions, glossary, and other content. Returns ranked results with snippets.",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Search query" }
        ],
        "responses": { "200": { "description": "Search results with type, title, snippet, and URL" } }
      }
    },
    "/api/calibration": {
      "get": {
        "operationId": "getCalibration",
        "summary": "Prediction market calibration metrics. Brier scores computed from prices 24h before resolution (t-24h) across Polymarket and Kalshi settled markets.",
        "parameters": [
          { "name": "source", "in": "query", "schema": { "type": "string", "enum": ["marketwide", "sf"], "default": "marketwide" }, "description": "Data source: marketwide (Polymarket+Kalshi resolutions) or sf (thesis-driven)" },
          { "name": "period", "in": "query", "schema": { "type": "string", "enum": ["7d", "30d", "90d", "all"], "default": "all" }, "description": "Time window filter" },
          { "name": "category", "in": "query", "schema": { "type": "string" }, "description": "Filter by category substring" },
          { "name": "min_volume", "in": "query", "schema": { "type": "integer", "default": 0 }, "description": "Minimum volume threshold" }
        ],
        "responses": { "200": { "description": "Calibration metrics: t-24h Brier score (primary), settlement baseline (comparison), calibration curve by price decile, breakdowns by venue and category" } }
      }
    },
    "/api/public/opinions": {
      "get": {
        "operationId": "getOpinions",
        "summary": "Opinion articles list. Long-form prediction market analysis and commentary.",
        "parameters": [],
        "responses": { "200": { "description": "List of opinion articles with title, slug, date, and excerpt" } }
      }
    },
    "/api/public/opinions/{slug}": {
      "get": {
        "operationId": "getOpinion",
        "summary": "Single opinion article. Full content with metadata, related markets, and author.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Opinion article slug" }
        ],
        "responses": { "200": { "description": "Full opinion article content" } }
      }
    },
    "/api/public/technicals": {
      "get": {
        "operationId": "getTechnicals",
        "summary": "Technical analysis articles list. Quantitative market structure analysis and pattern breakdowns.",
        "parameters": [],
        "responses": { "200": { "description": "List of technical articles with title, slug, date, and excerpt" } }
      }
    },
    "/api/public/technicals/{slug}": {
      "get": {
        "operationId": "getTechnical",
        "summary": "Single technical analysis article. Full content with charts, data, and methodology.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Technical article slug" }
        ],
        "responses": { "200": { "description": "Full technical article content" } }
      }
    },
    "/api/public/glossary": {
      "get": {
        "operationId": "getGlossary",
        "summary": "Glossary entries list. Prediction market terminology, SF-specific indicators, and trading concepts defined.",
        "parameters": [],
        "responses": { "200": { "description": "List of glossary entries with term, slug, and short definition" } }
      }
    },
    "/api/public/glossary/{slug}": {
      "get": {
        "operationId": "getGlossaryEntry",
        "summary": "Single glossary entry. Full definition with examples, related terms, and usage context.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Glossary entry slug" }
        ],
        "responses": { "200": { "description": "Full glossary entry with definition and examples" } }
      }
    },
    "/api/public/skills": {
      "get": {
        "operationId": "getPublicSkills",
        "summary": "Agent cognitive skills and workflows. Reusable prompts and reasoning patterns that make agents more disciplined at prediction market analysis.",
        "parameters": [],
        "responses": { "200": { "description": "List of available agent skills with name, slug, and description" } }
      }
    },
    "/api/public/skill/{slug}": {
      "get": {
        "operationId": "getPublicSkill",
        "summary": "Single skill detail. Full prompt, usage instructions, and example invocations for one cognitive workflow.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Skill slug" }
        ],
        "responses": { "200": { "description": "Full skill detail with prompt, instructions, and examples" } }
      }
    },
    "/api/public/topic/{slug}": {
      "get": {
        "operationId": "getTopic",
        "summary": "Topic landing page data. Aggregated view for a topic — related markets, theses, opinions, recent changes, and current state.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Topic slug (e.g. iran, fed, crypto)" }
        ],
        "responses": { "200": { "description": "Topic page data with related markets, content, and summary" } }
      }
    },
    "/api/edges": {
      "get": {
        "operationId": "getEdges",
        "summary": "Aggregated edges across all theses, sorted by |executableEdge|. Enriched with status, expiresAt, volume24h, depth, reasoning, causalPath, absorption, fees. All prices float cents 0-100.",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } },
          { "name": "minEdge", "in": "query", "schema": { "type": "integer", "default": 3 }, "description": "Minimum |executableEdge| in cents" },
          { "name": "venue", "in": "query", "schema": { "type": "string", "enum": ["kalshi", "polymarket"] } },
          { "name": "include_closed", "in": "query", "schema": { "type": "boolean", "default": false } }
        ],
        "responses": { "200": { "description": "Enriched edges with priceUnit, status, expiresAt, volume24h, bidDepthUsd, askDepthUsd, reasoning, causalPath, edgeDiscoveredAt, edgeAgeHours, priceAtDiscovery, marketAbsorption, feeAssumption, tickerAlt" } }
      }
    },
    "/api/intents": {
      "post": {
        "operationId": "createIntent",
        "summary": "Declare execution intent with trigger conditions. Runtime daemon evaluates and executes.",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["action", "venue", "marketId", "marketTitle", "direction", "targetQuantity"] } } } },
        "responses": { "201": { "description": "Intent created" } }
      },
      "get": {
        "operationId": "listIntents",
        "summary": "List execution intents with status and fill progress.",
        "parameters": [
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "name": "active", "in": "query", "schema": { "type": "boolean", "default": true } }
        ],
        "responses": { "200": { "description": "List of intents" } }
      }
    },
    "/api/intents/{id}": {
      "delete": {
        "operationId": "cancelIntent",
        "summary": "Cancel an active intent.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ],
        "responses": { "200": { "description": "Intent cancelled" } }
      }
    },
    "/api/thesis/{id}/evaluations": {
      "get": {
        "operationId": "getEvaluationHistory",
        "summary": "Confidence trajectory over time — daily aggregated evaluation history.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ],
        "responses": { "200": { "description": "Daily evaluations with confidence and summary" } }
      }
    },
    "/api/thesis/{id}/nodes/update": {
      "post": {
        "operationId": "updateNodes",
        "summary": "Directly update causal tree node probabilities. Zero LLM cost. Lock confirmed facts.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["updates"] } } } },
        "responses": { "200": { "description": "Updated nodes with new confidence" } }
      }
    },
    "/api/thesis/{id}/heartbeat": {
      "get": {
        "operationId": "getHeartbeatStatus",
        "summary": "Heartbeat config + monthly cost summary for a thesis.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ],
        "responses": { "200": { "description": "Config, defaults, and cost breakdown" } }
      },
      "patch": {
        "operationId": "configureHeartbeat",
        "summary": "Update heartbeat config: news interval, model tier, budget, pause/resume.",
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "200": { "description": "Updated config" } }
      }
    },
    "/api/x/search": {
      "get": {
        "operationId": "searchX",
        "summary": "Search X/Twitter for social sentiment. Returns posts sorted by engagement — uses X API directly.",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "hours", "in": "query", "schema": { "type": "integer", "default": 24 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } }
        ],
        "responses": {
          "200": { "description": "X/Twitter search results" }
        }
      }
    },
    "/api/skills": {
      "get": {
        "operationId": "getSkills",
        "summary": "Agent cognitive guardrails and workflows — prompts that make agents disciplined.",
        "responses": {
          "200": { "description": "Available skills" }
        }
      }
    },
    "/api/tools": {
      "get": {
        "operationId": "getToolManifest",
        "summary": "Full capability manifest with all tools, parameters, and auth requirements.",
        "responses": {
          "200": { "description": "Tool manifest" }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Health check. Returns 200 if the service is up. Use for uptime monitoring and load balancer probes.",
        "parameters": [],
        "responses": { "200": { "description": "Service is healthy" } }
      }
    },
    "/api/status": {
      "get": {
        "operationId": "getStatus",
        "summary": "Detailed system status. Component-level health: database, crons, proxy, cache, external feeds. More granular than /health.",
        "parameters": [],
        "responses": { "200": { "description": "System status with per-component health and latency" } }
      }
    },
    "/api/mcp/{transport}": {
      "get": {
        "operationId": "mcpTransport",
        "summary": "Model Context Protocol endpoint. Supports SSE transport for streaming and JSON-RPC for request/response. Connect MCP-compatible clients (Cursor, Claude Desktop, etc.) to SF tools.",
        "parameters": [
          { "name": "transport", "in": "path", "required": true, "schema": { "type": "string", "enum": ["sse", "message"] }, "description": "Transport type: sse for Server-Sent Events, message for JSON-RPC" }
        ],
        "responses": { "200": { "description": "MCP session established (SSE) or JSON-RPC response" } }
      },
      "post": {
        "operationId": "mcpMessage",
        "summary": "Send a JSON-RPC message to the MCP endpoint.",
        "parameters": [
          { "name": "transport", "in": "path", "required": true, "schema": { "type": "string", "enum": ["sse", "message"] }, "description": "Transport type" }
        ],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "200": { "description": "JSON-RPC response" } }
      }
    },
    "/api/monitor-the-situation": {
      "post": {
        "operationId": "monitorTheSituation",
        "summary": "General web enrichment and scraping. Submit a URL or topic for deep research — returns structured intelligence gathered from web sources.",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "200": { "description": "Enrichment results with extracted data and sources" } }
      }
    }
  },
  "components": {
    "schemas": {
      "QueryResponse": {
        "type": "object",
        "properties": {
          "query": { "type": "string" },
          "answer": { "type": "string", "description": "LLM-synthesized answer (full mode only)" },
          "keyFactors": { "type": "array", "items": { "type": "string" } },
          "kalshi": { "type": "array", "items": { "$ref": "#/components/schemas/Market" } },
          "polymarket": { "type": "array", "items": { "$ref": "#/components/schemas/Market" } },
          "traditional": { "type": "array", "items": { "$ref": "#/components/schemas/TraditionalMarket" } },
          "x": { "type": "array", "items": { "$ref": "#/components/schemas/XPost" } },
          "meta": { "type": "object", "properties": { "sources": { "type": "array", "items": { "type": "string" } }, "latencyMs": { "type": "integer" } } }
        }
      },
      "ContextResponse": {
        "type": "object",
        "properties": {
          "scannedAt": { "type": "string", "format": "date-time" },
          "highlights": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "detail": { "type": "string" } } } },
          "edges": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "ticker": { "type": "string" }, "price": { "type": "integer" }, "edge": { "type": "integer" }, "venue": { "type": "string" } } } },
          "traditional": { "type": "array", "items": { "$ref": "#/components/schemas/TraditionalMarket" } }
        }
      },
      "Market": {
        "type": "object",
        "properties": {
          "title": { "type": "string" },
          "ticker": { "type": "string" },
          "price": { "type": "integer", "description": "Price in cents" },
          "volume": { "type": "integer" }
        }
      },
      "TraditionalMarket": {
        "type": "object",
        "properties": {
          "symbol": { "type": "string" },
          "name": { "type": "string" },
          "price": { "type": "number" },
          "change1d": { "type": "number" },
          "changePct": { "type": "number" }
        }
      },
      "XPost": {
        "type": "object",
        "properties": {
          "author": { "type": "string" },
          "text": { "type": "string" },
          "url": { "type": "string" },
          "likes": { "type": "integer" },
          "retweets": { "type": "integer" }
        }
      }
    }
  }
}
