Archive download link
Asks for a temporary download link to one Hyperliquid archive file — a fills or positions day, or the 5-minute latest positions file. The link needs no key, names exactly one file and works for 300 seconds.
GET https://data.vike.io/v1/hyperliquid/archive/url?dataset={dataset}&date={date}Asks for a temporary link to one Hyperliquid archive file. No daily or latest file has a permanent URL and
their folder cannot be listed, key or no key, so this is the only way to get one. Ask which days exist at
/archive/datasets; ask here for the one you want. The free samples
are the one part of the archive with a plain address, the samples_base of that index
(Free samples).
The answer carries the link, when it stops being accepted, and the size of the file it names. dataset is fills or
positions; date is a published UTC day, or latest for the 5-minute positions file.
# a link to one day of fills: the url is good for 300 seconds and needs no key
curl -s "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-19" \
-H "X-API-KEY: $VIKE_API_KEY"
# one day of 5-minute position snapshots: 1.6 GB, so read bytes before you download
curl -s "https://data.vike.io/v1/hyperliquid/archive/url?dataset=positions&date=2026-10-19" \
-H "X-API-KEY: $VIKE_API_KEY"
# the current open positions of every asset, a small file replaced every 5 minutes
curl -s "https://data.vike.io/v1/hyperliquid/archive/url?dataset=positions&date=latest" \
-H "X-API-KEY: $VIKE_API_KEY"
# ask and download in one step: redirect=1 answers 302 with the link in Location, and -L follows it
curl -s -L "https://data.vike.io/v1/hyperliquid/archive/url?dataset=positions&date=latest&redirect=1" \
-H "X-API-KEY: $VIKE_API_KEY" \
-o positions-latest.parquet
# keep only the link, to hand to a downloader
curl -s "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-19" \
-H "X-API-KEY: $VIKE_API_KEY" \
| jq -r '.url'datasetqueryrequiredfills or positions. Anything else returns 400 naming both.datequeryrequiredYYYY-MM-DD of a published UTC day, or latest (positions only: the file of the current open positions, replaced every 5 minutes). A day that is not published returns 400 naming the range that is.redirectqueryoptional1 or true answers 302 with the link in Location; the JSON body is still sent, so a client that does not follow redirects keeps the answer.These are the three links, captured from the running service. In each url the token between /dl/ and the next
/ was replaced with <exp>.<kid>.<sig>, because a real signed link is a credential for five minutes; every
other value is as returned.
{
"url": "https://data.vike.io/dl/<exp>.<kid>.<sig>/venue=hyperliquid/date=2026-10-19/fills.parquet",
"expires_at": "2026-10-21T10:24:43Z",
"expires_in": 300,
"dataset": "fills",
"date": "2026-10-19",
"bytes": 358509915,
"rows": 12022655
}{
"url": "https://data.vike.io/dl/<exp>.<kid>.<sig>/venue=hyperliquid/date=2026-10-19/positions.parquet",
"expires_at": "2026-10-21T10:24:43Z",
"expires_in": 300,
"dataset": "positions",
"date": "2026-10-19",
"bytes": 1639446104,
"rows": 102738790
}{
"url": "https://data.vike.io/dl/<exp>.<kid>.<sig>/venue=hyperliquid/latest/positions.parquet",
"expires_at": "2026-10-21T10:24:43Z",
"expires_in": 300,
"dataset": "positions",
"date": "latest",
"bytes": 29578173,
"rows": 427884
}bytes and rows are the file's size and row count, so you can budget the download first. For latest they are the
values of the version that existed when you asked; the file is replaced about every 5 minutes, so the bytes you
receive can differ.
The link
The url is an ordinary HTTPS address:
| Part | Meaning |
|---|---|
https://data.vike.io/dl/ | The prefix of every download link. Nothing under /archive/venue=hyperliquid/ is reachable. |
<exp>.<kid>.<sig> | One opaque token: the expiry, the key that asked, and a signature over them and the file path. Do not parse or build it. |
venue=hyperliquid/date=2026-10-19/fills.parquet | The file, with its real name, so a reader such as DuckDB or pyarrow sees fills.parquet. latest is venue=hyperliquid/latest/positions.parquet. |
- It needs no key. The link is the credential. Anyone holding it can download that one file until it expires, so keep it out of logs and shared tickets. Downloads are recorded against the key that asked for the link.
- It names exactly one file. The signature covers the path: changing the date or the token returns
403, and a path that matches no archive file returns404. - It is accepted for 300 seconds (
expires_in) from the start of a request. A download that is running when the clock passesexpires_atis not cut. A reader that opens new requests, such as DuckDB or pyarrow reading over HTTP, needs a link that is still valid for each one, so download the whole file, or ask again per file. - A file is served whole or in ranges. Responses carry
Accept-Ranges: bytes,Content-LengthandCache-Control: private, no-store, socurl -C -can resume an interrupted download (with a fresh link).
What it costs
The call is a normal /v1 request: 1 credit, one request of the hourly budget, and
counted by the per-minute /v1 cap. The download itself is recorded as an archive_download and spends neither the
hourly budget nor the per-minute cap; its cost is bandwidth, capped per connection like the rest of the archive.
There is an allowance of 20 GB of links per user per rolling 24 hours, all of a user's keys together. What is
counted is the size (bytes) of each link issued, not the bytes you read, so a link you never use still counts. Past it
the call answers 429 with {"detail": "..."} saying how much was issued. Unlike the rate-limit 429s it carries no
Retry-After: the window rolls over 24 hours, so a retry minutes later is refused again. Ask again after earlier links
have aged out of the window, or write to us if you need more.
Errors on the ask, and the 403 on the link
Errors on this call are the usual /v1 ones. A bad dataset or date, or a day with no file, is a 400
whose body names what exists. These were captured from the running service:
dataset=fills&date=2026-04-30 returns 400 {"detail":"no fills file for 2026-04-30; published: 2026-05-01 to 2026-10-20 (173 days)"}.
The range is the published one, and the day count (a count below the span would mean a gap inside it) is as of the call.
dataset=positions&date=2026-05-07 returns 400 {"detail":"no positions file for 2026-05-07; published: 2026-05-08 to 2026-10-19 (165 days)"}.
dataset=fills&date=latest returns 400 {"detail":"date=latest exists for positions only (the current open positions, refreshed every 5 minutes)"}.
dataset=trades&date=2026-10-19 returns 400 {"detail":"dataset must be one of: fills, positions"}.
A missing or invalid key is a 401 from the gate in front of the API, with the UNAUTHORIZED JSON body (see
Errors).
Errors on the link come from the download host, not from this route. A link that is expired or altered
returns 403 {"error":"download link expired or invalid","hint":"request a new one: GET /v1/hyperliquid/archive/url?dataset=fills&date=YYYY-MM-DD"}.
Ask again and use the new link. A direct /archive/venue=hyperliquid/... path returns 404 whether or not you send a key.
Related
/archive/datasets— which days exist, their rows and bytes, and the columns.- Download the Hyperliquid file archive — download a file with
curlor Python and read it. - Rate limits — what a link request and a download each spend.