/archive/manifest.json
The index of everything in the archive, regenerated daily — coverage, both partitioning patterns, the inline column schemas, the auth scheme, the licence, and one entry per partition. Needs no key.
GET https://data.vike.io/archive/manifest.jsonThe index of everything in the archive, regenerated daily: coverage, both partitioning patterns, the inline column schemas, the auth scheme, the licence, and one entry per partition carrying byte size and row count. It needs no key. Fetch it first and enumerate it — it is what is true today, where any figure written into a doc page is a snapshot.
# download the index: it needs no key, so there is no -H and nothing is recorded
curl "https://data.vike.io/archive/manifest.json" -o manifest.json
# the newest day on offer; dates[] is newest first
jq -r '.dates[0].date' manifest.json
# that day's three streams with their rows and bytes, to budget a download before making it
jq '.dates[0].streams' manifest.json
# the newest btc 5-minute family file: max_by(.date) rather than [0], so it holds whatever order families[] arrives in
jq '[.families[] | select(.asset=="btc" and .tenor=="5m")] | max_by(.date)' manifest.json
# the days whose trades row count is null (the oldest partitions): code that does arithmetic on rows has to check for them, bytes is always there
jq '[.dates[] | select(.streams.trades.rows == null) | .date]' manifest.json
# what every day of book_events would cost to download, in bytes: the full-history figure to weigh before pulling it
jq '[.dates[].streams.book_events.bytes] | add' manifest.json
# the same index filtered server side instead: an ordinary API call, which spends a unit of the hourly budget but spares you parsing 250 KB
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/polymarket/archive/datasets?stream=trades&from=2026-09-01&limit=10"The missing -H is deliberate, not an omission: this is one of the two keyless paths, so the
request validates nothing and records nothing. The live response, fetched
2026-09-03, carries three elisions, marked inline and counted under the fence.
{
"venue": "polymarket",
"generated_at": "2026-09-03T00:37:42Z",
"license": {
"name": "CC BY 4.0",
"url": "https://creativecommons.org/licenses/by/4.0/",
"attribution": "Polymarket L2 archive (c) Vike (vike.io/data), CC BY 4.0",
"note": "Applies to the DATA files this manifest indexes. It grants no rights to any Vike source code."
},
"partitioning": "venue=polymarket/date=YYYY-MM-DD/{book_events,trades,l1_quotes}.parquet",
"note": "Full L2 (book_events) + taker tape (trades) + derived top-of-book (l1_quotes) for the whole Polymarket universe (crypto up/down + sports + politics markets), one UTC day per partition.",
"schema": {
"book_events": [ /* 16 columns, elided */ ],
"trades": [
{ "name": "token_id", "type": "String" },
{ "name": "condition_id", "type": "String" },
{ "name": "ts", "type": "Int64" },
{ "name": "local_ts", "type": "Int64" },
{ "name": "seq", "type": "UInt64" },
{ "name": "price", "type": "Float64" },
{ "name": "size", "type": "Float64" },
{ "name": "side", "type": "String" }
],
"l1_quotes": [ /* 8 columns, elided */ ]
},
"auth": {
"scheme": "header",
"header": "X-API-Key",
"how_to_get_a_key": "Request access via vike.io — the same account/API-key system that gates data.vike.io/v1 and data.vike.io/mcp."
},
"range_requests": true,
"free_sample": {
"path": "/archive/samples/",
"readme": "/archive/samples/README.txt",
"note": "One full crypto up/down 5-minute market (both outcome tokens, open through resolution), regenerated daily — no key required."
},
"dates": [
{ "date": "2026-09-02", "streams": {
"book_events": { "rows": 306994531, "bytes": 4799571940 },
"trades": { "rows": 1006555, "bytes": 12314277 },
"l1_quotes": { "rows": 36596619, "bytes": 373583589 } } },
{ "date": "2026-09-01", "streams": {
"book_events": { "rows": 307245726, "bytes": 4826341757 },
"trades": { "rows": 1100045, "bytes": 13459739 },
"l1_quotes": { "rows": 32065417, "bytes": 335196889 } } }
/* 38 more dates, newest first, ending 2026-07-25 */
],
"family_partitioning": "venue=polymarket/asset=<asset>/tenor=<tenor>/date=YYYY-MM-DD/{book_events,trades,l1_quotes}.parquet",
"family_partitioning_note": "ADDITIVE alternative layout (poly_export_family.sh) grouping the crypto up/down families (asset x tenor, e.g. asset=btc/tenor=5m) into their own small files so a single-family customer does not download the whole token-sorted date= file. asset=other/tenor=other is the catch-all for every market that is not a recognized up/down family (sports, politics, one-off events) — never silently dropped. Same schema as the date= layout (see `schema` above); not every (asset,tenor,date) is guaranteed present for every stream (a family with zero rows in a stream that day has no file for it).",
"families": [
{ "asset": "xrp", "tenor": "5m", "date": "2026-09-02", "streams": {
"book_events": { "rows": 8531385, "bytes": 104536361 },
"trades": { "rows": 33332, "bytes": 555993 },
"l1_quotes": { "rows": 1699187, "bytes": 11729583 } } },
{ "asset": "xrp", "tenor": "5m", "date": "2026-09-01", "streams": {
"book_events": { "rows": 7852908, "bytes": 99223946 },
"trades": { "rows": 33015, "bytes": 544739 },
"l1_quotes": { "rows": 986897, "bytes": 7096420 } } }
/* 658 more families */
]
}What was elided, exactly. The response is 262,424 bytes. Every scalar and every object
above is verbatim; three arrays are cut, and nothing else is. schema.book_events (16 columns)
and schema.l1_quotes (8) are dropped — schema.trades is shown whole as the shape exemplar,
and the full column lists are on Bulk archive. dates carries
40 entries and families 660; two of each are shown, in the order the response returns
them, which is newest first.
The two type vocabularies are ClickHouse's, not Parquet's
The type strings in schema are ClickHouse's — visible above as Int64 and Float64 on
trades, and as Decimal(9, 4), LowCardinality(String) and Enum8('book' = 1, …) on the two
elided streams. They describe the table the file was exported from. What a Parquet reader hands
back is the physical type, and the gap between the two is the decoding trap that
Bulk archive works through.
The tail of dates[] is a different shape from its head, which is why the head alone would
mislead — the oldest partition in the same response:
{ "date": "2026-07-25", "streams": {
"book_events": { "rows": null, "bytes": 5235801848 },
"trades": { "rows": null, "bytes": 12139041 },
"l1_quotes": { "rows": null, "bytes": 357730559 } } }Parameters: none. No query string is read, and no header changes the response. The path is
matched exactly, so manifest.json is the only keyless name under /archive/: any other name
in that directory is gated like the rest of the full archive, and answers 401 without a
credential.
Top-level keys, read from the live response fetched 2026-09-03:
| Key | What it holds |
|---|---|
generated_at | UTC timestamp of this regeneration. |
venue | polymarket. |
note | One sentence on what the three streams are. |
partitioning | The date= pattern string. |
family_partitioning, family_partitioning_note | The additive asset=/tenor= pattern and its caveats. |
dates | One row per UTC day, each with a streams object keyed by stream name. |
families | One row per (asset, tenor, date), same streams shape. |
schema | Column types per stream — book_events, trades, l1_quotes. |
auth | scheme, header (X-API-Key) and how to get a key. |
free_sample | Paths to /archive/samples/ and its README.txt. |
license | CC BY 4.0 with its attribution string, covering the data files only. |
range_requests | true. |
A dates[] row, verbatim from that response:
{"date":"2026-09-02","streams":{
"book_events":{"rows":306994531,"bytes":4799571940},
"trades":{"rows":1006555,"bytes":12314277},
"l1_quotes":{"rows":36596619,"bytes":373583589}}}rows is optional, bytes is not
The three oldest partitions carry a byte size and a null row count — confirmed in today's
manifest for 2026-07-25, 2026-07-26 and 2026-07-27. Code that does arithmetic on rows without a
null check breaks on the earliest dates and nowhere else, which is the hardest kind of bug to find.
Discovering partitions programmatically. The manifest is not the only index. Two JSON
endpoints answer the same question over HTTP, with filters and paging —
/v1/polymarket/archive/datasets enumerates
partitions across both layouts, each row carrying the absolute download URL beside that file's byte
and row counts, and /v1/polymarket/archive/url
resolves one already-known partition to the same information. They
are routed under the polymarket namespace rather than under /archive/, because the archive
carries only Polymarket data. There is no /v1/archive/... alias — that spelling is routed
nowhere and answers 404.
Those two discovery endpoints are ordinary API calls
They need a credential and they do spend the hourly budget that an archive download does not — see Rate limits. This manifest remains the keyless way to get the whole index in one request; the discovery endpoints are what you want when you would rather filter server-side than parse 250 KB of JSON.
Polymarket archive
Bulk Parquet for the recorded Polymarket CLOB — three paths on data.vike.io, two free and one key-gated, serving files directly with no JSON envelope in front of them.
/archive/samples/
A real slice of the full archive — one complete crypto up/down 5-minute market, both outcome tokens, open through resolution, all three streams — regenerated daily and served free.