Skip to content

Check it yourself

Every value DEBYKO returns says how long it is good for and what that claim rests on. Past that moment the value is not handed to you as a value. This page shows it with five requests you can run yourself. Every response below was captured on production on 2026-09-29 with a free key, and cut to the parts that matter.

The data endpoints need a key. A free one takes a minute at studio.debyko.com/account, no card. The free plan sees two venues — the two with the most 24 h volume, recomputed daily; on 2026-09-29 that was Binance USD-M and Aster — ten instruments, seven days of history, two requests per second and 5,000 a day. Send the key as a header, never in a URL:

Terminal window
export DEBYKO_KEY=dbk_...
Terminal window
curl -s https://api.debyko.com/v2/snapshots \
-H "Authorization: Bearer $DEBYKO_KEY" -H "Content-Type: application/json" \
-d '{"where":"base in (BTC)","layers":["mark","ticker","oi"]}'
{
"served_at": "2026-09-29T11:56:25.752000Z",
"receipt_id": "6ROKoLR98muglig4fE26Xs",
"items": [ { "venue": "BINANCE-USDM", "venue_symbol": "BTCUSDT", "layers": {
"ticker": { "status": "present", "venue_ts": "2026-09-29T11:56:25.507Z", "received_at": "2026-09-29T11:56:25.639Z",
"age_ms": 113, "venue_age_ms": 245,
"valid_until": null, "horizon_source": "connection", "anchor": "venue",
"values": { "last": 84401.5 } },
"mark": { "status": "present", "venue_ts": "2026-09-29T11:56:15Z", "received_at": "2026-09-29T11:56:16.025Z",
"age_ms": 9727, "venue_age_ms": 10752,
"valid_until": "2026-09-29T11:56:45Z", "horizon_source": "measured", "anchor": "venue",
"values": { "mark": 84395.4, "index": 84428.54956522, "basis": -0.000392634545905618 } }
} } ]
}
  • valid_until — the moment after which the value is no longer treated as current. The mark above is polled every 15 s, so it is good for two intervals from the venue’s own timestamp.
  • horizon_source — what that moment rests on: measured (a cadence we measured), documented (the venue’s documentation), assumed (a cadence we assume and say so), venue_declared (the venue said when the next value comes), connection (see below).
  • connection — Binance sends the ticker only when it changes, so silence can mean “nothing changed” or “the feed is dead”. The value holds while the connection that delivered it is alive, and valid_until is null until that connection is lost.
  • anchor — which clock the horizon counts from: venue (its timestamp) or receipt (ours, when the venue sends none).
  • Two ages. age_ms is by our clock, venue_age_ms by the venue’s. They differ when a venue hands out an old value. Aster’s open interest in the same response:
"oi": { "status": "present", "venue_ts": "2026-09-29T11:52:34.694Z", "received_at": "2026-09-29T11:54:00.746Z",
"age_ms": 145006, "venue_age_ms": 231058,
"valid_until": "2026-09-29T12:02:34.694Z", "horizon_source": "measured", "anchor": "venue" }

It reached us 86 seconds after the venue stamped it — it comes from a cache. Counting from our receipt would have called it fresher than it was, so the horizon counts from the venue’s time.

On 2026-09-27 at 20:17:14.729 UTC the collector serving Binance went down. Ask what the Binance ticker was 0.8 s later:

Terminal window
curl -s https://api.debyko.com/v2/snapshots/history \
-H "Authorization: Bearer $DEBYKO_KEY" -H "Content-Type: application/json" \
-d '{"where":"base in (BTC)","layers":["ticker"],"at":["2026-09-27T20:17:15.500Z"]}'
{ "venue": "BINANCE-USDM", "venue_symbol": "BTCUSDT", "layers": { "ticker": { "rows": [ {
"at": "2026-09-27T20:17:15.500Z",
"status": "stale", "reason": "connection_lost", "gap_cause": "collector_down",
"venue_ts": "2026-09-27T20:17:09.859Z", "received_at": "2026-09-27T20:17:09.993Z",
"age_ms": 5507, "venue_age_ms": 5641,
"valid_until": "2026-09-27T20:17:14.729Z", "horizon_source": "connection", "anchor": "venue",
"values": {}
} ] } } }

The value is gone from values. The row still says what it was — received at 20:17:09.993, good until 20:17:14.729, when the connection was lost — so nothing is hidden, but nothing can be read by accident either. A client that never looks at status gets an empty object, not a number that was no longer true.

This instant is inside the free plan’s seven days until 2026-10-04. Live, the most frequent case is Kraken Futures, whose ticker, mark, open interest and 24 h stats are pushed only on change: its sockets drop about 113 times a day, each time for up to about two seconds, and during those seconds its values are stale, connection_lost. Kraken is not in the free plan’s two venues.

Other reasons you can meet: horizon_passed (the value outlived its horizon), state_lag (our own pipeline fell behind — the delay is ours, not the venue’s), horizon_unknown (nothing proves the value was current), freshness_bound (your query asked for something fresher).

Add "allow_stale": true to the same request:

{ "status": "stale", "reason": "connection_lost",
"valid_until": "2026-09-27T20:17:14.729Z", "horizon_source": "connection",
"values": {},
"withheld": { "values": { "last": 84757.1 } } }

The number comes back under withheld, never under values. Using a stale value is allowed; doing it without noticing is not.

Freshness and cadence lists every venue and dataset with its mode, interval, label and the evidence behind it. Today that is 99 pairs:

label pairs
measured 36
assumed 47
documented 16

and 20 of the 99 live on their connection. The 47 assumed ones are a fact about what we know, published as such: an assumed cadence is a weaker claim than a measured one, and horizon_source tells you which one you are reading. GET /v2/instruments states the same fact per layer.

Ask history for the instant of your snapshot — its served_at — once it is settled (120 s):

Terminal window
curl -s https://api.debyko.com/v2/snapshots/history \
-H "Authorization: Bearer $DEBYKO_KEY" -H "Content-Type: application/json" \
-d '{"where":"base in (BTC)","layers":["mark","ticker","oi"],"at":["2026-09-29T11:56:25.752000Z"]}'

It returns what was recorded as of that instant: every value visible then, with its received_at, its horizon and its state. Asked again 30 seconds later it returned the same bytes — items_sha256 5e68c0edfcd58e1851c486b6c00db75e6af02a2a227db9c27f1711c56943bdb3 both times — and it will keep doing so: a later correction of a cadence acts only from the moment it is written. Step 2 was itself such a replay, of an instant two days old; withheld values and their reasons come back the same way.

Replay is not the live answer. The mark and open interest above came back identical; the ticker came back as 84395.4 received at 11:56:19.999, not 84401.5 at 11:56:25.639. History keeps one reading per sampling window, and a stored reading counts from the end of its window: the live answer is the freshest we have seen, history is what we stored, and the live answer can be one reading ahead until that reading’s window closes — further apart in time where the venue updates less often. Each layer’s window is history_cadence on GET /v2/instruments. To keep exactly what you read, log the response itself; receipt_id names it.