{"openapi":"3.1.0","info":{"title":"Starwell API","version":"1.0.0","description":"Verified official statistics for AI agents and applications: harmonized series with provenance on every observation, a verification status on every series, computed answers cited to the official source table, and webhooks on series movement. Series whose license does not permit redistribution are excluded from every surface; direct requests for them return 451.","termsOfService":"https://starwell.dev/terms"},"servers":[{"url":"https://starwell.dev/api/starwell"}],"security":[{"apiKey":[]},{}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Optional: anonymous callers get per-IP preview limits; keys (dlk_live_...) get daily tier quotas with usage metering. Also accepted as X-API-Key. Free keys: POST /v1/keys or the /keys page."}},"schemas":{"Error":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","const":false},"code":{"type":"string","description":"Machine-readable error code, when applicable."},"error":{"type":"string"}}},"Provenance":{"type":"object","description":"Where this exact value came from — stored append-only, never inferred.","required":["sourceUrl","retrievedAt","connectorVersion"],"properties":{"sourceUrl":{"type":"string","description":"The exact source API request or table URL."},"retrievedAt":{"type":"string","format":"date-time"},"connectorVersion":{"type":"string"},"releaseTime":{"type":["string","null"],"format":"date-time"}}},"Verification":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["passing","stale","failing","unverified"],"description":"passing: golden-value + freshness checks pass against the live source. stale: newer official data exists (or the source has not been re-checked within its cadence window). failing: a golden check disagrees with the source — do not rely on it. unverified: not yet through the harness."},"lastVerifiedAt":{"type":["string","null"],"format":"date-time"}}},"License":{"type":"object","properties":{"code":{"type":"string","enum":["public-domain","statcan-open","cc-by-4.0","open-government","third-party-restricted","unknown"]},"url":{"type":["string","null"]},"attribution":{"type":["string","null"],"description":"The exact attribution line to print alongside the data."},"redistributable":{"type":"boolean"},"trainingEligible":{"type":"boolean"}}},"Citation":{"type":"object","properties":{"source":{"type":"string"},"authority":{"type":["string","null"]},"dataset":{"type":"string"},"datasetExternalId":{"type":"string"},"url":{"type":["string","null"],"description":"Human-facing official table page."},"termsUrl":{"type":["string","null"]},"text":{"type":"string","description":"Ready-to-print citation line."}}},"Observation":{"type":"object","required":["period","value","provenance"],"properties":{"period":{"type":"string","format":"date"},"value":{"type":["number","null"],"description":"Null only when status explains it."},"status":{"type":"string","enum":["normal","missing","suppressed","terminated"]},"decimals":{"type":["integer","null"]},"revision":{"type":"integer","description":"Bumps when the source revises the period; history is append-only."},"provenance":{"$ref":"#/components/schemas/Provenance"}}},"CatalogEntry":{"type":"object","properties":{"source":{"type":"string"},"sourceName":{"type":"string"},"authority":{"type":["string","null"]},"termsUrl":{"type":["string","null"]},"seriesId":{"type":"string","description":"Source-native id practitioners already use (e.g. 'UNRATE', 'v41690973')."},"indicator":{"type":"string"},"unit":{"type":["string","null"]},"frequency":{"type":["string","null"]},"geography":{"type":["string","null"]},"startPeriod":{"type":["string","null"],"format":"date"},"endPeriod":{"type":["string","null"],"format":"date"},"verificationStatus":{"type":"string","enum":["passing","stale","failing","unverified"]},"lastVerifiedAt":{"type":["string","null"],"format":"date-time"},"licenseCode":{"type":"string"},"attributionText":{"type":["string","null"]},"redistributable":{"type":"boolean"},"datasetExternalId":{"type":"string"},"datasetTitle":{"type":"string"},"datasetUrl":{"type":["string","null"]}}},"Monitor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"seriesId":{"type":"string"},"webhookUrl":{"type":"string"},"active":{"type":"boolean"},"lastPeriod":{"type":["string","null"],"format":"date"},"lastFiredAt":{"type":["string","null"],"format":"date-time"},"lastDeliveryStatus":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}},"responses":{"BadRequest":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Unknown source, dataset, or series.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"LicenseRestricted":{"description":"The series exists but its license does not permit redistribution; no values are served.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Per-IP preview limit or key quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1":{"get":{"summary":"API index: endpoints and verification-status semantics.","responses":{"200":{"description":"OK"}}}},"/v1/sources":{"get":{"summary":"The official sources served, with dataset/series counts, cadence, and terms links.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"type":"array"}}}}}}}}},"/v1/catalog":{"get":{"summary":"Every served series, flat, in one call — with ranked search.","description":"The right first call for agents: search across series ids, indicators, geographies, and dataset titles, then fetch or pin what you found.","parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":200},"description":"Ranked search: exact series id, then id/indicator prefix, then all-terms substring."},{"name":"source","in":"query","schema":{"type":"string"},"description":"Restrict to one source slug."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000},"description":"Defaults to 50 with q, else all."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CatalogEntry"}},"meta":{"type":"object","properties":{"count":{"type":"integer"},"total":{"type":"integer"},"hasMore":{"type":"boolean"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/v1/sources/{source}/datasets":{"get":{"summary":"Datasets (official releases/tables) in one source.","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/sources/{source}/datasets/{datasetId}":{"get":{"summary":"One dataset with its served series and the citation block.","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string"}},{"name":"datasetId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/sources/{source}/series/{seriesId}":{"get":{"summary":"Full series metadata, verification status with recent checks, license, citation.","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string"}},{"name":"seriesId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"$ref":"#/components/responses/NotFound"},"451":{"$ref":"#/components/responses/LicenseRestricted"}}}},"/v1/sources/{source}/series/{seriesId}/observations":{"get":{"summary":"The values, each with provenance; envelope carries verification, license, citation, honest hasMore.","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string"}},{"name":"seriesId","in":"path","required":true,"schema":{"type":"string"}},{"name":"start","in":"query","schema":{"type":"string","format":"date"}},{"name":"end","in":"query","schema":{"type":"string","format":"date"}},{"name":"latest","in":"query","schema":{"type":"integer","minimum":1,"maximum":5000},"description":"The latest N points (alternative to start/end)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":5000}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0}},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv"]},"description":"csv returns a spreadsheet-ready file with attribution comment lines."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Observation"}},"meta":{"type":"object","properties":{"series":{"type":"object"},"verification":{"$ref":"#/components/schemas/Verification"},"license":{"$ref":"#/components/schemas/License"},"citation":{"$ref":"#/components/schemas/Citation"},"returned":{"type":"integer"},"hasMore":{"type":"boolean"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"451":{"$ref":"#/components/responses/LicenseRestricted"}}}},"/v1/sources/{source}/series/{seriesId}/stats":{"get":{"summary":"Summary statistics: latest, previous, all-time min/max, mean, change vs previous period and vs a year ago.","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string"}},{"name":"seriesId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"type":"object"},"meta":{"type":"object","properties":{"series":{"type":"object"},"verification":{"$ref":"#/components/schemas/Verification"},"license":{"$ref":"#/components/schemas/License"},"citation":{"$ref":"#/components/schemas/Citation"}}}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"451":{"$ref":"#/components/responses/LicenseRestricted"}}}},"/v1/answer":{"post":{"summary":"The flagship: a computed, cited answer from verified data.","description":"Real Python runs in a sandbox over the verified store — nothing is model-estimated. Returns the answer, the chart, the code, and per-series verification + citations. Refuses honestly (422) when no served series can answer. 10-40s on a cache miss; cached answers serve instantly and invalidate when the official data moves.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["question"],"properties":{"question":{"type":"string","minLength":3,"maxLength":500},"series":{"type":"array","maxItems":4,"items":{"type":"object","properties":{"source":{"type":"string"},"seriesId":{"type":"string"}}},"description":"Optional: pin exact series and skip AI resolution."},"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"},"source":{"type":"string","description":"Optional: restrict resolution to one source."}}}}}},"responses":{"200":{"description":"Computed answer with python, chart, citations, verification badges, and honest coverage meta."},"400":{"$ref":"#/components/responses/BadRequest"},"422":{"description":"No served series answers this question (never an invented number).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/keys":{"post":{"summary":"Self-serve free API key (issued instantly, shown once).","security":[{}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"201":{"description":"The raw key (only the hash is stored) with tier quotas."},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/monitors":{"post":{"summary":"Watch a series: webhook on movement (new period or revised value), riding the refresh loop.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source","seriesId","webhookUrl"],"properties":{"source":{"type":"string"},"seriesId":{"type":"string"},"webhookUrl":{"type":"string","description":"https only."}}}}}},"responses":{"201":{"description":"Monitor created; snapshot seeded at the current head (fires on NEXT movement).","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Monitor"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"description":"API key required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"get":{"summary":"List your monitors.","security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Monitor"}}}}}}}}}},"/v1/monitors/{id}":{"delete":{"summary":"Delete one of your monitors.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted."},"404":{"$ref":"#/components/responses/NotFound"}}}},"/mcp":{"post":{"summary":"The remote MCP server (Streamable HTTP, stateless JSON-RPC).","description":"Tools: search_catalog, list_sources, list_datasets, get_series, get_observations, answer, create_monitor, list_monitors, delete_monitor. Same data, same limits, agent-native transport.","responses":{"200":{"description":"JSON-RPC response."}}}}}}