Freshness
How current each Data API answer is: the provisional hourly row, the freshness block, the position-match gate, snapshot age and the archive manifest.
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. The WebSocket's own latency is on /v1/stream.
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.
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.
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 archive: the manifest is what is true today
Read generated_at in /archive/manifest.json before trusting a coverage figure. Anything below is a snapshot; the manifest is what is true today.
Recorder gaps are marked, not hidden
In the 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.
Polymarket data model
What the Polymarket endpoints and the archive record: market and token ids, event rows, order-book snapshots and the on-chain settlement.
Endpoint Overview
Every endpoint of the Vike Data API — 68 across 6 namespaces — with the base URL, the one endpoint that is not on it, and the conventions every namespace page assumes.