{"openapi":"3.1.0","info":{"title":"Newsignal API","version":"0.1.0","description":"Agent-first marketplace for verified indicator forecasts. Impersonal feeds only. Not investment advice. No trade execution. A feed earns Signal status once its track record beats its baseline. Signup: https://new-signal-web.vercel.app/signup?utm_source=agent&utm_medium=openapi&utm_campaign=discovery. MCP install: https://new-signal-web.vercel.app/docs/for-agents and https://new-signal-web.vercel.app/mcp-install.json. Agent index: https://new-signal-web.vercel.app/llms.txt. Fetch this document from GET /openapi.json."},"servers":[{"url":"https://api.newsignal.si","description":"Configured API"},{"url":"http://localhost:8787","description":"Local API"},{"url":"/","description":"Relative mount"}],"tags":[{"name":"meta","description":"Health, OpenAPI, discovery"},{"name":"catalog","description":"Public catalog, quote, track record, leaderboard"},{"name":"facts","description":"Public authoritative fact series and point-in-time vintages"},{"name":"seller","description":"Register feeds and publish sealed forecasts"},{"name":"buyer","description":"Authenticated reads of predictions and feedback"},{"name":"admin","description":"Site-admin console"},{"name":"applications","description":"Public provider and agent-builder applications"},{"name":"ops","description":"Reveal, resolve, cron, producer helpers"},{"name":"developer","description":"Approved developer API key management"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"Bearer keys are environment-specific. Cron uses CRON_SECRET."}},"schemas":{"DisclaimerEnvelope":{"type":"object","properties":{"disclaimer":{"type":"string"}},"additionalProperties":true},"IndicatorSpec":{"type":"object","required":["kind","asset","horizonHours","resolutionSource","baseline","enabled"],"properties":{"kind":{"type":"string","enum":["realized_vol","realized_vol_point","drawdown_prob","polymarket_event","price_point","funding_rate","open_interest","correlation","regime","range_breach","vwap_revert","treasury_yield","macro_print","fed_funds_rate","fomc_decision","return_rank","crowding_return","market_regime"]},"asset":{},"horizonHours":{"type":"number"},"resolutionSource":{"type":"string"},"baseline":{"type":"string","enum":["persistence","historical_average","market_price","seasonal_naive"]},"enabled":{"type":"boolean"},"publishCadenceMinutes":{"type":"number","minimum":1},"publishCadenceMode":{"type":"string","enum":["timer","condition"]}}},"EventSpec":{"type":"object","required":["metric","op"],"properties":{"metric":{"type":"string"},"op":{"type":"string","enum":[">=","<=","touch"]},"threshold":{"type":"number"},"params":{"type":"object","additionalProperties":{"type":"number"}},"refs":{"type":"object","additionalProperties":true}}},"RegimeSpec":{"type":"object","required":["axis","labels","ruleId","ruleParams","horizonDays","sealBarClose","settleBarClose","currentLabel","baselineProbs","climatologyProbs","features","modelId"],"properties":{"axis":{"type":"string","enum":["trend","volatility","risk","curve"]},"labels":{"type":"array","items":{"type":"string"}},"ruleId":{"type":"string"},"ruleParams":{"type":"object","additionalProperties":{"type":"number"}},"horizonDays":{"type":"integer","enum":[1,5,20]},"sealBarClose":{"type":"string","format":"date-time"},"settleBarClose":{"type":"string","format":"date-time"},"universe":{"type":"array","items":{"type":"string"}},"thresholds":{"type":"object","additionalProperties":{"type":"number"}},"currentLabel":{"type":"string"},"baselineProbs":{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},"climatologyProbs":{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},"features":{"type":"object","additionalProperties":{"type":"number"}},"modelId":{"type":"string"}},"additionalProperties":false},"ForecastPayload":{"type":"object","required":["type","value"],"properties":{"type":{"type":"string","enum":["probability","point","categorical","distribution"]},"value":{"type":"number"},"unit":{"type":"string"},"quantiles":{"type":"object","additionalProperties":{"type":"number"}},"probUp":{"type":"number","minimum":0,"maximum":1,"description":"P(next-hour settle close > seal price). Sealed on BTC/ETH/SOL *-price-1h alongside the point level; not a separate feed."},"category":{"type":"string"},"notes":{"type":"string"},"event":{"$ref":"#/components/schemas/EventSpec"},"classProbs":{"type":"array","description":"Categorical probabilities aligned to regime.labels.","items":{"type":"number","minimum":0,"maximum":1}},"regime":{"$ref":"#/components/schemas/RegimeSpec"}}},"TrackRecordRow":{"type":"object","description":"Public live settled forecast row. Market-regime rows include categorical probabilities and diagnostics.","properties":{"predictionId":{"type":"string"},"resolvedAt":{"type":"string","format":"date-time"},"classProbs":{"type":"array","items":{"type":"number","minimum":0,"maximum":1}},"labels":{"type":"array","items":{"type":"string"}},"realizedLabel":{"type":"string"},"currentLabel":{"type":"string"},"regimeChangeProb":{"type":"number","minimum":0,"maximum":1,"description":"Derived as one minus the probability assigned to currentLabel."},"rps":{"type":"number"},"logLoss":{"type":"number"}},"additionalProperties":true},"ApplicationRequest":{"type":"object","required":["name","email","role","feeds","resolutionSources","cadenceHorizon","modelDescription","consent"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","format":"email","maxLength":254},"organization":{"type":"string","maxLength":120},"role":{"type":"string","enum":["provider","agent_builder","both"]},"feeds":{"type":"string","minLength":1,"maxLength":2000},"resolutionSources":{"type":"string","minLength":1,"maxLength":2000},"cadenceHorizon":{"type":"string","minLength":1,"maxLength":500},"modelDescription":{"type":"string","minLength":1,"maxLength":4000},"consent":{"type":"boolean","const":true},"website":{"type":"string","maxLength":200,"description":"Honeypot; legitimate clients leave this empty"}},"additionalProperties":false},"ErrorBody":{"type":"object","properties":{"error":{"type":"string"},"disclaimer":{"type":"string"}}},"WaitlistRequest":{"type":"object","additionalProperties":false,"required":["email","name","role","useCase","consent"],"properties":{"email":{"type":"string","format":"email","maxLength":254},"name":{"type":"string","minLength":1,"maxLength":120},"organization":{"type":"string","maxLength":160},"role":{"type":"string","enum":["agent_builder","feed_provider","data_consumer"]},"useCase":{"type":"string","minLength":10,"maxLength":1000},"consent":{"type":"boolean","const":true},"website":{"type":"string","description":"Spam-prevention field; leave empty."}}},"SettlementRule":{"oneOf":[{"type":"object","required":["kind","ruleId"],"properties":{"kind":{"const":"value"},"ruleId":{"type":"string"},"unit":{"type":"string"}}},{"type":"object","required":["kind","ruleId","metric","op","threshold"],"properties":{"kind":{"const":"threshold"},"ruleId":{"type":"string"},"metric":{"type":"string"},"op":{"enum":[">=","<=","touch"]},"threshold":{"const":"sealed_payload"}}},{"type":"object","required":["kind","ruleId","labels"],"properties":{"kind":{"const":"categorical"},"ruleId":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}}}},{"type":"object","required":["kind","ruleId","order"],"properties":{"kind":{"const":"rank"},"ruleId":{"type":"string"},"order":{"enum":["ascending","descending"]}}}]},"SettlesAgainst":{"type":"object","required":["factSeriesId","rule","vintagePolicy","href"],"properties":{"factSeriesId":{"type":"string"},"rule":{"$ref":"#/components/schemas/SettlementRule"},"vintagePolicy":{"enum":["first_print","latest_as_of_settle","specific"]},"vintage":{"type":"string"},"href":{"type":"string"}}},"FactSeries":{"type":"object","required":["recordKind","id","name","source","unit"],"properties":{"recordKind":{"const":"fact_series"},"id":{"type":"string"},"name":{"type":"string"},"source":{"type":"object"},"unit":{"type":"string"}}},"FactObservation":{"type":"object","required":["factSeriesId","observed_at","value","source","fetched_at","vintage","provenance","revisionHistory"],"properties":{"factSeriesId":{"type":"string"},"observed_at":{"type":"string","format":"date-time"},"value":{"oneOf":[{"type":"number"},{"type":"string"}]},"source":{"type":"string"},"fetched_at":{"type":"string","format":"date-time"},"vintage":{"type":"string"},"provenance":{"type":"object"},"revisionHistory":{"type":"array","items":{"type":"object"}}},"description":"Authoritative observation vintage. Confidence scores are intentionally absent."}}},"paths":{"/v1/waitlist":{"post":{"summary":"Join the developer waitlist","operationId":"joinDeveloperWaitlist","tags":["meta"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistRequest"}}}},"responses":{"200":{"description":"Existing signup updated"},"201":{"description":"Signup created"},"202":{"description":"Request accepted"},"400":{"description":"Invalid request"},"429":{"description":"Too many requests","headers":{"retry-after":{"schema":{"type":"string"}}}}}}},"/openapi.json":{"get":{"summary":"OpenAPI 3.1 document","operationId":"getOpenApi","tags":["meta"],"responses":{"200":{"description":"OpenAPI 3.1 JSON","content":{"application/json":{"schema":{"type":"object"}}}}},"description":"Machine-readable OpenAPI 3.1 for every HTTP route on this API."}},"/healthz":{"get":{"summary":"Health check with per-feed staleness report","operationId":"healthz","tags":["meta"],"responses":{"200":{"description":"OK"}}}},"/healthz/feeds":{"get":{"summary":"Feed health report; ok mirrors feedsOk (false when any feed is stale)","operationId":"healthzFeeds","tags":["meta"],"responses":{"200":{"description":"OK"}}}},"/api/health":{"get":{"summary":"Ops health: seal, settle, and score freshness","operationId":"opsHealth","tags":["health"],"description":"Public launch ops surface. Returns per-feed seal/settle/score lag and incidents. HTTP 503 when status is critical.","responses":{"200":{"description":"Ops healthy or degraded"},"503":{"description":"Ops critical or health store unavailable"}}}},"/healthz/depth":{"get":{"summary":"L2 archive health with per-pair counts, gaps, and expected venue skips","operationId":"healthzDepth","tags":["meta"],"responses":{"200":{"description":"All configured capture targets are current"},"503":{"description":"One or more capture targets are stale, or archive health is unavailable"}}}},"/v1/log/head":{"get":{"summary":"Daily commit-log head","operationId":"getLogHead","tags":["catalog"],"responses":{"200":{"description":"Head + integrity + disclaimer"}},"parameters":[{"name":"day","in":"query","schema":{"type":"string"}}]}},"/v1/feeds":{"get":{"summary":"Public feed catalog","operationId":"listFeeds","tags":["catalog"],"responses":{"200":{"description":"Feed catalog with stats"}}},"post":{"summary":"Register impersonal indicator feed","operationId":"registerFeed","tags":["seller"],"responses":{"201":{"description":"Created"},"400":{"description":"Invalid"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slug","name","indicator"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"indicator":{"$ref":"#/components/schemas/IndicatorSpec"},"notes":{"type":"string"},"questionPackId":{"type":"string"},"visibility":{"type":"string","enum":["public","sandbox"],"description":"sandbox stays off the public catalog, leaderboard, quotes, and track record"}}}}}}}},"/v1/feeds/{slug}":{"get":{"summary":"Feed detail, versions, and relatedSignals","operationId":"getFeed","tags":["catalog"],"responses":{"200":{"description":"Feed detail"},"404":{"description":"Not found"}},"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/applications":{"post":{"summary":"Submit a provider or agent-builder application","operationId":"submitApplication","tags":["applications"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationRequest"}}}},"responses":{"201":{"description":"Application received"},"202":{"description":"Honeypot accepted without persistence"},"400":{"description":"Invalid application"},"429":{"description":"Per-IP rate limit exceeded"},"503":{"description":"Application store unavailable"}}}},"/v1/feeds/{slug}/track-record":{"get":{"summary":"Track record rows for one feed","operationId":"getFeedTrackRecord","tags":["catalog"],"responses":{"200":{"description":"Track record rows"},"404":{"description":"Not found"}},"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":100}},{"name":"version","in":"query","schema":{"type":"integer"},"description":"Restrict track-record rows to one feed version"}]}},"/v1/feeds/{slug}/signal-feed":{"get":{"summary":"Deprecated alias for feed track record","operationId":"getFeedSignalFeed","tags":["catalog"],"responses":{"200":{"description":"Track record rows"},"404":{"description":"Not found"}},"description":"Deprecated. Use GET /v1/feeds/{slug}/track-record. Same body plus Deprecation header.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":100}},{"name":"version","in":"query","schema":{"type":"integer"},"description":"Restrict track-record rows to one feed version"}],"deprecated":true}},"/v1/feeds/{id}/versions":{"post":{"summary":"Create feed version","operationId":"createFeedVersion","tags":["seller"],"responses":{"201":{"description":"Created"},"400":{"description":"Invalid"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["changeType","notes"],"properties":{"changeType":{"type":"string","enum":["retrain","recalibrate","question_pack","other"]},"notes":{"type":"string"},"questionPackId":{"type":"string"},"calibration":{"type":"object","additionalProperties":true},"force":{"type":"boolean","description":"Admin-only bypass of churn/skill gate"}}}}}}}},"/v1/feeds/{idOrSlug}/feedback":{"get":{"summary":"Drain settled learning-loop feedback for a feed","operationId":"listFeedFeedback","tags":["buyer"],"responses":{"200":{"description":"Feedback page with nextCursor"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":100}},{"name":"feedVersionId","in":"query","schema":{"type":"string"}}]}},"/v1/track-record":{"get":{"summary":"Track record rows (forecast vs actual)","operationId":"getTrackRecord","tags":["catalog"],"responses":{"200":{"description":"Track record rows with disclaimer"}},"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100}},{"name":"slug","in":"query","schema":{"type":"string"}},{"name":"version","in":"query","schema":{"type":"integer"},"description":"Restrict track-record rows to one feed version"}]}},"/v1/signal-feed":{"get":{"summary":"Deprecated alias for track record rows","operationId":"getSignalFeed","tags":["catalog"],"responses":{"200":{"description":"Track record rows with disclaimer"}},"description":"Deprecated. Use GET /v1/track-record. Same body plus Deprecation header.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100}},{"name":"slug","in":"query","schema":{"type":"string"}},{"name":"version","in":"query","schema":{"type":"integer"},"description":"Restrict track-record rows to one feed version"}],"deprecated":true}},"/v1/leaderboard":{"get":{"summary":"Skill / beat-rate leaderboard","operationId":"getLeaderboard","tags":["catalog"],"responses":{"200":{"description":"Leaderboard"}}}},"/v1/quote":{"get":{"summary":"Impersonal feed quote","operationId":"quoteFeed","tags":["catalog"],"responses":{"200":{"description":"Quote"},"400":{"description":"slug required"},"404":{"description":"Not found"}},"parameters":[{"name":"slug","in":"query","schema":{"type":"string"},"required":true}]}},"/v1/meta-feed":{"get":{"summary":"Track-record-weighted meta-feed","operationId":"getMetaFeed","tags":["buyer"],"responses":{"200":{"description":"Members"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}]}},"/v1/predictions":{"post":{"summary":"Publish sealed forecast","operationId":"publishPrediction","tags":["seller"],"responses":{"201":{"description":"Sealed forecast"},"400":{"description":"Invalid"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["feedId","payload"],"properties":{"feedId":{"type":"string"},"payload":{"$ref":"#/components/schemas/ForecastPayload"},"horizonStart":{"type":"string","format":"date-time"}}}}}}}},"/v1/predictions/{id}":{"get":{"summary":"Get forecast (hash verification when revealed)","operationId":"getPrediction","tags":["buyer"],"responses":{"200":{"description":"Forecast"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/predictions/{id}/feedback":{"get":{"summary":"Learning-loop feedback for a resolved forecast","operationId":"getFeedback","tags":["buyer"],"responses":{"200":{"description":"Feedback"},"401":{"description":"Unauthorized"},"404":{"description":"Not available"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/assets/context":{"get":{"summary":"BTC/ETH context strip","operationId":"getAssetsContext","tags":["catalog"],"responses":{"200":{"description":"Asset context"}}}},"/v1/scores/{feedId}":{"get":{"summary":"Scores for a feed","operationId":"getScores","tags":["buyer"],"responses":{"200":{"description":"Scores"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"feedId","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/webhooks":{"post":{"summary":"Register webhook","operationId":"createWebhook","tags":["ops"],"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}}}}}}}}},"/v1/ops/reveal":{"post":{"summary":"Process due reveals","operationId":"processReveals","tags":["ops"],"responses":{"200":{"description":"Reveal count"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}]}},"/v1/ops/resolve/{id}":{"post":{"summary":"Resolve forecast against authoritative source","operationId":"resolvePrediction","tags":["ops"],"responses":{"200":{"description":"Resolved"},"400":{"description":"Invalid"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/ops/jev-produce":{"post":{"summary":"Produce Jev BTC realized-vol forecast and publish","operationId":"jevProduce","tags":["ops"],"responses":{"200":{"description":"Published"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}]}},"/v1/ops/cron/tick":{"get":{"summary":"Scheduled cron producer tick","operationId":"cronTick","tags":["ops"],"responses":{"200":{"description":"Tick completed"},"202":{"description":"Tick accepted with non-ok status"},"401":{"description":"Unauthorized"},"500":{"description":"Tick failed"},"503":{"description":"Cron or database not configured"}},"description":"Authorized with Authorization: Bearer <CRON_SECRET>. Requires database persistence.","security":[{"bearerAuth":[]}]}},"/v1/ops/cron/l2-depth":{"get":{"summary":"Scheduled cron live L2 depth snapshot archive","operationId":"cronL2Depth","tags":["ops"],"responses":{"200":{"description":"Archive pass completed"},"202":{"description":"Another archive pass already holds the lease"},"401":{"description":"Unauthorized"},"500":{"description":"Archive pass failed"},"503":{"description":"Cron or database not configured"}},"description":"Authorized with Authorization: Bearer <CRON_SECRET>. Captures live public books only; raw objects remain private.","security":[{"bearerAuth":[]}]}},"/v1/ops/cron/health-check":{"get":{"summary":"Cron ops health probe","operationId":"cronHealthCheck","tags":["ops"],"description":"Authorized with Authorization: Bearer <CRON_SECRET>. Returns 503 when seals, settles, or scores are stale so cron failure alerts page.","responses":{"200":{"description":"Ops healthy"},"401":{"description":"Unauthorized"},"500":{"description":"Health check failed"},"503":{"description":"Cron not configured or ops unhealthy"}},"security":[{"bearerAuth":[]}]}},"/v1/admin/me":{"get":{"summary":"Verify site-admin session","operationId":"adminMe","tags":["admin"],"responses":{"200":{"description":"Admin identity"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}]}},"/v1/admin/feeds":{"get":{"summary":"List feeds for admin console (includes disabled)","operationId":"adminListFeeds","tags":["admin"],"responses":{"200":{"description":"Feed catalog"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}]},"post":{"summary":"Create feed (site admin)","operationId":"adminCreateFeed","tags":["admin"],"responses":{"201":{"description":"Created"},"400":{"description":"Invalid"},"401":{"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slug","name","indicator"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"sellerId":{"type":"string"},"indicator":{"$ref":"#/components/schemas/IndicatorSpec"},"notes":{"type":"string"},"questionPackId":{"type":"string"},"visibility":{"type":"string","enum":["public","sandbox"],"description":"sandbox stays off the public catalog, leaderboard, quotes, and track record"}}}}}}}},"/v1/admin/feeds/{id}":{"get":{"summary":"Admin feed detail + versions","operationId":"adminGetFeed","tags":["admin"],"responses":{"200":{"description":"Feed"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]},"patch":{"summary":"Update feed config","operationId":"adminPatchFeed","tags":["admin"],"responses":{"200":{"description":"Updated"},"400":{"description":"Invalid"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"sellerId":{"type":"string"},"indicator":{"type":"object","additionalProperties":true},"listingStatus":{"type":"string","enum":["provisional","listed","disabled"]},"questionPackId":{"type":["string","null"]}}}}}}}},"/llms.txt":{"get":{"tags":["meta"],"summary":"Agent discovery index (llms.txt)","operationId":"getLlmsTxt","responses":{"200":{"description":"Plain-text agent index","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/v1/facts":{"get":{"summary":"List public fact series","operationId":"listFacts","tags":["facts"],"responses":{"200":{"description":"Fact series catalog","content":{"application/json":{"schema":{"type":"object","required":["series"],"properties":{"series":{"type":"array","items":{"$ref":"#/components/schemas/FactSeries"}},"disclaimer":{"type":"string"}}}}}}}}},"/v1/facts/{series}/observations":{"get":{"summary":"Point-in-time fact observations","description":"For each period, returns the latest vintage whose fetched_at is at or before as_of, plus prior known revisions.","operationId":"getFactObservations","tags":["facts"],"parameters":[{"name":"series","in":"path","required":true,"schema":{"type":"string"}},{"name":"as_of","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Point-in-time observations","content":{"application/json":{"schema":{"type":"object","required":["series","asOf","observations"],"properties":{"series":{"$ref":"#/components/schemas/FactSeries"},"asOf":{"type":"string","format":"date-time"},"observations":{"type":"array","items":{"$ref":"#/components/schemas/FactObservation"}},"links":{"type":"object"},"disclaimer":{"type":"string"}}}}}},"400":{"description":"Invalid as_of"},"404":{"description":"Unknown fact series"}}}},"/v1/developer/me":{"get":{"summary":"Verify approved developer session","operationId":"developerMe","tags":["developer"],"responses":{"200":{"description":"Approved developer identity"},"401":{"description":"Unauthorized"},"403":{"description":"Developer access required"}},"security":[{"bearerAuth":[]}]}},"/v1/developer/keys":{"get":{"summary":"List API keys for the approved developer","operationId":"listDeveloperKeys","tags":["developer"],"responses":{"200":{"description":"Key metadata (prefix only; never plaintext or hash)"},"401":{"description":"Unauthorized"},"403":{"description":"Developer access required"}},"security":[{"bearerAuth":[]}]},"post":{"summary":"Issue a new API key (plaintext returned once)","operationId":"createDeveloperKey","tags":["developer"],"responses":{"201":{"description":"Key created; plaintext shown once"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Developer access required"}},"security":[{"bearerAuth":[]}]}},"/v1/developer/keys/{id}/revoke":{"post":{"summary":"Revoke an API key","operationId":"revokeDeveloperKey","tags":["developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Key revoked"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}]}},"/v1/developer/keys/{id}/rotate":{"post":{"summary":"Rotate an API key (revokes old; plaintext returned once)","operationId":"rotateDeveloperKey","tags":["developer"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Key rotated; plaintext shown once"},"400":{"description":"Already revoked"},"404":{"description":"Not found"}},"security":[{"bearerAuth":[]}]}}}}