Freshness and completeness
How current each Data API answer is, product by product, and how an answer marks what it leaves out: live balances and daily windows on-chain, the position-match gate and daily files on Hyperliquid, the provisional row and freshness block on HL Cohorts, snapshot age, the hourly leaderboard and the archive manifest on Polymarket.
Data reaches the API a little behind the clock, and some answers carry an old value in exactly the shape of a current one. Each section here is the field or rule that tells the two apart, product by product, and the last says how an answer marks what it does not hold. The WebSocket's own latency is on /v1/stream.
On-chain: three clocks
- Balance amounts are live.
/wallets/{address}/balancesreads each amount from the chain at request time. Which tokens it checks comes from our own copy of the wallet's transfers, so a token first received after the last sync is not listed yet. - Transfers trail the chain by minutes. The routes that list or rank transfers read our own copy of each chain,
which a sync extends every few minutes, so the newest blocks may not be in it yet. A transfer's USD value arrives
only when pricing runs, so a route filtering on
min_usdabove 0 can skip the newest, still unpriced hours. - Leaderboard windows are rebuilt once a day. The
24h,7d,30dand90dfigures of/wallets/discovercan be up to about a day old.
On base and hyperevm, a stale window is a 400, not an old answer
/wallets/discover serves a base or hyperevm window other than all only while every part of that chain's
window data was rebuilt within the last 2 days. Past that, the request is a 400 saying only window=all is
available, rather than a days-old leaderboard in the shape of a current one. all always answers, and it is the
default on those two chains.
Hyperliquid
Position matching: a 15-minute gate
A 15-minute freshness gate is why /positions/match returns fewer rows than the position history holds
Only positions seen within 15 minutes of the newest snapshot batch are matched. The latest-state view keeps a wallet's last-known row forever — 89.8% of it measured more than a day stale, the oldest ghost 2026-04-02 — so without the gate this matched months-closed positions as open. The gate is anchored on the newest snapshot batch rather than on the wall clock, so ingestion lag cannot empty the result.
The daily files and latest
A day of fills or positions appears in /archive/datasets once
the day is complete: yesterday's files are published in the early UTC morning. The exporter does not rewrite a
published day on its own; a repair that does is recorded in the changelog.
The latest positions file is replaced about every 5 minutes; latest.positions in the same index carries its
snapshot_ts (the newest cycle in the file) and generated_at (when the file was written), so read its age there
rather than assume it.
HL Cohorts
The hourly series: the provisional row
Every row carries provisional, and it is true on at most one of them
The newest row covers the hour still in progress. The hourly rollup lands 60–120 minutes late,
so without that row a "current positioning" read would be silently that stale. Its ts is a
snapshot instant rather than an hour boundary and it changes on every poll: drop it when
persisting a series. It is present only on the first page of a window reaching the present.
Cohort-metrics: the freshness block
Read the age off freshness.behind_hours, never off a number in prose
On any window that reaches the present the envelope carries
{newest_ts, behind_hours, settled_lag_ceiling_hours, stale}. stale is the pre-computed verdict,
so a consumer does not have to re-derive the rollup's cadence.
It exists because prose was not enough. grading=realized-pit reads a frozen research
artefact: nothing has written to it since 2026-08-16 19:00 UTC. Ask it for an explicit recent
window and it honestly answers with zero rows — but ask it the way a poller does
(?grading=realized-pit&hours=1, no start) and it returns its own newest bucket, identical in
shape to a current one, and days old. That gap is not a constant: it grows by 24 hours a day.
For live trading use grading=realized with labelBasis=point_in_time — honest labels, and one
hour behind the clock rather than days.
A window ending in the past gets no freshness block at all: "the newest bar is four months
old" answers a question a historical query did not ask, and would make every backtest fetch look
broken.
Polymarket
A snapshot is as old as as_of_ts
On /orderbook, as_of_ts is the snapshot's own timestamp, not the ts you asked for — read it, because the
nearest snapshot may be considerably older than your request.
The recorded book starts on 2026-07-25
/ohlcv, /events and /orderbook read the order book we record, which starts on 2026-07-25 and is kept from then
on. A window that ends before that date answers empty, with an X-Vike-Note header saying why
(Errors).
The leaderboard is rebuilt hourly
/leaderboard reads a board rebuilt every hour, not the live tape. Its
24h, 7d and 30d windows can be revised by a later rebuild, because a market's resolution time can be corrected
after the fact; all is not affected. A page fetched with offset after a rebuild can repeat or skip a wallet, so
fetch the pages of one walk close together.
The archive: the manifest is what is true today
Read generated_at in /archive/manifest.json before trusting a coverage figure. Anything written down elsewhere is a snapshot; the manifest is what is true today.
Completeness: what an answer can leave out
An empty or short answer is not always "nothing happened". These are the places an answer marks what it does not hold, rather than hiding it:
- On-chain routes return one page, capped. None of them pages, and a route's applied cap can be lower than the
limitit accepts; a full page at the cap is not the whole answer. Page through large reads has the detail. - On-chain history starts on a different date per chain.
/wallets/{address}/first-fundersays where in itscoverage, so an earliest transfer is the earliest one we hold, not proof of who funded the wallet. - Label provenance degrades rather than fails.
/labels/{address}/provenancereturns fewer rows while one of its label sources is being refreshed. - Hyperliquid position days are counted, not padded. The
snapshotsfield of eachpositionsday in/archive/datasetssays how many 5-minute snapshots it holds, andreconstructed_hourslists the hours rebuilt from fills rather than measured (what the files contain).
Recorder gaps are marked, not hidden
In the Polymarket archive's book_events stream, status carries gap_start and live_resume markers
where the recorder lost and regained the feed. Filter on them before treating a stretch of the book as
continuous — silence in a full-L2 stream is otherwise indistinguishable from a quiet market.
Page through large reads
The four ways the /v1 routes page, a cursor, a cursor in an envelope, an offset and a moving time window, each walked in one script with its stop condition, and the on-chain routes that do not page at all.
Live stream (WebSocket)
One authenticated WebSocket that pushes closed Hyperliquid OHLCV bars as they complete. Lives on vike.io, not on the data.vike.io base URL, and appears in no OpenAPI spec.