{"openapi":"3.1.0","info":{"title":"KnownAt API","version":"1.0.0","description":"The KnownAt API serves point-in-time market and alternative data for quantitative research,\nbacktesting and live trading systems.\n\n## Getting started\n\n1. Create an API key in the [KnownAt dashboard](https://knownat.com/dashboard/api-keys).\n2. Verify it against `GET /v1/account/key`.\n3. Discover what is available with `GET /v1/datasets`.\n\n```bash\ncurl \"https://api.knownat.com/v1/datasets?limit=10\" \\\n  -H \"Authorization: Bearer kat_live_...\"\n```\n\n## Authentication\n\nEvery endpoint except `/health`, `/health/ready` and `/v1/status` requires an API key,\nsent as a bearer token:\n\n```http\nAuthorization: Bearer kat_live_xxxxxxxx\n```\n\nKeys come in two environments. `kat_test_` keys are for development and integration tests;\n`kat_live_` keys carry production quotas. KnownAt stores only a SHA-256 hash of a key and\ncannot recover it — if you lose one, revoke it and issue another.\n\n### Scopes\n\nEach key carries an explicit scope set, and a request outside it fails with\n`INSUFFICIENT_SCOPE` rather than returning partial data.\n\n| Scope | Grants |\n| --- | --- |\n| `account:read` | Account metadata, plan, usage counters |\n| `datasets:read` | Dataset catalog and schemas |\n| `datasets:download` | Bulk dataset downloads |\n| `polymarket:read` | Polymarket datasets |\n| `hyperliquid:read` | Hyperliquid datasets |\n| `live:read` | Live streams |\n\n## Errors\n\nEvery error shares one envelope. Branch on `error.code`; never parse `error.message`,\nwhich is written for humans and changes without notice.\n\n```json\n{\n  \"error\": {\n    \"code\": \"INVALID_PARAMETER\",\n    \"message\": \"Parameter 'start' must be before 'end'.\",\n    \"request_id\": \"req_01J8ZC4V6QK7M3B0YHP2R9TAXD\",\n    \"details\": {}\n  }\n}\n```\n\nEvery response carries an `x-request-id` header, echoed in `error.request_id`. Quote it to\nsupport and the full path of that request can be retrieved from the logs.\n\n## Rate limits\n\nLimits apply per API key, not per IP address, so a client running across a serverless fleet\nis measured as one customer. Responses carry `ratelimit-limit` and `ratelimit-policy`;\na rejection carries `retry-after` and the code `RATE_LIMIT_EXCEEDED`.\n\n| Plan | Requests / minute | Requests / month |\n| --- | --- | --- |\n| Free | 60 | 10,000 |\n| Starter | 100 | 100,000 |\n| Pro | 1,000 | 1,000,000 |\n| Enterprise | custom | custom |\n\nBulk and other expensive requests draw on an additional, smaller budget.\n\n## Pagination\n\nList endpoints are cursor-paginated. Pass `meta.next_cursor` back as `cursor` and iterate\nuntil `meta.has_more` is false:\n\n```python\ncursor, rows = None, []\nwhile True:\n    page = requests.get(\n        \"https://api.knownat.com/v1/datasets\",\n        headers={\"Authorization\": f\"Bearer {key}\"},\n        params={\"limit\": 1000, **({\"cursor\": cursor} if cursor else {})},\n    ).json()\n    rows += page[\"data\"]\n    if not page[\"meta\"][\"has_more\"]:\n        break\n    cursor = page[\"meta\"][\"next_cursor\"]\n```\n\nOffset pagination is deliberately not offered: on an append-only dataset it silently skips\nand duplicates records between pages. Cursors are opaque, expire after 24 hours, and are\nbound to the filters they were issued with — changing a filter mid-scan returns\n`INVALID_CURSOR` instead of a subtly wrong result set.\n\n## Timestamps and point-in-time semantics\n\nAll timestamps are UTC ISO 8601 with millisecond precision. Point-in-time datasets carry\nthree of them:\n\n| Field | Meaning |\n| --- | --- |\n| `source_timestamp` | When the event happened, according to the source |\n| `received_at` | When KnownAt received it |\n| `ingested_at` | When KnownAt persisted it to queryable storage |\n\nThe distinction is what makes a backtest honest: `source_timestamp` tells you when\nsomething happened, `received_at` tells you when you could have known about it. A strategy\nevaluated against `source_timestamp` alone assumes information it could not have had.\n\n## Data freshness\n\n`GET /v1/status` reports three separate lags per feed, because they fail for different\nreasons: a stale source lag means the venue is quiet or down, a stale receive lag means our\ncollector lost its connection, and a fresh receive lag with a stale write lag means events\nare arriving but not being stored.\n\n## Live data\n\nLive data will be delivered over WebSocket rather than REST polling. Polling a tick endpoint\nis neither cheap for you nor kind to your rate limit; the streaming interface is documented\nseparately when a feed becomes available.\n\n## Bulk downloads\n\nLarge historical ranges are served as Parquet through signed download URLs rather than as\none enormous JSON response. REST endpoints are for queries; bulk history is for pipelines.","contact":{"name":"KnownAt support","url":"https://knownat.com","email":"support@knownat.com"},"termsOfService":"https://knownat.com/terms"},"servers":[{"url":"https://api.knownat.com","description":"Production"},{"url":"https://api-staging.knownat.com","description":"Staging"}],"security":[{"apiKey":[]}],"tags":[{"name":"System","description":"Health, availability and data freshness."},{"name":"Account","description":"API key verification and usage counters."},{"name":"Datasets","description":"Catalog of the datasets KnownAt publishes."}],"x-knownat-release":"v0-aeebd4c","x-knownat-guide":[{"id":"getting-started","title":"Getting started","summary":"From a fresh API key to your first response.","blocks":[{"kind":"text","text":"The KnownAt API serves point-in-time market and alternative data for quantitative research, backtesting and live trading systems. It is a read-only HTTP API: every endpoint is a `GET`, every response is JSON, and every field is documented."},{"kind":"list","ordered":true,"items":["Create an API key in the [KnownAt dashboard](https://knownat.com/dashboard/api-keys). The key is shown once and stored only as a hash — we cannot recover it for you.","Confirm it works against `GET /v1/account/key`.","Discover what is available with `GET /v1/datasets`."]},{"kind":"code","language":"bash","code":"curl \"https://api.knownat.com/v1/datasets?limit=10\" \\\n  -H \"Authorization: Bearer kat_live_...\""},{"kind":"text","text":"The base URL is `https://api.knownat.com`. Every path is versioned; there is no unversioned alias."}]},{"id":"authentication","title":"Authentication","summary":"Bearer API keys, test and live environments, and scopes.","blocks":[{"kind":"text","text":"Every endpoint except `/health`, `/health/ready` and `/v1/status` requires an API key, sent as a bearer token."},{"kind":"code","language":"http","code":"Authorization: Bearer kat_live_xxxxxxxx"},{"kind":"text","text":"Keys come in two environments. `kat_test_` keys are for development and integration tests; `kat_live_` keys carry production quotas. KnownAt stores only a SHA-256 hash of a key, so a lost key is replaced, never recovered."},{"kind":"note","text":"Treat a key like a password: keep it server-side, never commit it, and never ship it to a browser. Issue a separate key per application so one can be revoked without disrupting the others."},{"kind":"text","text":"**Scopes.** Each key carries an explicit scope set. A request outside it fails with `INSUFFICIENT_SCOPE` rather than returning partial data."},{"kind":"table","head":["Scope","Grants"],"rows":[["`account:read`","Account metadata, plan and usage counters"],["`datasets:read`","Dataset catalog and schemas"],["`datasets:download`","Bulk dataset downloads"],["`polymarket:read`","Polymarket datasets"],["`hyperliquid:read`","Hyperliquid datasets"],["`live:read`","Live streams"]]}]},{"id":"errors","title":"Errors","summary":"One envelope, stable codes, and a request ID for support.","blocks":[{"kind":"text","text":"Every error shares one envelope. Branch on `error.code`; never parse `error.message`, which is written for humans and changes without notice."},{"kind":"code","language":"json","code":"{\n  \"error\": {\n    \"code\": \"INVALID_PARAMETER\",\n    \"message\": \"Parameter 'start' must be before 'end'.\",\n    \"request_id\": \"req_01J8ZC4V6QK7M3B0YHP2R9TAXD\",\n    \"details\": {}\n  }\n}"},{"kind":"table","head":["Code","Status","Meaning"],"rows":[["`INVALID_API_KEY`","401","Missing, malformed, expired or revoked key"],["`INSUFFICIENT_SCOPE`","403","Valid key, but it lacks the scope this endpoint needs"],["`INVALID_PARAMETER`","400","A request parameter failed validation"],["`INVALID_CURSOR`","400","Cursor is malformed, expired, or from different filters"],["`DATASET_NOT_FOUND`","404","No such dataset is available to this key"],["`DATA_NOT_AVAILABLE`","404","No data for this account or time range"],["`RATE_LIMIT_EXCEEDED`","429","Plan rate limit spent; see `retry-after`"],["`UPSTREAM_DELAYED`","503","The underlying feed is beyond its lag budget"],["`SERVICE_UNAVAILABLE`","503","A dependency is unavailable — retry with backoff"],["`INTERNAL_ERROR`","500","Unexpected failure; quote the request ID"]]},{"kind":"text","text":"Every response carries an `x-request-id` header, echoed in `error.request_id`. Quote it to support and the full path of that request can be retrieved from the logs."}]},{"id":"rate-limits","title":"Rate limits","summary":"Measured per API key, not per IP address.","blocks":[{"kind":"text","text":"Limits apply per API key, so a client running across a serverless fleet is measured as one customer rather than punished for its address count. Successful responses carry `ratelimit-limit` and `ratelimit-policy`; a rejection carries `retry-after` and the code `RATE_LIMIT_EXCEEDED`."},{"kind":"table","head":["Plan","Requests / minute","Requests / month","Bandwidth / month"],"rows":[["Free","60","10,000","1 GB"],["Starter","100","100,000","10 GB"],["Pro","1,000","1,000,000","100 GB"],["Enterprise","custom","custom","custom"]]},{"kind":"text","text":"Bulk and other expensive requests draw on an additional, smaller budget so that one heavy scan cannot crowd out your own interactive queries. Track consumption against your plan with `GET /v1/account/usage`."}]},{"id":"pagination","title":"Pagination","summary":"Cursor-based, because offsets skip and duplicate rows.","blocks":[{"kind":"text","text":"List endpoints are cursor-paginated. Pass `meta.next_cursor` back as `cursor` and iterate until `meta.has_more` is false."},{"kind":"code","language":"python","code":"cursor, rows = None, []\nwhile True:\n    page = requests.get(\n        \"https://api.knownat.com/v1/datasets\",\n        headers={\"Authorization\": f\"Bearer {key}\"},\n        params={\"limit\": 1000, **({\"cursor\": cursor} if cursor else {})},\n    ).json()\n    rows += page[\"data\"]\n    if not page[\"meta\"][\"has_more\"]:\n        break\n    cursor = page[\"meta\"][\"next_cursor\"]"},{"kind":"text","text":"Offset pagination is deliberately not offered. On an append-only dataset, `?page=18272` silently skips and duplicates records between pages as rows arrive — the failure is invisible until a backtest is already wrong."},{"kind":"text","text":"Cursors are opaque, expire after 24 hours, and are bound to the filters they were issued with. Changing a filter mid-scan returns `INVALID_CURSOR` instead of a subtly incomplete result set. Page size may change between pages."}]},{"id":"timestamps","title":"Timestamps","summary":"UTC ISO 8601, with millisecond precision, everywhere.","blocks":[{"kind":"text","text":"Every timestamp the API emits is UTC ISO 8601 with millisecond precision, for example `2026-08-28T10:00:00.000Z`. The API never returns local time, epoch seconds, or a datetime without an offset."},{"kind":"text","text":"Timestamp parameters accept the same format. A range is half-open: `start` is inclusive, `end` is exclusive, so consecutive ranges tile without overlapping."}]},{"id":"point-in-time","title":"Point-in-time semantics","summary":"The difference between when something happened and when you could have known.","blocks":[{"kind":"text","text":"Point-in-time datasets carry three timestamps rather than one. Which you filter on decides whether a backtest is honest."},{"kind":"table","head":["Field","Meaning"],"rows":[["`source_timestamp`","When the event happened, according to the source"],["`received_at`","When KnownAt received it"],["`ingested_at`","When KnownAt persisted it to queryable storage"]]},{"kind":"text","text":"Where the source guarantees it, `source_timestamp <= received_at <= ingested_at` holds for every record."},{"kind":"note","text":"A strategy evaluated against `source_timestamp` alone assumes information it could not have had at the time. `received_at` is what you could actually have acted on. This distinction is the whole reason KnownAt stores all three."},{"kind":"text","text":"Check `is_point_in_time` on a dataset before relying on this: it tells you whether the dataset records both source and ingestion time."}]},{"id":"data-freshness","title":"Data freshness","summary":"Three lags, because a pipeline fails in three different places.","blocks":[{"kind":"text","text":"`GET /v1/status` reports three separate lags per feed. One number would hide which part of the chain broke."},{"kind":"table","head":["Signal","What a stale value means"],"rows":[["`source_lag_ms`","The venue is quiet, or has stopped publishing"],["`receive_lag_ms`","Our collector lost its connection to the source"],["`write_lag_ms`","Events are arriving but are not being persisted"]]},{"kind":"text","text":"A fresh `receive_lag_ms` with a stale `write_lag_ms` is the signature of a persistence failure: data is flowing in but is not queryable yet. Feed status is derived per feed against its own lag budget, because a tick stream and a daily dataset cannot share one threshold."}]},{"id":"live-and-bulk","title":"Live and bulk data","summary":"What REST is for, and what it is not for.","blocks":[{"kind":"text","text":"REST endpoints are for queries: historical windows, snapshots, metadata and catalog reads."},{"kind":"text","text":"**Live data** will be delivered over WebSocket rather than REST polling. Polling a tick endpoint is neither cheap for you nor kind to your rate limit; the streaming interface is documented separately as feeds become available."},{"kind":"text","text":"**Bulk history** is served as Parquet through signed download URLs, not as one enormous JSON response. Large ranges belong in a columnar format your pipeline can read directly."}]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A KnownAt API key: `Authorization: Bearer kat_live_...`."}},"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"],"description":"Whether the Worker itself is serving requests."},"service":{"type":"string","example":"knownat-api"},"environment":{"type":"string","example":"production"},"release":{"type":"string","description":"Release identifier of the running deployment, for correlating errors with a deploy.","example":"2026.08.28-1"},"git_sha":{"type":"string","example":"23f6bc9"},"generated_at":{"type":"string","format":"date-time","description":"UTC timestamp in ISO 8601 format with millisecond precision.","example":"2026-08-28T10:00:00.000Z"}},"required":["status","service","environment","release","git_sha","generated_at"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["INVALID_API_KEY","INSUFFICIENT_SCOPE","RATE_LIMIT_EXCEEDED","INVALID_PARAMETER","INVALID_CURSOR","DATA_NOT_AVAILABLE","DATASET_NOT_FOUND","UPSTREAM_DELAYED","SERVICE_UNAVAILABLE","INTERNAL_ERROR"],"description":"Stable machine-readable error code. Branch on this, never on `message`.","example":"INVALID_PARAMETER"},"message":{"type":"string","description":"Human-readable explanation. Not stable across releases.","example":"Parameter 'start' must be before 'end'."},"request_id":{"type":"string","pattern":"^req_[0-9A-HJKMNP-TV-Z]{26}$","description":"Unique identifier for this request. Quote it to support to have the full request path retrieved from the logs.","example":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"},"details":{"type":"object","additionalProperties":{},"description":"Additional machine-readable context, present for some codes.","example":{"parameter":"limit"}}},"required":["code","message","request_id"]}},"required":["error"]},"ReadinessResponse":{"allOf":[{"$ref":"#/components/schemas/HealthResponse"},{"type":"object","properties":{"dependencies":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"database"},"healthy":{"type":"boolean"},"latency_ms":{"type":"integer","minimum":0},"error":{"type":["string","null"]}},"required":["name","healthy","latency_ms","error"]},"description":"Result of probing each dependency required to serve requests."}},"required":["dependencies"]}]},"DataHealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["operational","delayed","degraded","offline","maintenance"],"description":"`operational` — the feed is within its documented lag budget. `delayed` — data is still arriving but later than the budget allows. `degraded` — lag is severe enough to affect most use cases. `offline` — no recent data has been persisted. `maintenance` — a planned interruption, announced in advance.","example":"operational"},"generated_at":{"type":"string","format":"date-time","description":"UTC timestamp in ISO 8601 format with millisecond precision.","example":"2026-08-28T10:00:00.000Z"},"feeds":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/StreamStatus"},{"type":"object","properties":{"feed":{"type":"string","description":"Feed identifier, `dataset.stream`.","example":"polymarket.trades"},"dataset":{"type":"string","example":"polymarket"},"stream":{"type":"string","example":"trades"}},"required":["feed","dataset","stream"]}]},"description":"Flat list of every collector heartbeat, for internal dashboards and the watchdog."}},"required":["status","generated_at","feeds"]},"StreamStatus":{"type":"object","properties":{"status":{"type":"string","enum":["operational","delayed","degraded","offline","maintenance"],"description":"`operational` — the feed is within its documented lag budget. `delayed` — data is still arriving but later than the budget allows. `degraded` — lag is severe enough to affect most use cases. `offline` — no recent data has been persisted. `maintenance` — a planned interruption, announced in advance.","example":"operational"},"source_lag_ms":{"type":["integer","null"],"description":"Time since the newest event timestamp reported by the source. Grows when the source itself stops producing data.","example":420},"receive_lag_ms":{"type":["integer","null"],"description":"Time since KnownAt last received an event. Grows when the collector loses its connection to the source.","example":380},"write_lag_ms":{"type":["integer","null"],"description":"Time since KnownAt last persisted an event. Fresh receive lag with stale write lag means the pipeline, not the source, is failing.","example":410},"last_source_timestamp":{"type":["string","null"],"format":"date-time","description":"Event time of the newest record, as reported by the source.","example":"2026-08-28T10:00:00.000Z"},"last_received_at":{"type":["string","null"],"format":"date-time","description":"When KnownAt received that record.","example":"2026-08-28T10:00:00.000Z"},"last_written_at":{"type":["string","null"],"format":"date-time","description":"When KnownAt persisted that record to queryable storage.","example":"2026-08-28T10:00:00.000Z"},"events_per_second":{"type":"number","minimum":0,"description":"Recent throughput of the feed.","example":128.5}},"required":["status","source_lag_ms","receive_lag_ms","write_lag_ms","last_source_timestamp","last_received_at","last_written_at","events_per_second"]},"StatusResponse":{"type":"object","properties":{"status":{"type":"string","enum":["operational","delayed","degraded","offline","maintenance"],"description":"Worst status across every feed. Use it as a single health signal.","example":"operational"},"generated_at":{"type":"string","format":"date-time","description":"UTC timestamp in ISO 8601 format with millisecond precision.","example":"2026-08-28T10:00:00.000Z"},"datasets":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/StreamStatus"}},"description":"Per-dataset, per-stream freshness, keyed by dataset slug and then by stream name.","example":{"polymarket":{"trades":{"status":"operational","source_lag_ms":420,"receive_lag_ms":380,"write_lag_ms":410,"last_source_timestamp":"2026-08-28T09:59:59.580Z","last_received_at":"2026-08-28T09:59:59.620Z","last_written_at":"2026-08-28T09:59:59.590Z","events_per_second":128.5}}}}},"required":["status","generated_at","datasets"]},"KeyVerification":{"type":"object","properties":{"authenticated":{"type":"boolean","enum":[true]},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Identifier of the presented key, safe to log."},"name":{"type":"string","description":"Label given to the key in the dashboard.","example":"backtest-runner"},"environment":{"type":"string","enum":["test","live"],"description":"Whether this is a test or live key, derived from its prefix."},"scopes":{"type":"array","items":{"type":"string"},"description":"Permissions granted to this key.","example":["account:read","datasets:read"]},"plan":{"type":"string","example":"pro"},"expires_at":{"type":["string","null"],"format":"date-time","description":"Expiry, or null for a non-expiring key.","example":"2026-08-28T10:00:00.000Z"}},"required":["id","name","environment","scopes","plan","expires_at"],"description":"Everything the API knows about the presented key. The key itself is never echoed."}},"required":["authenticated","key"]},"UsageResponse":{"type":"object","properties":{"plan":{"type":"string","description":"Plan the limits below are drawn from.","example":"pro"},"period":{"type":"object","properties":{"start":{"type":"string","format":"date-time","description":"Start of the current usage period, inclusive.","example":"2026-08-28T10:00:00.000Z"},"end":{"type":"string","format":"date-time","description":"End of the current usage period, exclusive.","example":"2026-08-28T10:00:00.000Z"}},"required":["start","end"],"description":"Calendar month in UTC that these counters cover."},"requests":{"type":"object","properties":{"used":{"type":"integer","minimum":0,"example":182341},"limit":{"type":"integer","minimum":0,"example":1000000}},"required":["used","limit"],"description":"Billable API requests consumed in the period."},"bandwidth_gb":{"type":"object","properties":{"used":{"type":"number","minimum":0,"example":14.8},"limit":{"type":"number","minimum":0,"example":100}},"required":["used","limit"],"description":"Response bytes served in the period, in gibibytes."},"rate_limited_requests":{"type":"integer","minimum":0,"description":"Requests rejected with RATE_LIMIT_EXCEEDED in the period. A persistently non-zero value means the plan is undersized.","example":0}},"required":["plan","period","requests","bandwidth_gb","rate_limited_requests"]},"LatestPolymarketMarketSnapshots":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PolymarketMarketSnapshot"},"description":"Page of records, in the endpoint’s documented order."},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"PolymarketMarketSnapshot":{"type":"object","properties":{"observed_at":{"type":"string","format":"date-time","description":"UTC time at which the collector started this Polymarket snapshot.","example":"2026-08-28T10:00:00.000Z"},"available_at":{"type":"string","format":"date-time","description":"UTC time at which this response was available to the KnownAt collector.","example":"2026-08-28T10:00:00.000Z"},"ingested_at":{"type":"string","format":"date-time","description":"UTC time at which ClickHouse persisted this row.","example":"2026-08-28T10:00:00.000Z"},"market_id":{"type":"string","minLength":1,"description":"Polymarket condition identifier shared by all outcome tokens in the market.","example":"0x4f9f9d9c6d87a56ec2d8b65f9303e366"},"token_id":{"type":"string","minLength":1,"description":"Polymarket CLOB token identifier for this outcome.","example":"2174265494803246004871024487728592001"},"outcome":{"type":"string","minLength":1,"description":"Human-readable market outcome represented by the token.","example":"Yes"},"price":{"type":"number","minimum":0,"maximum":1,"description":"Snapshot price quoted by Polymarket, from 0 through 1.","example":0.63}},"required":["observed_at","available_at","ingested_at","market_id","token_id","outcome","price"]},"ListMeta":{"type":"object","properties":{"records":{"type":"integer","minimum":0,"description":"Number of records in this page.","example":100},"next_cursor":{"type":["string","null"],"description":"Cursor for the next page, or null when the scan is complete.","example":"eyJ2IjoxLCJxIjoiL3YxL2RhdGFzZXRzPyIsImsiOlsicG9seW1hcmtldC10cmFkZXMiXSwidCI6MTc5MjE0NDAwMDAwMH0.Xn4Qk9mWvS0"},"has_more":{"type":"boolean","description":"Whether more records exist after this page.","example":true},"generated_at":{"type":"string","format":"date-time","description":"When this response was produced by the API.","example":"2026-08-28T10:00:00.000Z"}},"required":["records","next_cursor","has_more","generated_at"]},"DatasetList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Dataset"},"description":"Page of records, in the endpoint’s documented order."},"meta":{"$ref":"#/components/schemas/ListMeta"}},"required":["data","meta"]},"Dataset":{"type":"object","properties":{"slug":{"type":"string","description":"Stable dataset identifier used in every other endpoint path."},"title":{"type":"string","description":"Human-readable dataset name."},"description":{"type":"string","description":"What the dataset contains and how it is collected."},"category":{"type":"string","description":"Catalog grouping, e.g. `prediction-markets`."},"source":{"type":"object","properties":{"name":{"type":"string","description":"Origin of the data."},"url":{"type":["string","null"],"description":"Public reference for the source, when one exists."},"license":{"type":["string","null"],"description":"Licensing terms KnownAt redistributes under."}},"required":["name","url","license"],"description":"Provenance of the dataset."},"update_frequency":{"type":"string","description":"How often new records land, e.g. `realtime`, `hourly`, `daily`."},"access_formats":{"type":"array","items":{"type":"string"},"description":"Formats this dataset can be retrieved in. Large ranges should use `parquet` bulk downloads.","example":["json","parquet"]},"coverage":{"type":"object","properties":{"earliest_available_at":{"type":["string","null"],"format":"date-time","description":"Oldest record available. Null while the dataset is still backfilling.","example":"2026-08-28T10:00:00.000Z"},"latest_available_at":{"type":["string","null"],"format":"date-time","description":"Newest record available at the time of this response.","example":"2026-08-28T10:00:00.000Z"}},"required":["earliest_available_at","latest_available_at"],"description":"Historical availability window."},"row_count":{"type":"integer","minimum":0,"description":"Approximate number of records currently queryable."},"is_point_in_time":{"type":"boolean","description":"Whether the dataset records both source and ingestion time, making it safe for point-in-time backtests."},"updated_at":{"type":"string","format":"date-time","description":"When this catalog entry last changed.","example":"2026-08-28T10:00:00.000Z"}},"required":["slug","title","description","category","source","update_frequency","access_formats","coverage","row_count","is_point_in_time","updated_at"]},"DatasetDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DatasetDetail"}},"required":["data"]},"DatasetDetail":{"allOf":[{"$ref":"#/components/schemas/Dataset"},{"type":"object","properties":{"columns":{"type":"array","items":{"$ref":"#/components/schemas/DatasetColumn"},"description":"Column schema in the order the data endpoints return them."}},"required":["columns"]}]},"DatasetColumn":{"type":"object","properties":{"name":{"type":"string","description":"Column name as returned by the data endpoints."},"data_type":{"type":"string","description":"Storage type, e.g. `timestamptz`, `numeric`, `text`."},"description":{"type":"string","description":"Meaning of the column."},"nullable":{"type":"boolean","description":"Whether the column may be null."},"semantic_role":{"type":["string","null"],"description":"Point-in-time role of the column: `source_timestamp`, `received_at`, `ingested_at`, or null for ordinary fields.","example":"source_timestamp"}},"required":["name","data_type","description","nullable","semantic_role"]}},"parameters":{}},"paths":{"/health":{"get":{"tags":["System"],"summary":"Liveness probe","description":"Reports whether the API Worker is running. This endpoint performs no dependency checks and no authentication, so it stays answerable during a database outage and is safe for a high-frequency external uptime monitor. Use `/health/ready` to check dependencies and `/v1/status` to check data freshness.","security":[],"responses":{"200":{"description":"The Worker is running.","content":{"application/json":{"example":{"status":"ok","service":"knownat-api","environment":"production","release":"2026.08.28-1","git_sha":"23f6bc9","generated_at":"2026-08-28T10:00:00.000Z"},"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health/ready":{"get":{"tags":["System"],"summary":"Readiness probe","description":"Probes every dependency required to serve API traffic and reports each one individually with its latency. Returns 503 when any dependency is unhealthy, so a load balancer or deployment gate can act on it. Slower than `/health`: do not poll it at high frequency.","security":[],"responses":{"200":{"description":"Every dependency is healthy.","content":{"application/json":{"example":{"status":"ok","service":"knownat-api","environment":"production","release":"2026.08.28-1","git_sha":"23f6bc9","generated_at":"2026-08-28T10:00:00.000Z","dependencies":[{"name":"database","healthy":true,"latency_ms":18,"error":null}]},"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"At least one dependency is unhealthy.","content":{"application/json":{"example":{"status":"degraded","service":"knownat-api","environment":"production","release":"2026.08.28-1","git_sha":"23f6bc9","generated_at":"2026-08-28T10:00:00.000Z","dependencies":[{"name":"database","healthy":false,"latency_ms":5001,"error":"Dependency timed out."}]},"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}}}}},"/health/data":{"get":{"tags":["System"],"summary":"Ingestion pipeline health","description":"Flat view of every collector heartbeat, including source, receive and write lag per feed. Intended for the KnownAt watchdog and operational dashboards rather than for client applications, which should use `/v1/status`. Requires the `account:read` scope.","responses":{"200":{"description":"Current state of every ingestion feed.","content":{"application/json":{"example":{"status":"operational","generated_at":"2026-08-28T10:00:00.000Z","feeds":[{"feed":"polymarket.trades","dataset":"polymarket","stream":"trades","status":"operational","source_lag_ms":420,"receive_lag_ms":380,"write_lag_ms":410,"last_source_timestamp":"2026-08-28T09:59:59.580Z","last_received_at":"2026-08-28T09:59:59.620Z","last_written_at":"2026-08-28T09:59:59.590Z","events_per_second":128.5}]},"schema":{"$ref":"#/components/schemas/DataHealthResponse"}}}},"401":{"description":"The API key is missing, malformed, expired, or revoked.","content":{"application/json":{"example":{"error":{"code":"INVALID_API_KEY","message":"The API key is missing, malformed, expired, or revoked.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the scope this endpoint requires.","content":{"application/json":{"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"The API key is valid but lacks the scope this endpoint requires.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"A dependency required to serve this request is unavailable.","content":{"application/json":{"example":{"error":{"code":"SERVICE_UNAVAILABLE","message":"A dependency required to serve this request is unavailable.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/status":{"get":{"tags":["System"],"summary":"Data freshness and feed status","description":"Current status and lag of every live KnownAt feed, grouped by dataset and stream. Public and unauthenticated so it can be polled by a client before it decides to trust live data, or wired into a customer-side monitor. `status` at the top level is the worst status across all feeds. Poll at most once every 10 seconds.","security":[],"responses":{"200":{"description":"Status of every feed.","content":{"application/json":{"example":{"status":"delayed","generated_at":"2026-08-28T10:00:00.000Z","datasets":{"polymarket":{"trades":{"status":"operational","source_lag_ms":420,"receive_lag_ms":380,"write_lag_ms":410,"last_source_timestamp":"2026-08-28T09:59:59.580Z","last_received_at":"2026-08-28T09:59:59.620Z","last_written_at":"2026-08-28T09:59:59.590Z","events_per_second":128.5},"orderbook":{"status":"delayed","source_lag_ms":18420,"receive_lag_ms":18380,"write_lag_ms":18410,"last_source_timestamp":"2026-08-28T09:59:41.580Z","last_received_at":"2026-08-28T09:59:41.620Z","last_written_at":"2026-08-28T09:59:41.590Z","events_per_second":12.1}}}},"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"A dependency required to serve this request is unavailable.","content":{"application/json":{"example":{"error":{"code":"SERVICE_UNAVAILABLE","message":"A dependency required to serve this request is unavailable.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/account/key":{"get":{"tags":["Account"],"summary":"Verify an API key","description":"Returns the identity, scopes and plan associated with the presented API key. Use it as a connectivity and credentials check when wiring up a client: a 200 means the key is valid, unexpired and unrevoked, and the `scopes` array tells you exactly what it may call. The key itself is never echoed back.","responses":{"200":{"description":"The key is valid.","content":{"application/json":{"example":{"authenticated":true,"key":{"id":"6f1c8f2e-5f0a-4a1b-9d3e-6b2c1a7f4d55","name":"backtest-runner","environment":"live","scopes":["account:read","datasets:read","polymarket:read"],"plan":"pro","expires_at":null}},"schema":{"$ref":"#/components/schemas/KeyVerification"}}}},"401":{"description":"The API key is missing, malformed, expired, or revoked.","content":{"application/json":{"example":{"error":{"code":"INVALID_API_KEY","message":"The API key is missing, malformed, expired, or revoked.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the scope this endpoint requires.","content":{"application/json":{"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"The API key is valid but lacks the scope this endpoint requires.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/account/usage":{"get":{"tags":["Account"],"summary":"Current period usage","description":"Requests and bandwidth consumed by the account in the current calendar month (UTC), against the limits of its plan. Counters are derived from KnownAt’s own per-request accounting, not from edge rate-limiter state, and are the same numbers billing uses. They may lag live traffic by up to a minute.","responses":{"200":{"description":"Usage for the current period.","content":{"application/json":{"example":{"plan":"pro","period":{"start":"2026-08-01T00:00:00.000Z","end":"2026-09-01T00:00:00.000Z"},"requests":{"used":182341,"limit":1000000},"bandwidth_gb":{"used":14.8,"limit":100},"rate_limited_requests":0},"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"401":{"description":"The API key is missing, malformed, expired, or revoked.","content":{"application/json":{"example":{"error":{"code":"INVALID_API_KEY","message":"The API key is missing, malformed, expired, or revoked.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the scope this endpoint requires.","content":{"application/json":{"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"The API key is valid but lacks the scope this endpoint requires.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"A dependency required to serve this request is unavailable.","content":{"application/json":{"example":{"error":{"code":"SERVICE_UNAVAILABLE","message":"A dependency required to serve this request is unavailable.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/datasets/polymarket.market_snapshots/latest":{"get":{"tags":["Datasets"],"summary":"Latest Polymarket market snapshots","description":"Returns the newest stored price snapshot for each selected Polymarket outcome token, ordered by observation time descending. This small endpoint is intended for live dashboards and v0 integration checks; historical range scans will use a separate cursor-based endpoint.\n\n**Data source.** Polymarket CLOB simplified markets, collected by the KnownAt ingestion service. `observed_at` marks the snapshot cycle, `available_at` records when the source response reached the collector, and `ingested_at` records persistence in ClickHouse.\n\n**Query budget.** Results come from a compact latest-state table rather than the full history and are capped at 100 rows, protecting the shared ClickHouse instance from dashboard refreshes.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Maximum number of current token snapshots to return. Between 1 and 100.","example":20},"required":false,"description":"Maximum number of current token snapshots to return. Between 1 and 100.","name":"limit","in":"query"}],"responses":{"200":{"description":"Newest stored Polymarket token snapshots, or an empty page before the first successful ingestion.","content":{"application/json":{"example":{"data":[{"observed_at":"2026-08-31T12:00:00.000Z","available_at":"2026-08-31T12:00:00.042Z","ingested_at":"2026-08-31T12:00:00.083Z","market_id":"0x4f9f9d9c6d87a56ec2d8b65f9303e366","token_id":"2174265494803246004871024487728592001","outcome":"Yes","price":0.63}],"meta":{"records":1,"next_cursor":null,"has_more":false,"generated_at":"2026-08-31T12:00:01.000Z"}},"schema":{"$ref":"#/components/schemas/LatestPolymarketMarketSnapshots"}}}},"400":{"description":"One or more request parameters failed validation.","content":{"application/json":{"example":{"error":{"code":"INVALID_PARAMETER","message":"One or more request parameters failed validation.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, expired, or revoked.","content":{"application/json":{"example":{"error":{"code":"INVALID_API_KEY","message":"The API key is missing, malformed, expired, or revoked.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the scope this endpoint requires.","content":{"application/json":{"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"The API key is valid but lacks the scope this endpoint requires.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"A dependency required to serve this request is unavailable.","content":{"application/json":{"example":{"error":{"code":"SERVICE_UNAVAILABLE","message":"A dependency required to serve this request is unavailable.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/datasets":{"get":{"tags":["Datasets"],"summary":"List datasets","description":"Every dataset published in the KnownAt catalog, with its provenance, update cadence, historical coverage window and available access formats.\n\nUse this endpoint to discover what is queryable and over what period, before hitting a dataset’s data endpoints. `is_point_in_time` tells you whether a dataset records both source and ingestion time and is therefore safe to backtest against without lookahead bias.\n\n**Data source.** The KnownAt catalog, updated whenever a dataset is published or its coverage window advances. Coverage timestamps reflect the state at the moment of the response; use `/v1/status` for live feed lag.\n\n**Ordering.** Datasets are returned in ascending `slug` order. The slug is unique, so the ordering is total and deterministic: two calls with the same filters return rows in the same sequence.\n\n**Pagination.** Cursor-based. Pass `meta.next_cursor` as `cursor` to fetch the next page; iterate until `meta.has_more` is false. Because paging resumes strictly after the last slug returned rather than at a numeric offset, a full scan neither skips nor duplicates a record while datasets are being published concurrently. Cursors are opaque, expire after 24 hours, and are bound to the filters they were issued with — change `category` and you must restart the scan.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Maximum number of datasets to return. Between 1 and 1000.","example":100},"required":false,"description":"Maximum number of datasets to return. Between 1 and 1000.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048,"description":"Pass `meta.next_cursor` from the previous page. Cursors are bound to the filters they were issued with; changing `category` requires restarting the scan."},"required":false,"description":"Pass `meta.next_cursor` from the previous page. Cursors are bound to the filters they were issued with; changing `category` requires restarting the scan.","name":"cursor","in":"query"},{"schema":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]+$","description":"Restrict results to a single catalog category.","example":"prediction-markets"},"required":false,"description":"Restrict results to a single catalog category.","name":"category","in":"query"}],"responses":{"200":{"description":"A page of datasets in ascending slug order.","content":{"application/json":{"example":{"data":[{"slug":"polymarket-trades","title":"Polymarket trades","description":"Every executed trade on Polymarket prediction markets, timestamped at the source and at KnownAt ingestion.","category":"prediction-markets","source":{"name":"Polymarket","url":"https://polymarket.com","license":"Public market data"},"update_frequency":"realtime","access_formats":["json","parquet"],"coverage":{"earliest_available_at":"2024-01-01T00:00:00.000Z","latest_available_at":"2026-08-28T09:59:12.418Z"},"row_count":184920331,"is_point_in_time":true,"updated_at":"2026-08-28T10:00:00.000Z"}],"meta":{"records":1,"next_cursor":null,"has_more":false,"generated_at":"2026-08-28T10:00:00.000Z"}},"schema":{"$ref":"#/components/schemas/DatasetList"}}}},"400":{"description":"One or more request parameters failed validation. The pagination cursor is malformed, expired, or was issued for different filters.","content":{"application/json":{"example":{"error":{"code":"INVALID_CURSOR","message":"The pagination cursor is malformed, expired, or was issued for different filters.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, expired, or revoked.","content":{"application/json":{"example":{"error":{"code":"INVALID_API_KEY","message":"The API key is missing, malformed, expired, or revoked.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the scope this endpoint requires.","content":{"application/json":{"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"The API key is valid but lacks the scope this endpoint requires.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"A dependency required to serve this request is unavailable.","content":{"application/json":{"example":{"error":{"code":"SERVICE_UNAVAILABLE","message":"A dependency required to serve this request is unavailable.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/datasets/{slug}":{"get":{"tags":["Datasets"],"summary":"Get a dataset","description":"Full catalog entry for one dataset, including its column schema in the order the data endpoints return them.\n\nEach column carries a `semantic_role` identifying the point-in-time timestamps: `source_timestamp` is the event time reported by the source, `received_at` is when KnownAt received it, and `ingested_at` is when it was persisted. Where the source guarantees it, `source_timestamp <= received_at <= ingested_at` holds for every record.\n\n**Data source.** The KnownAt catalog. Unpublished datasets are indistinguishable from non-existent ones and return `DATASET_NOT_FOUND`.","parameters":[{"schema":{"type":"string","maxLength":128,"pattern":"^[a-z0-9]+([._-][a-z0-9]+)*$","description":"Stable dataset identifier. Slugs never change once published.","example":"polymarket-trades"},"required":true,"description":"Stable dataset identifier. Slugs never change once published.","name":"slug","in":"path"}],"responses":{"200":{"description":"The dataset and its column schema.","content":{"application/json":{"example":{"data":{"slug":"polymarket-trades","title":"Polymarket trades","description":"Every executed trade on Polymarket prediction markets, timestamped at the source and at KnownAt ingestion.","category":"prediction-markets","source":{"name":"Polymarket","url":"https://polymarket.com","license":"Public market data"},"update_frequency":"realtime","access_formats":["json","parquet"],"coverage":{"earliest_available_at":"2024-01-01T00:00:00.000Z","latest_available_at":"2026-08-28T09:59:12.418Z"},"row_count":184920331,"is_point_in_time":true,"updated_at":"2026-08-28T10:00:00.000Z","columns":[{"name":"source_timestamp","data_type":"timestamptz","description":"Event time reported by Polymarket.","nullable":false,"semantic_role":"source_timestamp"},{"name":"received_at","data_type":"timestamptz","description":"Moment the KnownAt collector received the event.","nullable":false,"semantic_role":"received_at"},{"name":"price","data_type":"numeric","description":"Executed price, expressed as an implied probability between 0 and 1.","nullable":false,"semantic_role":null}]}},"schema":{"$ref":"#/components/schemas/DatasetDetailResponse"}}}},"400":{"description":"One or more request parameters failed validation.","content":{"application/json":{"example":{"error":{"code":"INVALID_PARAMETER","message":"One or more request parameters failed validation.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, expired, or revoked.","content":{"application/json":{"example":{"error":{"code":"INVALID_API_KEY","message":"The API key is missing, malformed, expired, or revoked.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is valid but lacks the scope this endpoint requires.","content":{"application/json":{"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"The API key is valid but lacks the scope this endpoint requires.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such dataset is available to this API key.","content":{"application/json":{"example":{"error":{"code":"DATASET_NOT_FOUND","message":"No such dataset is available to this API key.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The plan rate limit for this API key has been exceeded.","content":{"application/json":{"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"The plan rate limit for this API key has been exceeded.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred. The request ID identifies it in our logs.","content":{"application/json":{"example":{"error":{"code":"INTERNAL_ERROR","message":"An unexpected error occurred. The request ID identifies it in our logs.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"A dependency required to serve this request is unavailable.","content":{"application/json":{"example":{"error":{"code":"SERVICE_UNAVAILABLE","message":"A dependency required to serve this request is unavailable.","request_id":"req_01J8ZC4V6QK7M3B0YHP2R9TAXD"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}