{"openapi":"3.1.0","info":{"title":"MoneySignals API","description":"ML-powered stock predictions, market intelligence, and alternative data signals. Provides access to predictions for 600+ tickers, social sentiment, congressional trading activity, corporate flight tracking, lobbying disclosures, and more.\n\n**Base URL:** `https://api.moneysignals.us`\n\n**Get a key (free):** A free API key comes with the free email signup at https://moneysignals.us/#pricing — no credit card.\n\n**Authentication:** Pass your key via the `X-API-Key` header **or** as `Authorization: Bearer <key>` (whichever your client prefers).\n\n**Rate limits:** 30 requests/minute, 1,000 requests/day. Every response carries `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset` (epoch seconds) for the minute window, plus `...-Day` variants for the daily budget; a `429` adds `Retry-After`. Read them to self-pace instead of polling `/account/usage`.\n\n**MCP:** AI agents can connect via Streamable HTTP at `https://api.moneysignals.us/mcp` (same key, via X-API-Key or Bearer).","version":"1.0.0"},"servers":[{"url":"https://api.moneysignals.us","description":"Production"}],"paths":{"/api/v1/predictions/latest":{"get":{"tags":["Predictions"],"summary":"Get Latest Predictions","description":"Get latest ML predictions across all tickers.\n\nReturns direction (bullish/bearish), predicted return magnitude, confidence score,\nand historical model accuracy for each ticker. Ranked by confidence.\n\nWeekly/monthly pipelines were discontinued 2026-03-23: those timeframes return the\nfinal archived batch (check target_date) with accuracy_status='archived_sample'.","operationId":"get_latest_predictions","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"timeframe","in":"query","required":false,"schema":{"type":"string","pattern":"^(daily|weekly|monthly)$","default":"daily","title":"Timeframe"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","pattern":"^(bullish|bearish)$","title":"Direction"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictionsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/predictions/accuracy":{"get":{"tags":["Predictions"],"summary":"Get Prediction Accuracy","description":"Get historical prediction accuracy statistics.\n\nWithout a ticker, returns aggregate accuracy by timeframe.\nWith a ticker, returns that ticker's accuracy breakdown.","operationId":"get_prediction_accuracy","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"ticker","in":"query","required":false,"schema":{"type":"string","title":"Ticker"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccuracyResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/predictions/batch":{"get":{"tags":["Predictions"],"summary":"Get Batch Predictions","description":"Get predictions for multiple tickers in a single request (Pro tier).\n\nPass a comma-separated list of tickers. Returns predictions for each.","operationId":"get_batch_predictions","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"tickers","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated tickers (e.g. AAPL,MSFT,NVDA)","title":"Tickers"},"description":"Comma-separated tickers (e.g. AAPL,MSFT,NVDA)"},{"name":"timeframe","in":"query","required":false,"schema":{"type":"string","pattern":"^(daily|weekly|monthly)$","default":"daily","title":"Timeframe"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictionsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/predictions/{ticker}":{"get":{"tags":["Predictions"],"summary":"Get Ticker Predictions","description":"Get predictions for a specific ticker across all timeframes (daily, weekly, monthly).","operationId":"get_ticker_predictions","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TickerPredictionsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/market/regime":{"get":{"tags":["Market Data"],"summary":"Get Market Regime","description":"Get current market regime — VIX level, SPY vs 200-day MA, and regime classification.\n\nRegime states: `normal`, `cautious`, `defensive`, `paused`.\nThe size_multiplier indicates how aggressively the system sizes positions.","operationId":"get_market_regime","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegimeResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/v1/market/fear-greed":{"get":{"tags":["Market Data"],"summary":"Get Fear Greed","description":"Get CNN Fear & Greed index and crypto fear/greed for the last 7 days.\n\nScale: 0 (Extreme Fear) to 100 (Extreme Greed). Values below 25 indicate extreme fear.","operationId":"get_fear_greed","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FearGreedResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/v1/market/pcr":{"get":{"tags":["Market Data"],"summary":"Get Pcr","description":"Get Put/Call ratio data for the last 7 days.\n\nTotal PCR > 1.0 = bearish sentiment (more puts). < 0.7 = bullish (more calls).","operationId":"get_pcr","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PCRResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/v1/market/economic-calendar":{"get":{"tags":["Market Data"],"summary":"Get Economic Calendar","description":"Get upcoming US economic events (next `days` days) from EODHD.\n\nFilter by `impact` level: high, medium, or low. EODHD doesn't rate impact, so it's\nderived from the event name — `high` is the genuine market-movers (FOMC/rate\ndecisions, CPI/inflation, NFP, GDP, PCE, PPI, retail sales, ISM); `medium` is\nsecond-tier releases (jobless claims, JOLTs, confidence, regional Fed, housing).\n\nCached 6h; degrades to an empty list (not an error) if the upstream is unavailable.","operationId":"get_economic_calendar","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"impact","in":"query","required":false,"schema":{"type":"string","pattern":"^(high|medium|low)$","title":"Impact"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":7,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EconomicCalendarResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/market/ohlcv/{ticker}":{"get":{"tags":["Market Data"],"summary":"Get Ohlcv","description":"Get OHLCV price data for a specific ticker.\n\nReturns daily, weekly, or monthly bars. Data sourced from EODHD.","operationId":"get_ohlcv","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string","title":"Ticker"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}},{"name":"granularity","in":"query","required":false,"schema":{"type":"string","pattern":"^(1d|1w|1m)$","default":"1d","title":"Granularity"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OHLCVResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/market/anomalies":{"get":{"tags":["Market Data"],"summary":"Get Anomalies","description":"Surface today's statistical outliers — tickers whose latest daily move is at\nleast `min_sigma` std-devs from their own recent mean daily return (over\n`lookback_days`), ranked by |sigma|.\n\nEach result gives the move and direction; the response `note` reports the\nmeasured next-day **mean-reversion** tendency from the same window. Reversion is\nmost reliable for indices/ETFs — single-stock extremes are frequently\nnews/earnings driven and can continue, so the implied direction is context, not\na call. Heavy compute (scans the active universe); cached for hours, refreshes daily.","operationId":"get_anomalies","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"min_sigma","in":"query","required":false,"schema":{"type":"number","maximum":6.0,"minimum":1.5,"default":2.5,"title":"Min Sigma"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"lookback_days","in":"query","required":false,"schema":{"type":"integer","maximum":400,"minimum":60,"default":180,"title":"Lookback Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomaliesResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/market/character":{"get":{"tags":["Market Data"],"summary":"Get Market Character","description":"Market character / dispersion gauge — how unusual is the current single-name\ntape vs every year since 2015?\n\nComputes a live trailing-`window` (trading days) read over the ~700-ticker model\nuniverse — cross-sectional dispersion, median |daily move|, share of >2% / >5%\nmoves, median intraday range, and SPY's median move as the index contrast — and\ncompares it against embedded full-year reference values for 2015-2025 computed\nwith the identical convention, yielding a plain-language `read`\n(record_dispersion / elevated / normal / quiet). Heavy compute (scans the active\nuniverse); cached, refreshes daily.","operationId":"get_market_character","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"window","in":"query","required":false,"schema":{"type":"integer","maximum":60,"minimum":5,"default":20,"title":"Window"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketCharacterResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/social/trending":{"get":{"tags":["Social Sentiment"],"summary":"Get Social Trending","description":"Get trending tickers (and per-platform topics) from social media.\n\nBy default (no `platform`) returns only **ticker-tagged** trends — the\nfinance-relevant signal (overwhelmingly Reddit ticker mentions). Without that\nfilter the feed is dominated by non-finance topic noise: the table also ingests\n`wikipedia`, `hackernews`, `google_trends`, and `youtube_general` trending items\n(viral Shorts, world news, sports) that have no ticker and would crowd out the\nactual market chatter when ranked by mentions.\n\nPass an explicit `platform` to get that platform's raw feed, including non-ticker\ntopic rows. Platforms: `reddit` (ticker mentions), `youtube` / `youtube_general`\n(videos), `wikipedia` / `hackernews` / `google_trends` (trending topics).\n\nIncludes mention counts, engagement scores, and sentiment (-1 to +1).","operationId":"get_social_trending","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"platform","in":"query","required":false,"schema":{"type":"string","pattern":"^(reddit|youtube|youtube_general|wikipedia|hackernews|google_trends)$","title":"Platform"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":14,"minimum":1,"default":3,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SocialTrendingResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/social/sentiment":{"get":{"tags":["Social Sentiment"],"summary":"Get Social Sentiment","description":"Get ApeWisdom Reddit sentiment data — Reddit mention/upvote volume per stock.\n\nApeWisdom aggregates mentions and upvotes across major finance subreddits\n(r/wallstreetbets, r/stocks, r/investing, etc.). With a `ticker`, returns that\nstock's recent mention rows (empty if it hasn't been trending). Without one,\nreturns the top trending stocks ranked by mention count.","operationId":"get_social_sentiment","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"ticker","in":"query","required":false,"schema":{"type":"string","description":"Filter to one ticker (e.g. NVDA); omit for the top trending list","title":"Ticker"},"description":"Filter to one ticker (e.g. NVDA); omit for the top trending list"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":14,"minimum":1,"default":3,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SocialSentimentResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alternative/flights":{"get":{"tags":["Alternative Data"],"summary":"Get Flight Signals","description":"Get DC-area corporate flight signals with lobbying/hearing cross-validation.\n\nTracks aircraft owned by S&P 500 companies, executives, and political figures\nat 7 Washington DC airports. Signals are cross-validated against lobbying\ndisclosures and congressional hearing schedules.\n\nValidation levels: `TRIPLE_CONFIRMED` (flight + lobby + hearing),\n`LOBBY_CONFIRMED`, `HEARING_CONFIRMED`, `FLIGHT_ONLY`.","operationId":"get_flight_signals","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":3,"title":"Days"}},{"name":"ticker","in":"query","required":false,"schema":{"type":"string","title":"Ticker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlightSignalsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alternative/lobbying":{"get":{"tags":["Alternative Data"],"summary":"Get Lobbying Disclosures","description":"Get lobbying disclosure filings from the Senate LDA database.\n\nIncludes registrant, client, dollar amounts, issue areas, and mapped stock tickers.\nFilter by ticker to see which companies are actively lobbying.","operationId":"get_lobbying_disclosures","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"ticker","in":"query","required":false,"schema":{"type":"string","title":"Ticker"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":90,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LobbyingResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alternative/hearings":{"get":{"tags":["Alternative Data"],"summary":"Get Congressional Hearings","description":"Get congressional hearing schedules with sector and ticker mapping.\n\nEach hearing is mapped to affected GICS sectors and stock tickers based on\ncommittee jurisdiction (e.g., Armed Services → LMT, BA, RTX).","operationId":"get_congressional_hearings","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}},{"name":"committee","in":"query","required":false,"schema":{"type":"string","title":"Committee"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HearingsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals/events":{"get":{"tags":["Signals"],"summary":"Get Event Signals","description":"Get LLM-generated event-driven trade signals.\n\nSignals are produced by Claude analyzing RSS headlines, economic calendar,\nsocial sentiment, and congressional trading data. Each signal includes a\nconfidence score (0-1), time horizon, and causal reasoning.\n\nThe `second_order` flag marks indirect effects (e.g., a tariff announcement\naffecting chip stocks through supply chain disruption).","operationId":"get_event_signals","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":14,"minimum":1,"default":3,"title":"Days"}},{"name":"ticker","in":"query","required":false,"schema":{"type":"string","title":"Ticker"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","pattern":"^(bullish|bearish)$","title":"Direction"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventSignalsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals/best":{"get":{"tags":["Signals"],"summary":"Get Best Signals","description":"Today's highest-conviction event signals — the precision picks.\n\nFilters live (unresolved) signals to those whose (event_type, second_order)\ncurrently clears a precision gate on its historical win rate, then ranks by\n**conviction = shrunk-type-win-rate x confidence**. The gate is precision-first:\n\n  - `min_type_wilson_lo` (default 0.50): the **Wilson 95% lower bound** of the\n    type's win rate must clear this. A type whose confidence interval still\n    spans a coin flip — even if its point estimate is >0.52 — is excluded.\n    This is what separates a statistically-real edge from a lucky-looking small\n    sample. As of the latest revalidation NO event type clears it (sector_catalyst-2nd,\n    once ~0.74, has decayed to coin-flip), so /signals/best is currently empty by\n    design — the gate is doing its job, not hiding a live edge.\n  - `min_type_win_rate` (default 0.52): secondary raw floor.\n  - `min_type_samples` (default 8): minimum resolved outcomes for the type.\n\nAnti-signal types (e.g. congress_trade, historically ~36%) and decayed types\nfall below these floors and are excluded. The win-rate is shrunk toward 0.5\n(Beta(2.5, 2.5) prior) so a lucky small-sample type can't top the ranking.","operationId":"get_best_signals","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":14,"minimum":1,"default":3,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Limit"}},{"name":"min_confidence","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"default":0.6,"title":"Min Confidence"}},{"name":"min_type_win_rate","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"default":0.52,"title":"Min Type Win Rate"}},{"name":"min_type_samples","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":8,"title":"Min Type Samples"}},{"name":"min_type_wilson_lo","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"default":0.5,"title":"Min Type Wilson Lo"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventSignalsResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals/brief":{"get":{"tags":["Signals"],"summary":"Get Daily Brief","description":"Today's decision brief in ONE call — for automated strategies and agents.\n\nComposes the three things needed to decide whether and what to trade today:\n  - `regime`: the market risk gate (VIX, SPY vs 200MA, position multiplier);\n  - `signals`: the top precision picks (same logic as /signals/best);\n  - `macro`: the next high-impact economic event (FOMC/CPI/NFP/etc.) and how soon;\nplus a curated `guidance` line tying them together. Pair with get_trade_plan /\na broker MCP for execution. NOT financial advice.","operationId":"get_daily_brief","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":15,"minimum":1,"default":5,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyBriefResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals/performance":{"get":{"tags":["Signals"],"summary":"Get Signal Performance","description":"Historical win rate of every event-signal TYPE — which signals to trust.\n\nGroups all resolved event signals by (event_type, second_order) and reports the\nrealized win rate, direction-adjusted average P&L (a correct short counts as a gain,\nnot a loss), and sample size, ranked by a sample-size-shrunk\nwin rate (Beta(2.5, 2.5) prior) so a lucky small-n type can't top the list. This is\nthe transparent map behind the per-signal `type_win_rate`: it shows which types have\nhistorically graded strong and which (like congress_trade) have graded as\nanti-signals. Each row is labeled strong / moderate / coin-flip / anti-signal.\nTypes with fewer than `min_samples` resolved outcomes are omitted as too noisy.\n\nHonest caveat: these are HISTORICAL realized outcomes on a still-growing sample, and\nhigh win rates on small n can decay as samples grow — types have dropped out of\n\"strong\" before. Pair with /signals/best (which only surfaces types clearing the\nstatistical precision gates) rather than treating any single number as guaranteed.","operationId":"get_signal_performance","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"min_samples","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":5,"title":"Min Samples"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalPerformanceResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals/congress-trades":{"get":{"tags":["Signals"],"summary":"Get Congress Trades","description":"Get congressional stock trades from STOCK Act disclosures.\n\nData sourced from QuiverQuant. Includes transaction type (Purchase, Sale),\ndollar amount range, politician name, party, and chamber.\n\nNote: this is raw disclosure data, not a buy signal. In our own backtests,\n*following* congressional trades has been an anti-signal (~36% win rate as a\n2nd-order event type — see /signals/performance), so treat it as context, not\na recommendation.","operationId":"get_congress_trades","security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":14,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CongressTradesResponse"}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute on your tier."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current minute."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the minute window frees up."},"X-RateLimit-Limit-Day":{"schema":{"type":"integer"},"description":"Requests allowed per day on your tier."},"X-RateLimit-Remaining-Day":{"schema":{"type":"integer"},"description":"Requests left in the current day."},"X-RateLimit-Reset-Day":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the daily budget resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals/etf-pullback":{"get":{"tags":["Signals"],"summary":"Get Etf Pullback Signal","description":"Mechanical ETF pullback-in-uptrend signal (RSI2) — live state + measured track record.\n\nA pre-registered, parameter-free rule: an ETF closes above its 200-day simple\nmoving average with a 2-period Wilder RSI below 10 -> buy, hold 5 trading days.\nSurfaced only for the tickers whose full-history edge cleared walk-forward-style\nkill-tests under realistic entry timing (see `research_context` in the response).\n\nThe track record is recomputed live from complete price history (cached ~6h):\nper-ETF hit rates vs the honest above-trend base rate, Wilson 95 lower bounds,\nand per-entry-timing splits — wins and losses included. Fires are infrequent by\ndesign; an empty `active` list is the normal state. Works with the free tier.\nNOT financial advice.","operationId":"get_etf_pullback_signal","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ETFPullbackResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/v1/signals/youtube-scoreboard":{"get":{"tags":["Signals"],"summary":"Get Youtube Scoreboard","description":"Finance-YouTube creator scoreboard — how the independent analysts we track\nhave actually graded, Wilson-95 lower-bounded.\n\nWe log the falsifiable calls (ticker or asset, direction, horizon) made by the\nindependent finance and macro YouTubers we follow, then grade each against real\nmarket data once its horizon elapses. This reports per-creator graded accuracy\nwith a Wilson 95% lower bound (so a 2/2 reads as ~0.31, not \"100%\"), alongside\nthe calls still pending resolution.\n\nThese are THIRD-PARTY forecasts, tracked and attributed — NOT MoneySignals\nsignals and NOT financial advice. The corpus is young: until a creator has\nresolved predictions, `graded` is empty by design and the tracked calls sit in\n`pending` (an empty scoreboard is the honest current state, not an error).\nWorks with the free tier.","operationId":"get_youtube_scoreboard","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YouTubeScoreboardResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/v1/account/me":{"get":{"tags":["Account"],"summary":"Get Account Info","description":"Get your API key info, tier, rate limits, and usage summary.","operationId":"get_account_info","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/api/v1/account/usage":{"get":{"tags":["Account"],"summary":"Get Usage Stats","description":"Get your API usage statistics for the last 30 days.\n\nIncludes daily request counts, average response times, error rates,\nand your most-used endpoints.","operationId":"get_usage_stats","responses":{"200":{"description":"Successful Response","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"401":{"description":"No API key (`missing_api_key`), or the key is not recognised (`invalid_api_key`). Send it as `X-API-Key` or `Authorization: Bearer <key>`. A free key comes with the free email signup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key is real but cannot be used here: `api_key_deactivated`, `api_key_expired`, or `tier_required` — a tier that does not include this endpoint. A refused request costs no quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded: `rate_limited_minute` or `rate_limited_day`. `Retry-After` is the wait in seconds; the headers for the window that tripped are also returned. Prefer reading `X-RateLimit-Remaining` on successful responses and pacing yourself instead of retrying into a 429.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the minute window frees up.","schema":{"type":"integer"}},"X-RateLimit-Limit-Day":{"description":"Requests allowed per day on your tier.","schema":{"type":"integer"}},"X-RateLimit-Remaining-Day":{"description":"Requests left in the current day.","schema":{"type":"integer"}},"X-RateLimit-Reset-Day":{"description":"Unix epoch seconds when the daily budget resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]},{"HTTPBearer":[]}]}},"/health":{"get":{"tags":["System"],"summary":"Health","description":"Service health check — no authentication required.\n\nChecks DB connectivity, model freshness, and prediction pipeline status.\nReturns 'degraded' with warnings if predictions are stale or missing.","operationId":"health","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/demo/snapshot":{"get":{"tags":["Demo"],"summary":"Demo Snapshot","description":"Public demo endpoint — returns a live market snapshot (no auth required).\n\nLimited data to showcase what the API provides. Subscribe for full access.","operationId":"demo_snapshot","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemoSnapshotResponse"}}}}}}},"/track-record":{"get":{"tags":["Demo"],"summary":"Track Record","description":"Public live track record for LLM event signals (no auth required).\n\nEvery signal's outcome — win or lose — is recorded automatically after its\ntime horizon elapses (scripts/backfill_event_outcomes.py). This endpoint\naggregates the resolved ledger; nothing is curated or cherry-picked.\nCached 1h. Recent resolved signals are inherently stale (their horizon has\npassed), so this does not leak live signal content.","operationId":"track_record","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackRecordResponse"}}}}}}}},"components":{"schemas":{"AccountInfo":{"properties":{"key_prefix":{"type":"string","title":"Key Prefix","examples":["at_sk_14e013..."]},"user_email":{"type":"string","title":"User Email","examples":["user@example.com"]},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Name","examples":["Dave Liu"]},"tier":{"type":"string","title":"Tier","examples":["secret"]},"rate_limit_per_minute":{"type":"integer","title":"Rate Limit Per Minute","examples":[30]},"rate_limit_per_day":{"type":"integer","title":"Rate Limit Per Day","examples":[1000]},"created_at":{"type":"string","title":"Created At","examples":["2026-03-24T18:32:00Z"]},"last_used_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Used At"},"total_requests":{"type":"integer","title":"Total Requests","examples":[142]},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["key_prefix","user_email","tier","rate_limit_per_minute","rate_limit_per_day","created_at","total_requests"],"title":"AccountInfo"},"AccountResponse":{"properties":{"account":{"$ref":"#/components/schemas/AccountInfo"}},"type":"object","required":["account"],"title":"AccountResponse","description":"API key and account info."},"AccuracyResponse":{"properties":{"days":{"type":"integer","title":"Days","examples":[30]},"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker","examples":["AAPL"]},"accuracy":{"items":{"$ref":"#/components/schemas/AccuracyStat"},"type":"array","title":"Accuracy"}},"type":"object","required":["days","accuracy"],"title":"AccuracyResponse","description":"Response for /predictions/accuracy.","example":{"accuracy":[{"accuracy":0.63,"correct":7843,"granularity":"1d","total_predictions":12450},{"accuracy":0.65,"correct":1365,"granularity":"1w","total_predictions":2100}],"days":30}},"AccuracyStat":{"properties":{"granularity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Granularity","description":"Normalized timeframe (legacy interval spellings are folded in).","examples":["daily"]},"timeframe":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timeframe","description":"Normalized form of granularity: daily / weekly / monthly.","examples":["daily"]},"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker","examples":["AAPL"]},"total_predictions":{"type":"integer","title":"Total Predictions","examples":[245]},"correct":{"type":"integer","title":"Correct","examples":[158]},"accuracy":{"type":"number","title":"Accuracy","examples":[0.6449]},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"'live' (this timeframe still produces and regrades predictions daily) or 'archived_sample' (pipeline discontinued — weekly/monthly stopped 2026-03-23; the accuracy is a closed historical sample, not a live metric).","examples":["live"]},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","description":"Present for archived_sample rows: the closed sample's date range, size in independent windows, and why it cannot establish skill."},"sample_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sample Start","description":"First resolved target date for this timeframe (all-time).","examples":["2026-02-21"]},"sample_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sample End","description":"Last resolved target date for this timeframe (all-time).","examples":["2026-04-21"]}},"type":"object","required":["total_predictions","correct","accuracy"],"title":"AccuracyStat","description":"Accuracy stats for a timeframe (granularity kept as a legacy alias)."},"AnomaliesResponse":{"properties":{"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","examples":["2026-06-18"]},"min_sigma":{"type":"number","title":"Min Sigma","examples":[2.5]},"lookback_days":{"type":"integer","title":"Lookback Days","examples":[180]},"count":{"type":"integer","title":"Count","examples":[19]},"note":{"type":"string","title":"Note","description":"Measured next-day reversal tendency + reliability caveats"},"anomalies":{"items":{"$ref":"#/components/schemas/Anomaly"},"type":"array","title":"Anomalies"}},"type":"object","required":["min_sigma","lookback_days","count","note","anomalies"],"title":"AnomaliesResponse","description":"Statistical outliers — tickers whose latest daily move is an outsized sigma event."},"Anomaly":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["ACN"]},"date":{"type":"string","title":"Date","examples":["2026-06-18"]},"return_pct":{"type":"number","title":"Return Pct","description":"Daily return in percent","examples":[-17.97]},"sigma":{"type":"number","title":"Sigma","description":"Std devs of this move from the ticker's recent mean daily return","examples":[-7.2]},"direction":{"type":"string","title":"Direction","examples":["down"]}},"type":"object","required":["ticker","date","return_pct","sigma","direction"],"title":"Anomaly","description":"A statistically outsized daily move."},"ApeWisdomEntry":{"properties":{"date":{"type":"string","title":"Date","examples":["2026-03-24"]},"ticker":{"type":"string","title":"Ticker","examples":["SPY"]},"mentions":{"type":"integer","title":"Mentions","examples":[1247]},"upvotes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Upvotes","examples":[5430]},"rank":{"type":"integer","title":"Rank","examples":[1]}},"type":"object","required":["date","ticker","mentions","rank"],"title":"ApeWisdomEntry"},"BriefMacro":{"properties":{"next_high_impact":{"anyOf":[{"$ref":"#/components/schemas/BriefMacroEvent"},{"type":"null"}]},"high_impact_next_7d":{"type":"integer","title":"High Impact Next 7D","default":0,"examples":[2]}},"additionalProperties":true,"type":"object","title":"BriefMacro"},"BriefMacroEvent":{"properties":{"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date","examples":["2026-07-29"]},"event":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event","examples":["FOMC Rate Decision"]},"days_away":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Away","examples":[3]}},"additionalProperties":true,"type":"object","title":"BriefMacroEvent","description":"The next high-impact scheduled economic event."},"BriefRegime":{"properties":{"regime":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Regime","examples":["risk_on"]},"vix":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vix","examples":[14.2]},"spy_vs_200ma_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Spy Vs 200Ma Pct","description":"SPY's distance above/below its 200-day average, in %.","examples":[6.4]},"position_multiplier":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Position Multiplier","description":"Size multiplier this regime implies (<1 means reduce).","examples":[1.0]},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","examples":["2026-07-24"]}},"additionalProperties":true,"type":"object","title":"BriefRegime","description":"The market risk gate the brief is conditioned on."},"BriefSignal":{"properties":{"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker","examples":["NVDA"]},"direction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Direction","examples":["bullish"]},"event_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Type","examples":["sector_catalyst"]},"second_order":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Second Order","description":"True when the signal is a downstream read-through, not the headline name."},"conviction":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Conviction","description":"Rank score: shrunk type win rate x confidence.","examples":[0.58]},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence","examples":[0.71]},"type_win_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Type Win Rate","description":"Historical resolved win rate for this event_type — near coin-flip for most.","examples":[0.52]},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning"}},"additionalProperties":true,"type":"object","title":"BriefSignal","description":"One precision pick, same selection logic as /signals/best."},"CharacterEra":{"properties":{"era":{"type":"string","title":"Era","examples":["2022"]},"metrics":{"$ref":"#/components/schemas/CharacterMetrics"},"is_ytd":{"type":"boolean","title":"Is Ytd","description":"True for the partial current-year row","default":false},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","examples":["rate-hike bear market"]}},"type":"object","required":["era","metrics"],"title":"CharacterEra","description":"Full-year reference values computed with the identical convention."},"CharacterMetrics":{"properties":{"xs_dispersion_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Xs Dispersion Pct","description":"Median across days of the same-day std-dev of returns across the universe — how differently single names move on the same day","examples":[3.09]},"median_abs_move_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Median Abs Move Pct","description":"Median |daily return| across all ticker-days","examples":[1.33]},"pct_moves_over_2pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pct Moves Over 2Pct","description":"Share of ticker-days with |return| > 2%","examples":[34.6]},"pct_moves_over_5pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pct Moves Over 5Pct","description":"Share of ticker-days with |return| > 5%","examples":[8.9]},"median_intraday_range_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Median Intraday Range Pct","description":"Median (high-low)/close across ticker-days","examples":[2.67]},"spy_median_abs_move_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Spy Median Abs Move Pct","description":"SPY's median |daily return| — the index contrast","examples":[0.55]}},"type":"object","title":"CharacterMetrics","description":"Market-character metrics over one window (live trailing or reference year)."},"CongressTrade":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["MSFT"]},"company_name":{"type":"string","title":"Company Name","examples":["Microsoft Corp"]},"transaction_type":{"type":"string","title":"Transaction Type","examples":["Purchase"]},"amount_range":{"type":"string","title":"Amount Range","examples":["$15,001 - $50,000"]},"politician":{"type":"string","title":"Politician","examples":["Pelosi, Nancy"]},"party":{"type":"string","title":"Party","examples":["D"]},"chamber":{"type":"string","title":"Chamber","examples":["House"]},"filed_date":{"type":"string","title":"Filed Date","examples":["2026-03-20"]},"traded_date":{"type":"string","title":"Traded Date","examples":["2026-03-15"]},"excess_return":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Excess Return","examples":[2.4]}},"type":"object","required":["ticker","company_name","transaction_type","amount_range","politician","party","chamber","filed_date","traded_date"],"title":"CongressTrade"},"CongressTradesResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[50]},"trades":{"items":{"$ref":"#/components/schemas/CongressTrade"},"type":"array","title":"Trades"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["count","trades"],"title":"CongressTradesResponse","description":"Congressional stock trades from STOCK Act disclosures."},"CrossValidation":{"properties":{"flight_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Flight Id"},"signal_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signal Date"},"entity_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Name"},"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker"},"validation_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validation Level","description":"TRIPLE_CONFIRMED, LOBBY_CONFIRMED, HEARING_CONFIRMED, or FLIGHT_ONLY","examples":["TRIPLE_CONFIRMED"]},"lobby_filings":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lobby Filings"},"lobby_total_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lobby Total Amount"},"relevant_hearings":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Relevant Hearings"}},"type":"object","title":"CrossValidation"},"DailyBriefResponse":{"properties":{"as_of":{"type":"string","title":"As Of","examples":["2026-07-24"]},"regime":{"$ref":"#/components/schemas/BriefRegime"},"macro":{"$ref":"#/components/schemas/BriefMacro"},"signals":{"items":{"$ref":"#/components/schemas/BriefSignal"},"type":"array","title":"Signals"},"guidance":{"type":"string","title":"Guidance","description":"One curated line tying regime, picks, and macro together.","examples":["Regime risk_on, VIX 14 — normal sizing. 2 precision signal(s), top: sector_catalyst NVDA."]},"disclaimer":{"type":"string","title":"Disclaimer"}},"additionalProperties":true,"type":"object","required":["as_of","regime","macro","guidance","disclaimer"],"title":"DailyBriefResponse","description":"Response for /signals/brief."},"DailyUsage":{"properties":{"day":{"type":"string","title":"Day","examples":["2026-03-24"]},"requests":{"type":"integer","title":"Requests","examples":[45]},"avg_response_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Response Ms","examples":[120]},"errors":{"type":"integer","title":"Errors","default":0,"examples":[2]}},"type":"object","required":["day","requests"],"title":"DailyUsage"},"DemoCoverage":{"properties":{"ml_models_trained":{"type":"integer","title":"Ml Models Trained","default":0,"examples":[9450]}},"additionalProperties":true,"type":"object","title":"DemoCoverage"},"DemoSnapshotResponse":{"properties":{"demo":{"type":"boolean","title":"Demo","default":true,"examples":[true]},"message":{"type":"string","title":"Message"},"fear_greed":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Fear Greed","description":"Recent stock and crypto fear/greed readings."},"top_reddit":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Top Reddit","description":"Most-mentioned tickers on Reddit, by rank."},"latest_event_signals":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Latest Event Signals"},"coverage":{"$ref":"#/components/schemas/DemoCoverage"}},"additionalProperties":true,"type":"object","required":["message","coverage"],"title":"DemoSnapshotResponse","description":"Response for /demo/snapshot. The 503 path returns {'demo': true, 'error': ...}."},"ETFPullbackActive":{"properties":{"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker","examples":["IWM"]},"fire_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fire Date","examples":["2026-07-22"]},"day_of_window":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Day Of Window","description":"Trading days elapsed since the fire (0 = fired today).","examples":[2]},"actionable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actionable","description":"Plain-language entry guidance for this fire. Mid-window entries say so explicitly — they were not part of the validated timing.","examples":["Fired at the latest close. The validated next_open entry is the NEXT session's open, exiting at the close 5 trading days after the fire."]}},"additionalProperties":true,"type":"object","title":"ETFPullbackActive","description":"An ETF currently inside its 5-day hold window."},"ETFPullbackResponse":{"properties":{"signal":{"type":"string","title":"Signal","examples":["etf_pullback_rsi2"]},"name":{"type":"string","title":"Name"},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","examples":["2026-07-24"]},"computed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computed At","examples":["2026-07-24T13:05:00+00:00"]},"universe":{"items":{"type":"string"},"type":"array","title":"Universe","examples":[["SPY","IWM","VTI","XLY"]]},"universe_unavailable":{"items":{"type":"string"},"type":"array","title":"Universe Unavailable","description":"Universe members with insufficient price history this run."},"data_quality_notes":{"additionalProperties":true,"type":"object","title":"Data Quality Notes","description":"Per-ticker notes about gaps in the price history."},"rule":{"additionalProperties":true,"type":"object","title":"Rule","description":"The pre-registered rule, stated in full."},"active":{"items":{"$ref":"#/components/schemas/ETFPullbackActive"},"type":"array","title":"Active","description":"Live fires. Empty is the normal state — this rule is infrequent by design."},"etfs":{"additionalProperties":true,"type":"object","title":"Etfs","description":"Measured track record keyed by ticker: hit rate vs the above-trend base rate, Wilson 95% lower bound, and per-entry-timing splits."},"entry_timing":{"additionalProperties":true,"type":"object","title":"Entry Timing"},"research_context":{"additionalProperties":true,"type":"object","title":"Research Context","description":"Which kill-tests the rule cleared, and on what sample."},"caveats":{"items":{"type":"string"},"type":"array","title":"Caveats"},"disclaimer":{"type":"string","title":"Disclaimer"}},"additionalProperties":true,"type":"object","required":["signal","name","disclaimer"],"title":"ETFPullbackResponse","description":"Response for /signals/etf-pullback."},"EconomicCalendarResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[12]},"events":{"items":{"$ref":"#/components/schemas/EconomicEvent"},"type":"array","title":"Events"}},"type":"object","required":["count","events"],"title":"EconomicCalendarResponse","description":"Upcoming economic events."},"EconomicEvent":{"properties":{"date":{"type":"string","title":"Date","examples":["2026-03-25"]},"time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time","examples":["08:30"]},"currency":{"type":"string","title":"Currency","default":"USD","examples":["USD"]},"impact":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact","examples":["High"]},"event":{"type":"string","title":"Event","examples":["Consumer Confidence"]},"actual":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actual","examples":["102.4"]},"forecast":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Forecast","examples":["100.0"]},"previous":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Previous","examples":["98.3"]}},"type":"object","required":["date","event"],"title":"EconomicEvent"},"EndpointUsage":{"properties":{"endpoint":{"type":"string","title":"Endpoint","examples":["/api/v1/predictions/latest"]},"requests":{"type":"integer","title":"Requests","examples":[89]}},"type":"object","required":["endpoint","requests"],"title":"EndpointUsage"},"ErrorCode":{"type":"string","enum":["missing_api_key","invalid_api_key","api_key_deactivated","api_key_expired","tier_required","rate_limited_minute","rate_limited_day","bad_request","unauthorized","forbidden","not_found","rate_limited","internal_error","upstream_error","unavailable"],"title":"ErrorCode","description":"Stable, machine-readable reasons a request failed.\n\n``detail`` is written for a person and will be reworded over time. A caller\nthat has to branch — and an agent almost always does — should branch on this\ninstead of pattern-matching prose. The distinctions are the ones that lead to\ngenuinely different behaviour: ``rate_limited_minute`` means wait a moment,\n``rate_limited_day`` means come back tomorrow; ``tier_required`` means offer\nthe human an upgrade, ``api_key_expired`` means ask them to renew, and\n``invalid_api_key`` means stop retrying altogether.\n\nThis list is exhaustive by construction: every error body gets either a code\nraised deliberately or the status-code default from ``_DEFAULT_CODES``, and a\ntest asserts both sets live inside this enum."},"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Human-readable explanation, and where actionable, the next step to take.","examples":["Missing API key. Send your key in the 'X-API-Key' header or as 'Authorization: Bearer <key>'. A free key comes with the free email signup at https://moneysignals.us/#pricing"]},"code":{"$ref":"#/components/schemas/ErrorCode","description":"Stable machine-readable reason. Branch on this, not on `detail` — `detail` is prose and will be reworded.","examples":["missing_api_key"]}},"type":"object","required":["detail","code"],"title":"ErrorResponse","description":"The body of every 4xx this API returns."},"EventSignal":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["NVDA"]},"direction":{"type":"string","title":"Direction","examples":["bullish"]},"confidence":{"type":"number","title":"Confidence","examples":[0.85]},"time_horizon":{"type":"string","title":"Time Horizon","examples":["1-3_days"]},"event_type":{"type":"string","title":"Event Type","examples":["sector_catalyst"]},"reasoning":{"type":"string","title":"Reasoning","examples":["AI chip demand surge driven by datacenter buildout"]},"source_headlines":{"items":{"type":"string"},"type":"array","title":"Source Headlines"},"second_order":{"type":"boolean","title":"Second Order","description":"True if indirect 2nd-order effect","default":false},"signal_date":{"type":"string","title":"Signal Date","examples":["2026-03-24"]},"was_correct":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Was Correct","description":"Post-hoc accuracy (if available)"},"actual_return":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Actual Return","examples":[0.032]},"type_win_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Type Win Rate","description":"Historical win rate of this (event_type, second_order) from resolved signals — how much to trust it","examples":[0.77]},"type_sample_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Type Sample Size","description":"Resolved-signal count behind type_win_rate","examples":[30]},"type_avg_return":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Type Avg Return","description":"Historical average DIRECTION-ADJUSTED return per resolved signal of this type — the P&L in the signal's favor (bullish: +move, bearish/short: -move), NOT the raw price move. The magnitude companion to type_win_rate: a type can win often yet have thin per-signal P&L. E.g. sector_catalyst-2nd ~+0.029 (+2.9%/signal).","examples":[0.029]},"conviction":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Conviction","description":"Ranking score for /signals/best = shrunk type win-rate x confidence (higher = stronger pick)","examples":[0.58]}},"type":"object","required":["ticker","direction","confidence","time_horizon","event_type","reasoning","signal_date"],"title":"EventSignal"},"EventSignalsResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[12]},"signals":{"items":{"$ref":"#/components/schemas/EventSignal"},"type":"array","title":"Signals"}},"type":"object","required":["count","signals"],"title":"EventSignalsResponse","description":"LLM-generated event-driven trade signals."},"EventTypePerformance":{"properties":{"event_type":{"type":"string","title":"Event Type","examples":["sector_catalyst"]},"second_order":{"type":"boolean","title":"Second Order","description":"True = indirect 2nd-order effect (where the edge concentrates)"},"n":{"type":"integer","title":"N","description":"Resolved-signal sample size","examples":[30]},"win_rate":{"type":"number","title":"Win Rate","description":"Share of resolved signals that were correct","examples":[0.767]},"avg_return":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Return","description":"Average DIRECTION-ADJUSTED P&L per resolved signal of this type — the return in the signal's favor (bullish: +price move, bearish/short: -price move), so a correct short counts as a gain, not a loss. The magnitude companion to win_rate (a type can win often yet pay thin). Matches /signals/best type_avg_return for the same type.","examples":[0.0295]},"shrunk_win_rate":{"type":"number","title":"Shrunk Win Rate","description":"Win rate shrunk toward 0.5 (Beta(2.5,2.5) prior) so small samples are pulled to coin-flip — the ranking key","examples":[0.729]},"edge":{"type":"string","title":"Edge","description":"strong / moderate / coin-flip / anti-signal, derived from shrunk_win_rate","examples":["strong"]}},"type":"object","required":["event_type","second_order","n","win_rate","shrunk_win_rate","edge"],"title":"EventTypePerformance","description":"Historical resolved-outcome performance for one (event_type, second_order)."},"FearGreedResponse":{"properties":{"days":{"type":"integer","title":"Days","examples":[7]},"sentiment":{"items":{"$ref":"#/components/schemas/SentimentDay"},"type":"array","title":"Sentiment"}},"type":"object","required":["days","sentiment"],"title":"FearGreedResponse","description":"Fear & Greed index history.","example":{"days":2,"sentiment":[{"aaii_bearish":3.0,"crypto_fear_greed":11,"date":"2026-03-24","stock_fear_greed":15},{"aaii_bearish":3.0,"crypto_fear_greed":12,"date":"2026-03-21","stock_fear_greed":14}]}},"FlightSignal":{"properties":{"tail_number":{"type":"string","title":"Tail Number","examples":["N476BA"]},"entity_name":{"type":"string","title":"Entity Name","examples":["Boeing"]},"entity_type":{"type":"string","title":"Entity Type","examples":["corporate"]},"tickers":{"items":{"type":"string"},"type":"array","title":"Tickers","examples":[["BA"]]},"airport_icao":{"type":"string","title":"Airport Icao","examples":["KHEF"]},"airport_name":{"type":"string","title":"Airport Name","examples":["Manassas Regional"]},"airport_type":{"type":"string","title":"Airport Type","examples":["private"]},"direction":{"type":"string","title":"Direction","examples":["arrival"]},"detected_at":{"type":"string","title":"Detected At","examples":["2026-03-24T15:30:00Z"]},"signal_date":{"type":"string","title":"Signal Date","examples":["2026-03-24"]},"confidence":{"type":"number","title":"Confidence","examples":[0.8]},"context":{"type":"string","title":"Context","examples":["Boeing corporate jet at Manassas Regional (private)"]},"match_source":{"type":"string","title":"Match Source","examples":["known_list"]}},"type":"object","required":["tail_number","entity_name","entity_type","airport_icao","airport_name","airport_type","direction","detected_at","signal_date","confidence","context","match_source"],"title":"FlightSignal"},"FlightSignalsResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[3]},"available":{"type":"boolean","title":"Available","description":"Whether DC flight tracking is currently producing signals. When False, an empty result means the stream is offline (not collected), not that no flights occurred — check `note`.","default":true},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","description":"Latest signal_date on record, or null if none have been collected."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","description":"Human-readable context, set when results are empty or the stream is offline."},"signals":{"items":{"$ref":"#/components/schemas/FlightSignal"},"type":"array","title":"Signals"},"cross_validation":{"items":{"$ref":"#/components/schemas/CrossValidation"},"type":"array","title":"Cross Validation"}},"type":"object","required":["count","signals","cross_validation"],"title":"FlightSignalsResponse","description":"DC-area corporate flight signals with cross-validation.","example":{"count":1,"cross_validation":[{"entity_name":"Boeing","flight_id":1,"lobby_filings":96,"lobby_total_amount":192729000,"relevant_hearings":2,"signal_date":"2026-03-24","ticker":"BA","validation_level":"TRIPLE_CONFIRMED"}],"signals":[{"airport_icao":"KHEF","airport_name":"Manassas Regional","airport_type":"private","confidence":0.8,"context":"Boeing corporate jet at Manassas Regional","detected_at":"2026-03-24T15:30:00Z","direction":"arrival","entity_name":"Boeing","entity_type":"corporate","match_source":"known_list","signal_date":"2026-03-24","tail_number":"N476BA","tickers":["BA"]}]}},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","title":"Status","examples":["ok"]},"db":{"type":"string","title":"Db","examples":["connected"]},"active_keys":{"type":"integer","title":"Active Keys","examples":[5]},"trained_models":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Trained Models","examples":[9450]},"today_predictions":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Today Predictions","examples":[500]},"latest_prediction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Prediction","examples":["2026-03-24T18:00:00"]},"warnings":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Warnings"},"server_time":{"type":"string","title":"Server Time","examples":["2026-03-24T18:32:40.651983"]}},"type":"object","required":["status","db","active_keys","server_time"],"title":"HealthResponse","description":"Service health check.","example":{"active_keys":5,"db":"connected","latest_prediction":"2026-03-24T18:00:00","server_time":"2026-03-24T18:32:40.651983","status":"ok","today_predictions":500,"trained_models":9450}},"Hearing":{"properties":{"hearing_id":{"type":"string","title":"Hearing Id","examples":["63037"]},"title":{"type":"string","title":"Title","examples":["Nomination hearing: Secretary of the Air Force"]},"chamber":{"type":"string","title":"Chamber","examples":["Senate"]},"committee_name":{"type":"string","title":"Committee Name","examples":["Senate Armed Services Committee"]},"committee_code":{"type":"string","title":"Committee Code","examples":["ssas00"]},"hearing_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hearing Date","examples":["2026-03-27"]},"sectors":{"items":{"type":"string"},"type":"array","title":"Sectors","examples":[["Industrials"]]},"tickers":{"items":{"type":"string"},"type":"array","title":"Tickers","examples":[["LMT","RTX","BA"]]},"keywords_matched":{"items":{"type":"string"},"type":"array","title":"Keywords Matched","examples":[["defense","military"]]}},"type":"object","required":["hearing_id","title","chamber","committee_name","committee_code"],"title":"Hearing"},"HearingsResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[5]},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","description":"Latest hearing_date on record, or null if none have been collected."},"stale":{"type":"boolean","title":"Stale","description":"True when the freshest hearing on record is >14 days old — schedule collection is lagging, so recent windows may legitimately be empty.","default":false},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","description":"Human-readable context, set when results are empty or data is stale."},"hearings":{"items":{"$ref":"#/components/schemas/Hearing"},"type":"array","title":"Hearings"}},"type":"object","required":["count","hearings"],"title":"HearingsResponse","description":"Congressional hearing schedules."},"LobbyingFiling":{"properties":{"filing_uuid":{"type":"string","title":"Filing Uuid","examples":["dc430f64-7a60-40be-8e66-12ba1fab465b"]},"registrant_name":{"type":"string","title":"Registrant Name","examples":["BOEING COMPANY"]},"client_name":{"type":"string","title":"Client Name","examples":["BOEING COMPANY"]},"filing_type":{"type":"string","title":"Filing Type","examples":["Q4"]},"filing_year":{"type":"integer","title":"Filing Year","examples":[2025]},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount","examples":[2890000.0]},"dt_posted":{"type":"string","title":"Dt Posted","examples":["2026-01-20T16:00:14-05:00"]},"issues":{"items":{"type":"string"},"type":"array","title":"Issues","examples":[["Aerospace","Defense"]]},"tickers":{"items":{"type":"string"},"type":"array","title":"Tickers","examples":[["BA"]]},"specific_issues":{"items":{"type":"string"},"type":"array","title":"Specific Issues"}},"type":"object","required":["filing_uuid","registrant_name","client_name","filing_type","filing_year","dt_posted"],"title":"LobbyingFiling"},"LobbyingResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[25]},"filings":{"items":{"$ref":"#/components/schemas/LobbyingFiling"},"type":"array","title":"Filings"}},"type":"object","required":["count","filings"],"title":"LobbyingResponse","description":"Lobbying disclosure filings."},"MarketCharacterResponse":{"properties":{"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","examples":["2026-07-09"]},"window_days":{"type":"integer","title":"Window Days","description":"Trading days actually in the live window","examples":[20]},"n_tickers":{"type":"integer","title":"N Tickers","description":"Tickers contributing returns to the window","examples":[712]},"read":{"type":"string","title":"Read","description":"Plain-language classification of current dispersion vs the 2015-2025 full-year range: record_dispersion / elevated / normal / quiet / unavailable","examples":["record_dispersion"]},"dispersion_vs_history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dispersion Vs History","description":"How the live dispersion ranks against the full reference years"},"current":{"$ref":"#/components/schemas/CharacterMetrics"},"reference":{"items":{"$ref":"#/components/schemas/CharacterEra"},"type":"array","title":"Reference"},"note":{"type":"string","title":"Note","description":"Methodology + honest-interpretation caveats"}},"type":"object","required":["window_days","n_tickers","read","current","reference","note"],"title":"MarketCharacterResponse","description":"Live market-character gauge vs a decade of full-year reference values."},"OHLCVBar":{"properties":{"date":{"type":"string","title":"Date","examples":["2026-03-24"]},"open":{"type":"number","title":"Open","examples":[560.12]},"high":{"type":"number","title":"High","examples":[565.89]},"low":{"type":"number","title":"Low","examples":[558.34]},"close":{"type":"number","title":"Close","examples":[562.45]},"volume":{"type":"integer","title":"Volume","examples":[78234500]}},"type":"object","required":["date","open","high","low","close","volume"],"title":"OHLCVBar","description":"Single OHLCV price bar."},"OHLCVResponse":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["SPY"]},"granularity":{"type":"string","title":"Granularity","examples":["1d"]},"count":{"type":"integer","title":"Count","examples":[30]},"bars":{"items":{"$ref":"#/components/schemas/OHLCVBar"},"type":"array","title":"Bars"}},"type":"object","required":["ticker","granularity","count","bars"],"title":"OHLCVResponse","description":"OHLCV price data for a ticker."},"PCRDay":{"properties":{"date":{"type":"string","title":"Date","examples":["2026-03-24"]},"total_pcr":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Pcr","examples":[0.92]},"equity_pcr":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Equity Pcr","examples":[0.68]},"index_pcr":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Index Pcr","examples":[1.24]},"vix_pcr":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vix Pcr","examples":[0.85]}},"type":"object","required":["date"],"title":"PCRDay"},"PCRResponse":{"properties":{"days":{"type":"integer","title":"Days","examples":[7]},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","description":"Date of the most recent PCR value","examples":["2026-03-31"]},"stale":{"type":"boolean","title":"Stale","description":"True if the latest value is more than 7 days old (options-metrics collection may be paused) — treat the PCR as historical, not current.","default":false,"examples":[true]},"pcr":{"items":{"$ref":"#/components/schemas/PCRDay"},"type":"array","title":"Pcr"}},"type":"object","required":["days","pcr"],"title":"PCRResponse","description":"Put/Call ratio history."},"Prediction":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["AAPL"]},"timeframe":{"type":"string","title":"Timeframe","examples":["daily"]},"direction":{"type":"string","title":"Direction","description":"bullish or bearish","examples":["bullish"]},"predicted_return":{"type":"number","title":"Predicted Return","description":"Predicted % return","examples":[0.0234]},"confidence":{"type":"number","title":"Confidence","description":"Model confidence 0-1","examples":[0.8712]},"target_date":{"type":"string","title":"Target Date","examples":["2026-03-25"]},"model_accuracy":{"type":"number","title":"Model Accuracy","description":"Realized OUT-OF-SAMPLE direction accuracy for this timeframe — the share of past resolved predictions that were correct (NOT the inflated training metric). Same value for every row: there is no persistent per-ticker edge, so this is the honest timeframe-level number. See realized_samples for the sample size.","examples":[0.484]},"accuracy_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accuracy Status","description":"'live' — outcomes still resolve daily and model_accuracy is current — or 'archived_sample' — this timeframe's pipeline was discontinued (weekly/monthly stopped 2026-03-23) and model_accuracy describes a closed historical sample, not a live performance metric. See the response-level accuracy_note.","examples":["live"]}},"type":"object","required":["ticker","timeframe","direction","predicted_return","confidence","target_date","model_accuracy"],"title":"Prediction","description":"A single ML prediction for a ticker."},"PredictionDetail":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["AAPL"]},"timeframe":{"type":"string","title":"Timeframe","examples":["daily"]},"direction":{"type":"string","title":"Direction","description":"bullish or bearish","examples":["bullish"]},"predicted_return":{"type":"number","title":"Predicted Return","description":"Predicted % return","examples":[0.0234]},"confidence":{"type":"number","title":"Confidence","description":"Model confidence 0-1","examples":[0.8712]},"target_date":{"type":"string","title":"Target Date","examples":["2026-03-25"]},"model_accuracy":{"type":"number","title":"Model Accuracy","description":"Realized OUT-OF-SAMPLE direction accuracy for this timeframe — the share of past resolved predictions that were correct (NOT the inflated training metric). Same value for every row: there is no persistent per-ticker edge, so this is the honest timeframe-level number. See realized_samples for the sample size.","examples":[0.484]},"accuracy_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accuracy Status","description":"'live' — outcomes still resolve daily and model_accuracy is current — or 'archived_sample' — this timeframe's pipeline was discontinued (weekly/monthly stopped 2026-03-23) and model_accuracy describes a closed historical sample, not a live performance metric. See the response-level accuracy_note.","examples":["live"]},"model_r2":{"type":"number","title":"Model R2","description":"Model R-squared","default":0.0,"examples":[0.42]}},"type":"object","required":["ticker","timeframe","direction","predicted_return","confidence","target_date","model_accuracy"],"title":"PredictionDetail","description":"Prediction with additional model metrics."},"PredictionsResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[50]},"timeframe":{"type":"string","title":"Timeframe","examples":["daily"]},"realized_accuracy":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Realized Accuracy","description":"Realized out-of-sample direction accuracy for this timeframe across ALL resolved predictions (the honest measure of how often these calls are right). Daily ML is near coin-flip; so are the event signals (graded in the open at /signals/best). The one statistically-validated edge is the mechanical ETF pullback rule (/signals/etf-pullback).","examples":[0.484]},"realized_samples":{"type":"integer","title":"Realized Samples","description":"Number of resolved predictions behind realized_accuracy (its sample size).","default":0,"examples":[27932]},"accuracy_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accuracy Status","description":"'live' (outcomes still resolving — the number is current) or 'archived_sample' (this timeframe's pipeline was discontinued; realized_accuracy is a closed historical sample — accuracy_note explains). Weekly/monthly have been archived since 2026-03-23.","examples":["live"]},"accuracy_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accuracy Note","description":"Present when accuracy_status='archived_sample': plain-language framing of the closed sample (date range, size in independent windows, why it cannot establish skill). Null for live timeframes."},"accuracy_sample_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accuracy Sample Start","description":"First resolved target date behind realized_accuracy.","examples":["2026-02-21"]},"accuracy_sample_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accuracy Sample End","description":"Last resolved target date behind realized_accuracy.","examples":["2026-04-21"]},"predictions":{"items":{"$ref":"#/components/schemas/Prediction"},"type":"array","title":"Predictions"}},"type":"object","required":["count","timeframe","predictions"],"title":"PredictionsResponse","description":"Response for /predictions/latest.","example":{"count":2,"predictions":[{"confidence":0.91,"direction":"bullish","model_accuracy":0.484,"predicted_return":0.0312,"target_date":"2026-03-25","ticker":"NVDA","timeframe":"daily"},{"confidence":0.78,"direction":"bearish","model_accuracy":0.484,"predicted_return":-0.0187,"target_date":"2026-03-25","ticker":"TSLA","timeframe":"daily"}],"realized_accuracy":0.484,"realized_samples":27932,"timeframe":"daily"}},"RegimeResponse":{"properties":{"regime":{"additionalProperties":true,"type":"object","title":"Regime"},"vix":{"$ref":"#/components/schemas/VIXData"},"spy":{"$ref":"#/components/schemas/SPYData"}},"type":"object","required":["vix","spy"],"title":"RegimeResponse","description":"Current market regime state.","example":{"regime":{"loss_streak":0,"regime":"normal","size_multiplier":1.0,"spy_vs_200ma_pct":2.3,"vix_level":21.5},"spy":{"date":"2026-03-24","price":562.34},"vix":{"date":"2026-03-24","level":21.5}}},"SPYData":{"properties":{"price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Price","examples":[562.34]},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date","examples":["2026-03-24"]}},"type":"object","title":"SPYData"},"SentimentDay":{"properties":{"date":{"type":"string","title":"Date","examples":["2026-03-24"]},"stock_fear_greed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stock Fear Greed","examples":[15]},"crypto_fear_greed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Crypto Fear Greed","examples":[11]},"aaii_bullish":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Aaii Bullish","examples":[28.4]},"aaii_bearish":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Aaii Bearish","examples":[52.1]}},"type":"object","required":["date"],"title":"SentimentDay"},"SignalPerformanceResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[8]},"note":{"type":"string","title":"Note","examples":["Historical resolved-outcome win rates by event type."]},"types":{"items":{"$ref":"#/components/schemas/EventTypePerformance"},"type":"array","title":"Types"}},"type":"object","required":["count","note","types"],"title":"SignalPerformanceResponse","description":"Per-event-type historical win rates — which signal types to trust.","example":{"count":3,"note":"Historical resolved-outcome win rates by event type, ranked by a sample-size-shrunk win rate. Second-order signals score highest but none currently clears the precision gate; small-n rows are noisy. Not a guarantee — pair with /signals/best.","types":[{"avg_return":0.0295,"edge":"strong","event_type":"sector_catalyst","n":30,"second_order":true,"shrunk_win_rate":0.729,"win_rate":0.767},{"avg_return":0.004,"edge":"moderate","event_type":"macro","n":27,"second_order":true,"shrunk_win_rate":0.547,"win_rate":0.556},{"avg_return":-0.0049,"edge":"anti-signal","event_type":"congress_trade","n":14,"second_order":true,"shrunk_win_rate":0.395,"win_rate":0.357}]}},"SocialSentimentResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[25]},"sentiment":{"items":{"$ref":"#/components/schemas/ApeWisdomEntry"},"type":"array","title":"Sentiment"}},"type":"object","required":["count","sentiment"],"title":"SocialSentimentResponse","description":"ApeWisdom Reddit sentiment data."},"SocialTrend":{"properties":{"platform":{"type":"string","title":"Platform","examples":["reddit"]},"date":{"type":"string","title":"Date","examples":["2026-03-24"]},"ticker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticker","examples":["NVDA"]},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic","examples":["AI chip demand"]},"mentions":{"type":"integer","title":"Mentions","default":0,"examples":[342]},"engagement":{"type":"integer","title":"Engagement","default":0,"examples":[15420]},"sentiment_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sentiment Score","examples":[0.72]},"rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rank","examples":[1]},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["platform","date"],"title":"SocialTrend"},"SocialTrendingResponse":{"properties":{"count":{"type":"integer","title":"Count","examples":[25]},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"trends":{"items":{"$ref":"#/components/schemas/SocialTrend"},"type":"array","title":"Trends"}},"type":"object","required":["count","trends"],"title":"SocialTrendingResponse","description":"Social media trending tickers/topics."},"TickerPredictionsResponse":{"properties":{"ticker":{"type":"string","title":"Ticker","examples":["AAPL"]},"count":{"type":"integer","title":"Count","examples":[6]},"predictions":{"items":{"$ref":"#/components/schemas/PredictionDetail"},"type":"array","title":"Predictions"}},"type":"object","required":["ticker","count","predictions"],"title":"TickerPredictionsResponse","description":"Response for /predictions/{ticker}."},"TrackRecordPending":{"properties":{"count":{"type":"integer","title":"Count","default":0,"examples":[182]},"oldest_signal_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oldest Signal Date","examples":["2026-07-14"]},"newest_signal_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Newest Signal Date","examples":["2026-07-24"]},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"additionalProperties":true,"type":"object","title":"TrackRecordPending","description":"Signals issued but not yet resolvable — published so the ledger can't be cherry-picked."},"TrackRecordResponse":{"properties":{"as_of":{"type":"string","title":"As Of","examples":["2026-07-24T13:05:00.123456"]},"methodology":{"type":"string","title":"Methodology","description":"How outcomes are recorded and why the aggregates are direction-signed."},"signals":{"$ref":"#/components/schemas/TrackRecordTotals"},"second_order":{"anyOf":[{"$ref":"#/components/schemas/TrackRecordSecondOrder"},{"type":"null"}]},"by_type":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"By Type","description":"Resolved performance broken out by event_type."},"cumulative_curve":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Cumulative Curve","description":"Direction-signed cumulative return over signal_date."},"recent_ledger":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Ledger","description":"Per-signal outcomes, wins and losses. actual_return here is the raw price move; direction and was_correct carry the sign."},"pending_resolution":{"$ref":"#/components/schemas/TrackRecordPending"},"disclaimer":{"type":"string","title":"Disclaimer"}},"additionalProperties":true,"type":"object","required":["as_of","methodology","signals","pending_resolution","disclaimer"],"title":"TrackRecordResponse","description":"Response for /track-record. The 503 path returns {'error': ...}."},"TrackRecordSecondOrder":{"properties":{"n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N","examples":[318]},"win_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Win Rate","examples":[0.468]},"avg_return":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Return","description":"Direction-signed P&L per signal (a bearish signal's return is negated).","examples":[0.0002]},"since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since","examples":["2026-02-10"]},"latest_outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Outcome","examples":["2026-07-18"]}},"additionalProperties":true,"type":"object","title":"TrackRecordSecondOrder","description":"Aggregates for second-order signals only."},"TrackRecordTotals":{"properties":{"total":{"type":"integer","title":"Total","description":"Signals ever issued.","default":0,"examples":[1284]},"resolved":{"type":"integer","title":"Resolved","description":"Signals whose horizon has elapsed.","default":0,"examples":[1102]}},"additionalProperties":true,"type":"object","title":"TrackRecordTotals"},"UsageResponse":{"properties":{"key_id":{"type":"integer","title":"Key Id"},"tier":{"type":"string","title":"Tier","examples":["secret"]},"daily_usage":{"items":{"$ref":"#/components/schemas/DailyUsage"},"type":"array","title":"Daily Usage"},"top_endpoints":{"items":{"$ref":"#/components/schemas/EndpointUsage"},"type":"array","title":"Top Endpoints"}},"type":"object","required":["key_id","tier","daily_usage","top_endpoints"],"title":"UsageResponse","description":"API usage statistics."},"VIXData":{"properties":{"level":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Level","examples":[21.5]},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date","examples":["2026-03-24"]}},"type":"object","title":"VIXData"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"YouTubeScoreboardResponse":{"properties":{"signal":{"type":"string","title":"Signal","examples":["youtube_creator_scoreboard"]},"name":{"type":"string","title":"Name"},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","examples":["2026-07-24"]},"computed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computed At","examples":["2026-07-24T13:05:00+00:00"]},"state":{"type":"string","title":"State","description":"'populated' once creators have resolved calls, else 'accumulating' — an empty scoreboard is the honest current state, not an error.","examples":["accumulating"]},"state_note":{"type":"string","title":"State Note"},"methodology":{"type":"string","title":"Methodology"},"graded":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Graded","description":"Per-creator accuracy, ranked by the Wilson 95% lower bound of the hit rate (so 2/2 reads as ~0.31, not 1.00)."},"pending_count":{"type":"integer","title":"Pending Count","description":"Calls logged but not yet resolvable.","default":0,"examples":[21]},"resolved_count":{"type":"integer","title":"Resolved Count","default":0,"examples":[0]},"creators_tracked":{"type":"integer","title":"Creators Tracked","default":0,"examples":[5]},"recent_predictions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Predictions"},"disclaimer":{"type":"string","title":"Disclaimer"}},"additionalProperties":true,"type":"object","required":["signal","name","state","state_note","methodology","disclaimer"],"title":"YouTubeScoreboardResponse","description":"Response for /signals/youtube-scoreboard."}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"},"HTTPBearer":{"type":"http","description":"Alternative to X-API-Key: send your key as `Authorization: Bearer <key>`.","scheme":"bearer"}}},"tags":[{"name":"Signals","description":"Trade signals, graded in the open. The mechanical ETF pullback rule is the one that clears the precision gate today; the LLM event signals publish their live hit rate — losses included — and currently sit near coin-flip in aggregate. Check `/track-record` before acting on any of it."},{"name":"Predictions","description":"Per-ticker directional ML predictions with realized out-of-sample accuracy attached. The accuracy is measured, not backtested — the always-on per-ticker models are near coin-flip, and these endpoints report that."},{"name":"Market Data","description":"Market context: regime, fear & greed, put/call ratio, cross-sectional dispersion, OHLCV history, the economic calendar, and anomaly flags."},{"name":"Social Sentiment","description":"Retail attention: trending tickers and per-ticker sentiment from Reddit and YouTube."},{"name":"Alternative Data","description":"Signals from outside the tape — corporate-jet flight tracking, lobbying disclosures, and congressional hearings."},{"name":"Account","description":"Your key: tier, limits, and usage. Prefer the `X-RateLimit-*` response headers on every call for self-pacing; poll this only for a full picture."},{"name":"Demo","description":"Public, no-key endpoints — the audited track record and a live sample snapshot."},{"name":"System","description":"Service health and status."}]}