{
  "openapi": "3.1.0",
  "info": {
    "title": "dhawal.org Markets API",
    "version": "1.0.0",
    "description": "Public, key-less JSON endpoints powering the markets surfaces on dhawal.org. Composites (breadth, options analytics, the daily wire) and public-domain data (FRED macro, CFTC Commitments of Traders, SEC EDGAR filings + XBRL fundamentals, U.S. Treasury yield curve + auctions, EIA energy curves, GDELT) sit alongside a few delayed market-data passthroughs (quote, movers, dividends, earnings). No auth required; responses are edge-cached. The first-party /api/proxy, /api/og-image, and /api/symbol-rss routes are intentionally undocumented (internal CORS proxy / image utility / RSS feed, not JSON data endpoints).",
    "license": {
      "name": "MIT",
      "url": "https://dhawal.org"
    },
    "contact": {
      "name": "Dhawal Ranka",
      "url": "https://dhawal.org",
      "email": "hello@dhawal.org"
    }
  },
  "servers": [
    {
      "url": "https://dhawal.org/api",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "quote",
      "description": "Live and last-session prices."
    },
    {
      "name": "macro",
      "description": "FRED macro series accessor."
    },
    {
      "name": "cot",
      "description": "CFTC weekly Commitments of Traders."
    },
    {
      "name": "filings",
      "description": "SEC EDGAR submissions."
    },
    {
      "name": "earnings",
      "description": "Earnings calendar window."
    },
    {
      "name": "crude-curve",
      "description": "EIA-backed NYMEX WTI futures curve."
    },
    {
      "name": "nat-gas-curve",
      "description": "EIA-backed NYMEX Henry Hub natural-gas futures curve."
    },
    {
      "name": "wire",
      "description": "Daily editorial brief drafted via OpenRouter."
    },
    {
      "name": "movers",
      "description": "Top gainers, losers, and most-active US names."
    },
    {
      "name": "dividends",
      "description": "Dividend and split history per symbol."
    },
    {
      "name": "breadth",
      "description": "In-house equal-weight vs cap-weight breadth composite."
    },
    {
      "name": "yield-curve",
      "description": "U.S. Treasury nominal + TIPS constant-maturity curve."
    },
    {
      "name": "auctions",
      "description": "U.S. Treasury auction results (FiscalData)."
    },
    {
      "name": "econ-events",
      "description": "Curated U.S. economic-release schedule."
    },
    {
      "name": "options",
      "description": "CBOE delayed options-chain analytics (composites)."
    },
    {
      "name": "fundamentals",
      "description": "SEC EDGAR XBRL quarterly fundamentals."
    },
    {
      "name": "news",
      "description": "Aggregated public-RSS news wire with story clustering."
    },
    {
      "name": "gdelt",
      "description": "GDELT coverage-velocity for a topic query."
    },
    {
      "name": "transcript-brief",
      "description": "LLM brief of a public earnings-call transcript."
    }
  ],
  "paths": {
    "/quote": {
      "get": {
        "tags": [
          "quote"
        ],
        "summary": "Live quote for a curated symbol.",
        "description": "Yahoo primary, Finnhub equity fallback. Returns a normalised flat envelope. Edge cache TTL: 30s.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "ES=F",
            "description": "Yahoo-style symbol. Must be in the curated 64-symbol universe; returns 404 otherwise."
          }
        ],
        "responses": {
          "200": {
            "description": "Normalised quote envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/macro": {
      "get": {
        "tags": [
          "macro"
        ],
        "summary": "FRED macro series snapshots.",
        "description": "Pulls the most-recent observation + week-over-week delta for each requested series. Up to 10 series per call. Edge cache TTL: 6h.",
        "parameters": [
          {
            "name": "series",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "VIXCLS,T10Y2Y,DTWEXBGS",
            "description": "Comma-separated FRED series ids (alphanumeric + underscore)."
          }
        ],
        "responses": {
          "200": {
            "description": "Series readings keyed by id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MacroEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/cot": {
      "get": {
        "tags": [
          "cot"
        ],
        "summary": "Commitments of Traders for one futures product.",
        "description": "CFTC Legacy Futures-Only report (dataset 6dca-aqww). Returns the latest week plus 52-week history. Edge cache TTL: 24h.",
        "parameters": [
          {
            "name": "product",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "ES",
                "NQ",
                "YM",
                "RTY",
                "GC",
                "SI",
                "HG",
                "CL",
                "NG",
                "ZB",
                "ZN",
                "ZF",
                "EURUSD",
                "GBPUSD",
                "USDJPY",
                "BTC"
              ]
            },
            "example": "ES"
          }
        ],
        "responses": {
          "200": {
            "description": "COT envelope with history + percentile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CotEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/filings": {
      "get": {
        "tags": [
          "filings"
        ],
        "summary": "Recent SEC EDGAR filings for a US-listed symbol.",
        "description": "Resolves ticker → CIK via SEC company_tickers.json, then fetches submissions. Material forms only by default. Edge cache TTL: 1h.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "AAPL"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 25,
              "default": 5
            }
          },
          {
            "name": "all",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "Pass `1` to include every form type, not just material."
          },
          {
            "name": "insider",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "Pass `1` to return ONLY insider forms (4, 144, 3, 5)."
          }
        ],
        "responses": {
          "200": {
            "description": "Filings envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FilingsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/wire": {
      "get": {
        "tags": [
          "wire"
        ],
        "summary": "Daily editorial brief for /today.",
        "description": "Drafted via OpenRouter (default model: meta-llama/llama-3.3-70b-instruct; override per-deploy with OPENROUTER_MODEL) and grounded in the dhawal.org markets data + macro-events config. Falls back to a deterministic, no-LLM composition (model: \"deterministic\") so the endpoint always returns 200. Edge cache TTL: 12h per date.",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-14"
          }
        ],
        "responses": {
          "200": {
            "description": "Brief envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WireEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/crude-curve": {
      "get": {
        "tags": [
          "crude-curve"
        ],
        "summary": "NYMEX WTI crude oil futures curve (4 contracts).",
        "description": "EIA-backed. Returns settlement prices for the front month plus three deferred contracts (PET.RCLC1..PET.RCLC4 daily series). The EIA republishes CME settlement data daily under a public-data-sharing agreement: no scraping, no rate limits, official source. Edge cache TTL: 6h.",
        "responses": {
          "200": {
            "description": "Crude curve envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrudeCurveEnvelope"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/nat-gas-curve": {
      "get": {
        "tags": [
          "nat-gas-curve"
        ],
        "summary": "NYMEX Henry Hub natural-gas futures curve (4 contracts).",
        "description": "EIA-backed sister to /crude-curve. Returns settlement prices for the front month plus three deferred contracts (NG.RNGC1..NG.RNGC4 daily series). Same shape, same edge cache TTL (6h).",
        "responses": {
          "200": {
            "description": "Natural-gas curve envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrudeCurveEnvelope"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/earnings": {
      "get": {
        "tags": [
          "earnings"
        ],
        "summary": "Earnings calendar for a date window.",
        "description": "Sources from Finnhub /calendar/earnings. Edge cache TTL: 6h.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-11"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-15"
          }
        ],
        "responses": {
          "200": {
            "description": "Earnings calendar window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EarningsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/movers": {
      "get": {
        "tags": [
          "movers"
        ],
        "summary": "Top US gainers, losers, and most-active names.",
        "description": "Yahoo predefined screeners (day_gainers / day_losers / most_actives), with a coverage-universe fallback when the screener is unreachable. Delayed data. Edge cache TTL: 5m.",
        "responses": {
          "200": {
            "description": "Three ranked mover lists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MoversEnvelope"
                }
              }
            }
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/dividends": {
      "get": {
        "tags": [
          "dividends"
        ],
        "summary": "Dividend and split history for a covered symbol.",
        "description": "Yahoo chart events (10y window). Derives trailing-12-month total, trailing yield, annual totals, and a growth streak counted over complete calendar years. Edge cache TTL: 12h.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "AAPL",
            "description": "Symbol from the curated universe; returns 404 otherwise."
          }
        ],
        "responses": {
          "200": {
            "description": "Dividend history envelope. Non-payers return empty arrays and null aggregates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DividendsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/breadth": {
      "get": {
        "tags": [
          "breadth"
        ],
        "summary": "Equal-weight vs cap-weight breadth composite.",
        "description": "In-house composite: deviation of today's RSP/SPY ratio from its 90-day mean, normalised 0-100. One optional leg of the macro regime; degrades to a 200 with null fields when the upstream is unreachable (never 5xx). Edge cache TTL: 6h.",
        "responses": {
          "200": {
            "description": "Breadth envelope. All readings null in the degraded form.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BreadthEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/yield-curve": {
      "get": {
        "tags": [
          "yield-curve"
        ],
        "summary": "U.S. Treasury constant-maturity yield curve.",
        "description": "Parses the U.S. Treasury nominal + TIPS real par-yield XML feeds. Returns the latest curve plus month-ago and year-ago ghost curves, the TIPS real curve (5Y+), and the 2s10s / 3m10y spreads. Public-domain source. Edge cache TTL: 6h.",
        "responses": {
          "200": {
            "description": "Yield-curve envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/YieldCurveEnvelope"
                }
              }
            }
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/auctions": {
      "get": {
        "tags": [
          "auctions"
        ],
        "summary": "U.S. Treasury auction announcements and results.",
        "description": "Treasury FiscalData auctions_query (public domain, fetched at build/edge). Returns upcoming announced auctions and recent results with bid-to-cover. Degrades to empty arrays at 200 when unreachable. Edge cache TTL: 12h.",
        "responses": {
          "200": {
            "description": "Auctions envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuctionsEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/econ-events": {
      "get": {
        "tags": [
          "econ-events"
        ],
        "summary": "Curated U.S. economic-release schedule for a window.",
        "description": "Serves the in-house static MACRO_EVENTS schedule (FOMC, CPI, NFP, GDP, PCE, …). No upstream fetch, no key. This route cannot 5xx on an upstream. Edge cache TTL: 6h.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-06-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-06-30"
          }
        ],
        "responses": {
          "200": {
            "description": "Economic-events envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EconEventsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/options": {
      "get": {
        "tags": [
          "options"
        ],
        "summary": "Options-chain analytics for a liquid underlying.",
        "description": "CBOE delayed quotes, all derivation server-side: put/call OI + volume ratios, front-expiry max pain, top-5 OI strikes, naive gamma exposure, ATM front-month IV. Whitelisted underlyings only. Edge cache TTL: 30m.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "_SPX",
                "SPY",
                "QQQ",
                "AAPL",
                "NVDA",
                "TSLA"
              ]
            },
            "example": "SPY",
            "description": "Underscore prefix (_SPX) denotes an index. Off-whitelist symbols return 404."
          }
        ],
        "responses": {
          "200": {
            "description": "Options-analytics envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OptionsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/fundamentals": {
      "get": {
        "tags": [
          "fundamentals"
        ],
        "summary": "Quarterly fundamentals for a US-listed symbol.",
        "description": "SEC EDGAR XBRL companyfacts (public domain). Revenue / EPS / net income quarterly + annual series, shares-outstanding trend, and YoY deltas. Requires the SEC_USER_AGENT env binding. Edge cache TTL: 24h.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "AAPL",
            "description": "Symbol from the curated CIK map; returns 404 otherwise."
          }
        ],
        "responses": {
          "200": {
            "description": "Fundamentals envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FundamentalsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    },
    "/news": {
      "get": {
        "tags": [
          "news"
        ],
        "summary": "Aggregated news wire for a category.",
        "description": "Aggregates free public RSS feeds, dedupes, and clusters related headlines (lead + also-covering outlets, developing flag). Every headline links to its original publisher. Edge cache TTL: 5m.",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "top",
                "markets",
                "economy",
                "companies",
                "world",
                "crypto",
                "commodities"
              ],
              "default": "top"
            },
            "example": "markets"
          }
        ],
        "responses": {
          "200": {
            "description": "News-wire envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewsEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/gdelt": {
      "get": {
        "tags": [
          "gdelt"
        ],
        "summary": "Coverage-velocity timeline for a topic query.",
        "description": "GDELT DOC 2.0 volume-intensity timeline (share of global coverage) for a sanitized query. Keyless public source. Edge cache TTL: 15m.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 80
            },
            "example": "federal reserve",
            "description": "2-80 chars of [word, space, quote, apostrophe, hyphen] after trimming."
          }
        ],
        "responses": {
          "200": {
            "description": "GDELT volume envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GdeltEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          }
        }
      }
    },
    "/transcript-brief": {
      "get": {
        "tags": [
          "transcript-brief"
        ],
        "summary": "LLM brief of a public earnings-call transcript.",
        "description": "Summarises a public earnings-call transcript (The Motley Fool, with attribution + source link; earningscall.biz fallback) into a tone label, three takeaways, and a guidance-changed flag via OpenRouter. Returns 404 when no public transcript is available. Edge cache TTL: 7d.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "AAPL"
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Fiscal year hint; omit to take the latest published call."
          },
          {
            "name": "quarter",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 4
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Call-brief envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallBriefEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailed"
          },
          "503": {
            "$ref": "#/components/responses/NotConfigured"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "MoversEnvelope": {
        "type": "object",
        "required": [
          "asOf",
          "source",
          "gainers",
          "losers",
          "actives"
        ],
        "properties": {
          "asOf": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "type": "string",
            "enum": [
              "yahoo-screener",
              "coverage-universe"
            ]
          },
          "gainers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MoverRow"
            }
          },
          "losers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MoverRow"
            }
          },
          "actives": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MoverRow"
            }
          }
        }
      },
      "MoverRow": {
        "type": "object",
        "required": [
          "symbol",
          "name",
          "last",
          "changePct"
        ],
        "properties": {
          "symbol": {
            "type": "string",
            "example": "NVDA"
          },
          "name": {
            "type": "string"
          },
          "last": {
            "type": "number"
          },
          "changePct": {
            "type": "number"
          },
          "volume": {
            "type": [
              "number",
              "null"
            ]
          },
          "marketCap": {
            "type": "number"
          }
        }
      },
      "DividendsEnvelope": {
        "type": "object",
        "required": [
          "symbol",
          "asOf",
          "currency",
          "annual",
          "recent",
          "splits",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "symbol": {
            "type": "string",
            "example": "AAPL"
          },
          "asOf": {
            "type": "string",
            "format": "date"
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "lastClose": {
            "type": [
              "number",
              "null"
            ]
          },
          "ttmAmount": {
            "type": [
              "number",
              "null"
            ]
          },
          "ttmYieldPct": {
            "type": [
              "number",
              "null"
            ]
          },
          "growthStreakYears": {
            "type": [
              "integer",
              "null"
            ]
          },
          "annual": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "year",
                "total"
              ],
              "properties": {
                "year": {
                  "type": "integer",
                  "example": 2025
                },
                "total": {
                  "type": "number"
                }
              }
            }
          },
          "recent": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "amount"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "amount": {
                  "type": "number"
                }
              }
            }
          },
          "splits": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "ratio"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "ratio": {
                  "type": "string",
                  "example": "4:1"
                }
              }
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "yahoo"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "QuoteEnvelope": {
        "type": "object",
        "required": [
          "symbol",
          "last",
          "change",
          "changePct",
          "prevClose",
          "currency",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "symbol": {
            "type": "string",
            "example": "ES=F"
          },
          "display": {
            "type": "string",
            "example": "E-mini S&P 500"
          },
          "kind": {
            "type": "string",
            "enum": [
              "index",
              "future",
              "fx",
              "crypto",
              "equity",
              "etf"
            ]
          },
          "last": {
            "type": "number"
          },
          "change": {
            "type": "number"
          },
          "changePct": {
            "type": "number"
          },
          "prevClose": {
            "type": "number"
          },
          "open": {
            "type": [
              "number",
              "null"
            ]
          },
          "dayHigh": {
            "type": [
              "number",
              "null"
            ]
          },
          "dayLow": {
            "type": [
              "number",
              "null"
            ]
          },
          "fiftyTwoWeekHigh": {
            "type": [
              "number",
              "null"
            ]
          },
          "fiftyTwoWeekLow": {
            "type": [
              "number",
              "null"
            ]
          },
          "volume": {
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "source": {
            "type": "string",
            "enum": [
              "yahoo",
              "finnhub"
            ]
          },
          "fetchedAt": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "ttlSeconds": {
            "type": "integer",
            "example": 30
          }
        }
      },
      "MacroEnvelope": {
        "type": "object",
        "required": [
          "series",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "series": {
            "type": "object",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "null"
                },
                {
                  "type": "object",
                  "required": [
                    "last",
                    "date"
                  ],
                  "properties": {
                    "last": {
                      "type": "number"
                    },
                    "date": {
                      "type": "string",
                      "format": "date"
                    },
                    "change": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              ]
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "fred"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "CotEnvelope": {
        "type": "object",
        "required": [
          "product",
          "weekEnding",
          "commercialNet",
          "largeSpecNet",
          "source",
          "fetchedAt"
        ],
        "properties": {
          "product": {
            "type": "string",
            "example": "ES"
          },
          "contractCode": {
            "type": "string",
            "example": "13874A"
          },
          "name": {
            "type": "string"
          },
          "weekEnding": {
            "type": "string",
            "format": "date"
          },
          "commercialLong": {
            "type": "number"
          },
          "commercialShort": {
            "type": "number"
          },
          "commercialNet": {
            "type": "number"
          },
          "largeSpecLong": {
            "type": "number"
          },
          "largeSpecShort": {
            "type": "number"
          },
          "largeSpecNet": {
            "type": "number"
          },
          "nonReportableLong": {
            "type": "number"
          },
          "nonReportableShort": {
            "type": "number"
          },
          "nonReportableNet": {
            "type": "number"
          },
          "openInterest": {
            "type": "number"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "weekEnding": {
                  "type": "string",
                  "format": "date"
                },
                "commercialNet": {
                  "type": "number"
                },
                "largeSpecNet": {
                  "type": "number"
                },
                "nonReportableNet": {
                  "type": "number"
                },
                "openInterest": {
                  "type": "number"
                }
              }
            }
          },
          "wowChange": {
            "type": "object",
            "properties": {
              "commercial": {
                "type": "number"
              },
              "largeSpec": {
                "type": "number"
              }
            }
          },
          "percentile52w": {
            "type": "object",
            "properties": {
              "commercial": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "largeSpec": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              }
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "cftc"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "FilingsEnvelope": {
        "type": "object",
        "required": [
          "symbol",
          "cik",
          "items",
          "source",
          "fetchedAt"
        ],
        "properties": {
          "symbol": {
            "type": "string"
          },
          "cik": {
            "type": "string",
            "example": "0000320193"
          },
          "name": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilingEntry"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "sec"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "FilingEntry": {
        "type": "object",
        "required": [
          "form",
          "filedAt",
          "accessionNumber",
          "url"
        ],
        "properties": {
          "form": {
            "type": "string",
            "example": "10-Q"
          },
          "filedAt": {
            "type": "string",
            "format": "date"
          },
          "periodOfReport": {
            "type": "string"
          },
          "accessionNumber": {
            "type": "string"
          },
          "primaryDocument": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "size": {
            "type": "integer"
          }
        }
      },
      "EarningsEnvelope": {
        "type": "object",
        "required": [
          "from",
          "to",
          "items",
          "source",
          "fetchedAt"
        ],
        "properties": {
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EarningsRow"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "finnhub"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "EarningsRow": {
        "type": "object",
        "required": [
          "symbol",
          "date"
        ],
        "properties": {
          "symbol": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "hour": {
            "type": "string",
            "enum": [
              "bmo",
              "amc",
              "dmh",
              ""
            ]
          },
          "quarter": {
            "type": [
              "integer",
              "null"
            ]
          },
          "year": {
            "type": [
              "integer",
              "null"
            ]
          },
          "epsEstimate": {
            "type": [
              "number",
              "null"
            ]
          },
          "epsActual": {
            "type": [
              "number",
              "null"
            ]
          },
          "revenueEstimate": {
            "type": [
              "number",
              "null"
            ]
          },
          "revenueActual": {
            "type": [
              "number",
              "null"
            ]
          }
        }
      },
      "CrudeCurveEnvelope": {
        "type": "object",
        "required": [
          "contracts",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "contracts": {
            "type": "object",
            "required": [
              "front",
              "m1",
              "m2",
              "m3"
            ],
            "properties": {
              "front": {
                "$ref": "#/components/schemas/CrudeContractReading"
              },
              "m1": {
                "$ref": "#/components/schemas/CrudeContractReading"
              },
              "m2": {
                "$ref": "#/components/schemas/CrudeContractReading"
              },
              "m3": {
                "$ref": "#/components/schemas/CrudeContractReading"
              }
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "eia"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer",
            "example": 21600
          }
        }
      },
      "WireEnvelope": {
        "type": "object",
        "required": [
          "date",
          "body",
          "model",
          "generatedAt",
          "ttlSeconds"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "body": {
            "type": "string",
            "description": "Markdown brief: paragraphs only, no headings. 400-550 words."
          },
          "model": {
            "type": "string",
            "example": "meta-llama/llama-3.3-70b-instruct",
            "description": "OpenRouter slug that drafted the brief, or \"deterministic\" when the LLM was unavailable and the brief was composed from data alone."
          },
          "generatedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer",
            "example": 43200
          }
        }
      },
      "CrudeContractReading": {
        "oneOf": [
          {
            "type": "null"
          },
          {
            "type": "object",
            "required": [
              "last",
              "date"
            ],
            "properties": {
              "last": {
                "type": "number",
                "description": "Settlement in USD/bbl."
              },
              "date": {
                "type": "string",
                "format": "date"
              }
            }
          }
        ]
      },
      "BreadthEnvelope": {
        "type": "object",
        "required": [
          "value",
          "score",
          "ratioToday",
          "ratioMean",
          "date",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "value": {
            "type": [
              "number",
              "null"
            ],
            "description": "Deviation (pp) of today's RSP/SPY ratio from its 90d mean."
          },
          "score": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "ratioToday": {
            "type": [
              "number",
              "null"
            ]
          },
          "ratioMean": {
            "type": [
              "number",
              "null"
            ]
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "source": {
            "type": "string",
            "enum": [
              "yahoo-rsp-spy"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "YieldCurveEnvelope": {
        "type": "object",
        "required": [
          "latest",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "latest": {
            "$ref": "#/components/schemas/CurveSnapshot"
          },
          "monthAgo": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CurveSnapshot"
              }
            ]
          },
          "yearAgo": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CurveSnapshot"
              }
            ]
          },
          "realLatest": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CurveSnapshot"
              }
            ]
          },
          "spread2s10s": {
            "type": [
              "number",
              "null"
            ],
            "description": "10Y minus 2Y (pp); negative = inverted."
          },
          "spread3m10y": {
            "type": [
              "number",
              "null"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "CurveSnapshot": {
        "type": "object",
        "required": [
          "date",
          "points"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CurvePoint"
            }
          }
        }
      },
      "CurvePoint": {
        "type": "object",
        "required": [
          "tenor",
          "months",
          "yield"
        ],
        "properties": {
          "tenor": {
            "type": "string",
            "example": "2Y"
          },
          "months": {
            "type": "integer",
            "example": 24
          },
          "yield": {
            "type": "number",
            "description": "Constant-maturity yield, percent."
          }
        }
      },
      "AuctionsEnvelope": {
        "type": "object",
        "required": [
          "upcoming",
          "results",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "upcoming": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuctionRecord"
            }
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuctionRecord"
            }
          },
          "degraded": {
            "type": "boolean"
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "AuctionRecord": {
        "type": "object",
        "required": [
          "cusip",
          "securityType",
          "securityTerm",
          "auctionDate"
        ],
        "properties": {
          "cusip": {
            "type": "string"
          },
          "securityType": {
            "type": "string",
            "example": "Note"
          },
          "securityTerm": {
            "type": "string",
            "example": "10-Year"
          },
          "auctionDate": {
            "type": "string",
            "format": "date"
          },
          "issueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "announcedDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "bidToCover": {
            "type": [
              "number",
              "null"
            ]
          },
          "highYield": {
            "type": [
              "number",
              "null"
            ]
          },
          "highDiscountRate": {
            "type": [
              "number",
              "null"
            ]
          },
          "offeringAmt": {
            "type": [
              "number",
              "null"
            ]
          }
        }
      },
      "EconEventsEnvelope": {
        "type": "object",
        "required": [
          "from",
          "to",
          "items",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EconEvent"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "static-schedule"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "EconEvent": {
        "type": "object",
        "required": [
          "date",
          "event",
          "country"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "time": {
            "type": "string",
            "description": "HH:MM ET if known, else empty."
          },
          "event": {
            "type": "string",
            "example": "Non-Farm Payrolls"
          },
          "country": {
            "type": "string",
            "example": "US"
          },
          "impact": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              ""
            ]
          },
          "actual": {
            "type": [
              "number",
              "null"
            ]
          },
          "forecast": {
            "type": [
              "number",
              "null"
            ]
          },
          "previous": {
            "type": [
              "number",
              "null"
            ]
          }
        }
      },
      "OptionsEnvelope": {
        "type": "object",
        "required": [
          "symbol",
          "spot",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "symbol": {
            "type": "string",
            "example": "SPY"
          },
          "spot": {
            "type": "number"
          },
          "putCallOiRatio": {
            "type": [
              "number",
              "null"
            ]
          },
          "putCallVolumeRatio": {
            "type": [
              "number",
              "null"
            ]
          },
          "maxPain": {
            "type": [
              "number",
              "null"
            ]
          },
          "topOiStrikes": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "strike",
                "callOi",
                "putOi"
              ],
              "properties": {
                "strike": {
                  "type": "number"
                },
                "callOi": {
                  "type": "number"
                },
                "putOi": {
                  "type": "number"
                }
              }
            }
          },
          "gex": {
            "type": [
              "number",
              "null"
            ],
            "description": "Naive dollar gamma exposure (calls +, puts -)."
          },
          "atmIvFrontMonth": {
            "type": [
              "number",
              "null"
            ]
          },
          "expiriesAnalyzed": {
            "type": "integer"
          },
          "source": {
            "type": "string",
            "enum": [
              "cboe-delayed"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "FundamentalsEnvelope": {
        "type": "object",
        "required": [
          "symbol",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "symbol": {
            "type": "string",
            "example": "AAPL"
          },
          "entityName": {
            "type": [
              "string",
              "null"
            ]
          },
          "revenueQuarters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuarterPoint"
            }
          },
          "revenueYears": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuarterPoint"
            }
          },
          "epsQuarters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuarterPoint"
            }
          },
          "netIncomeQuarters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuarterPoint"
            }
          },
          "sharesOutstanding": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuarterPoint"
            }
          },
          "revenueYoYPct": {
            "type": [
              "number",
              "null"
            ]
          },
          "epsYoYPct": {
            "type": [
              "number",
              "null"
            ]
          },
          "sharesChangePct1y": {
            "type": [
              "number",
              "null"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "sec-edgar-xbrl"
            ]
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "QuarterPoint": {
        "type": "object",
        "required": [
          "label",
          "end",
          "val"
        ],
        "properties": {
          "label": {
            "type": "string",
            "example": "FY26 Q2"
          },
          "end": {
            "type": "string",
            "format": "date"
          },
          "val": {
            "type": "number"
          }
        }
      },
      "NewsEnvelope": {
        "type": "object",
        "required": [
          "category",
          "items",
          "clusters",
          "sourcesOk",
          "sourcesTotal",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "category": {
            "type": "string",
            "enum": [
              "top",
              "markets",
              "economy",
              "companies",
              "world",
              "crypto",
              "commodities"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WireItem"
            }
          },
          "clusters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoryCluster"
            }
          },
          "sourcesOk": {
            "type": "integer"
          },
          "sourcesTotal": {
            "type": "integer"
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "WireItem": {
        "type": "object",
        "required": [
          "id",
          "title",
          "link",
          "source",
          "publishedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "link": {
            "type": "string",
            "format": "uri"
          },
          "source": {
            "type": "string",
            "example": "Reuters"
          },
          "publishedAt": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "image": {
            "type": "string",
            "format": "uri"
          },
          "summary": {
            "type": "string",
            "description": "Feed-provided blurb, not article body."
          }
        }
      },
      "StoryCluster": {
        "type": "object",
        "required": [
          "lead",
          "also",
          "sources",
          "velocity",
          "score",
          "developing"
        ],
        "properties": {
          "lead": {
            "$ref": "#/components/schemas/WireItem"
          },
          "also": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WireItem"
            }
          },
          "sources": {
            "type": "integer",
            "description": "Distinct outlet count."
          },
          "velocity": {
            "type": "integer",
            "description": "Distinct new sources in the last 60 min."
          },
          "score": {
            "type": "number"
          },
          "developing": {
            "type": "boolean"
          }
        }
      },
      "GdeltEnvelope": {
        "type": "object",
        "required": [
          "query",
          "points",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "query": {
            "type": "string",
            "description": "The sanitized query actually sent upstream."
          },
          "points": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "t",
                "v"
              ],
              "properties": {
                "t": {
                  "type": "integer",
                  "description": "Unix seconds."
                },
                "v": {
                  "type": "number",
                  "description": "Volume intensity (% of global coverage)."
                }
              }
            }
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "CallBriefEnvelope": {
        "type": "object",
        "required": [
          "symbol",
          "year",
          "quarter",
          "tone",
          "bullets",
          "guidanceChanged",
          "model",
          "source",
          "fetchedAt",
          "ttlSeconds"
        ],
        "properties": {
          "symbol": {
            "type": "string",
            "example": "AAPL"
          },
          "year": {
            "type": "integer",
            "example": 2026
          },
          "quarter": {
            "type": "integer",
            "minimum": 1,
            "maximum": 4
          },
          "conferenceDate": {
            "type": [
              "string",
              "null"
            ]
          },
          "tone": {
            "type": "string",
            "enum": [
              "upbeat",
              "neutral",
              "cautious"
            ]
          },
          "bullets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 3,
            "maxItems": 3
          },
          "guidanceChanged": {
            "type": "boolean"
          },
          "model": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "motley-fool",
              "earningscall-biz"
            ]
          },
          "transcriptUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "fetchedAt": {
            "type": "integer"
          },
          "ttlSeconds": {
            "type": "integer"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Required parameter missing or malformed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested resource (symbol / product) is outside the curated coverage.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UpstreamFailed": {
        "description": "Upstream provider returned a non-2xx status, was unreachable, or sent malformed data.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotConfigured": {
        "description": "Required server-side credentials / env binding are not present in this deployment.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}