/archive/{partition path}
One path prefix covering the whole archive — two Hive partitionings of the same data behind one path, not two endpoints.
GET https://data.vike.io/archive/venue=polymarket/date={YYYY-MM-DD}/{stream}.parquet
GET https://data.vike.io/archive/venue=polymarket/asset={asset}/tenor={tenor}/date={YYYY-MM-DD}/{stream}.parquetOne path prefix covering the whole archive. The two path shapes above are two Hive partitionings of the same data behind one path, not two endpoints — full detail of both, and which dates each covers, is on Bulk archive.
There is no JSON response to show you. The body is a binary Apache Parquet file — the one that command downloads is 13,459,739 bytes. So the example below asks for the first 2 KB of the next day's partition instead of the whole of it, which is enough to prove the route, the gate and the file type without moving the file:
curl -H "X-API-Key: $VIKE_API_KEY" \
-r 0-2047 -D - -o /dev/null \
"https://data.vike.io/archive/venue=polymarket/date=2026-09-02/trades.parquet"Response headers, verbatim, 2026-09-03:
HTTP/1.1 206 Partial Content
Content-Type: application/octet-stream
Content-Length: 2048
Content-Range: bytes 0-2047/12314277
Last-Modified: Thu, 03 Sep 2026 00:32:06 GMT
ETag: "6a98c006-bbe6a5"
Cache-Control: private, no-store
Server: cloudflare
cf-cache-status: DYNAMICThe first four bytes of that body are 50 41 52 31 — the ASCII PAR1 every Parquet file opens
and closes with. The rest is zstd-compressed column data and is not readable as text.
Three of those headers are worth reading as confirmations rather than trivia. 206 with a
Content-Range is the Range row of the table below, working — the server served 2,048 bytes
of a file it told you is 12,314,277. That total is also the cross-check on
manifest.json: its dates entry for 2026-09-02
reports the trades stream at 1,006,555 rows and 12,314,277 bytes — the same total — so a size
read from the manifest is the size you will actually be billed bandwidth for. And cf-cache-status: DYNAMIC beside
Cache-Control: private, no-store is the third bullet below holding: Cloudflare saw the
response and declined to cache it.
Drop the credential and the same URL never reaches the file — the request is refused before the file is opened. The status is 401 Authorization Required and the body is a plain HTML error page from the edge, not a JSON envelope:
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
</body>
</html>⚠ That 401 body is HTML, not the JSON error envelope the /v1 endpoints return. A client
that assumes every failure parses as JSON breaks here — see Errors. It is also
indistinguishable from the 401 a path that does not exist returns: probed keylessly on
2026-09-03, the real partition above and an invented
date=1999-01-01/nosuchstream.parquet both answered 401 with byte-identical bodies. Without
a credential you cannot tell a typo from a refusal, because the gate runs before the lookup.
There are no query parameters. What you can vary is the path and a small set of headers:
curl -H "X-API-Key: $VIKE_API_KEY" \
-o polymarket-trades-2026-09-01.parquet \
"https://data.vike.io/archive/venue=polymarket/date=2026-09-01/trades.parquet"X-API-KeyheaderrequiredX-API-KEY and the manifest X-API-Key — same header, same key.Authorization: Bearer vk_oat_…headerrequiredX-API-Key header. Both reach the same account — see Authentication.RangeheaderoptionalAccept-Ranges: bytes, and the manifest advertises range_requests: true. It is there so an interrupted download can resume, not so a query engine can page a remote file.venuepathrequiredpolymarket. The only venue in the archive today.datepathrequiredYYYY-MM-DD. Enumerate dates[] in the manifest; do not probe for dates.| asset | path | family layout only | btc, eth, sol, xrp, doge, bnb, hype, other — read from today's manifest, which is the authority rather than this row. |
| tenor | path | family layout only | 5m, 15m, 4h, other, same caveat. |
| {stream} | path | yes | book_events, trades or l1_quotes. Schemas differ per stream — Bulk archive. |
¹ One of the two credentials, not both.
A missing file is a legitimate answer in the family layout. A family with zero rows in a
stream on a given day has no file for that stream, and the family layout does not cover every
date the date= layout does. Enumerate families[] rather than assuming.
Three properties of this location worth knowing before you point a tool at it:
- Responses carry
Cache-Control: private, no-store, on every response. An authenticated file must never be cached at the edge — a cached copy would bypass both the gate and the usage record — so do not expect a CDN to serve a repeat download for you. - A directory URL under
/archive/returns a listing rather than a 403, once you present a credential. The listing is HTML. - Throughput is capped at 50 MB/s per connection. It is a bandwidth bound, not a request bound; parallel whole-file downloads are the supported way to go faster, and cost one recorded download each.
⚠ This path never returns a rate-limit 429: archive downloads do not draw on the hourly budget at all. A refusal here is a credential problem, not a budget one — see Rate limits and Errors.
/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.
Schema and spec
The live OpenAPI document, Swagger UI and ReDoc — where they live, what the spec actually declares, and the three gaps that decide whether you can generate a working client from it.