vike

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}/balances reads 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_usd above 0 can skip the newest, still unpriced hours.
  • Leaderboard windows are rebuilt once a day. The 24h, 7d, 30d and 90d figures of /wallets/discover can 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 limit it 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-funder says where in its coverage, 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}/provenance returns fewer rows while one of its label sources is being refreshed.
  • Hyperliquid position days are counted, not padded. The snapshots field of each positions day in /archive/datasets says how many 5-minute snapshots it holds, and reconstructed_hours lists 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.

On this page