Live in production, still flag-gated. Perpetuals are gated by
PERPETUALS_PUBLIC_API_ENABLED, enabled in production and staging today; a
deployment with the flag off returns 404 for every perpetual route. Read
Overview before writing code.Number.
Perps magnify small errors through leverage, funding, liquidation thresholds,
and long-running positions. Financial values must survive transport, storage,
and replay without changing meaning.
Beta:
ExactDecimal, nanosecond timestamps, and source/sequence fields
are live in the v2 perpetual book stream. Private-state fields described on
this page remain design contracts.Exact decimals
The two live surfaces spell an exact value differently. Both are exact.No JSON number ever carries a financial value on either surface. Prices,
quantities, volumes, rates, and multipliers are strings or
coefficient/scale pairs. Parse them into a decimal type. A
float round-trip
is a correctness bug, not a rounding preference.("0", 0) on the protobuf, "0" on REST. Services
parse into an exact decimal type and reject non-canonical or out-of-range
values rather than rounding silently. The public gateway independently
re-validates canonical form on every level it forwards.
Exact decimals are used for:
- prices and price bands
- native and normalized quantities
- balances, margin, PnL, and fees
- funding rates and payments
- notionals, multipliers, and risk limits
Twelve fractional digits is the streamer’s floor. Its internal perpetual
book holds prices and sizes as integers scaled by
1e-12 and refuses a venue
value it cannot represent at that scale. The wire type itself is scale-free,
but a venue price with more than twelve fractional digits is dropped rather
than rounded — you will see a missing book, not a wrong one.Missing is not zero
Optional values retain presence. For example:Every quantity has a unit
Quantity fields include a unit. Native quantity is always preserved; normalized base quantity and quote notional are separate optional fields. This prevents a contract count from being aggregated with a base-asset amount.Clocks
Messages distinguish four clocks:
The clocks are never substituted for one another. Unknown venue time stays
unknown. Ordering by receive time is not equivalent to venue event order.
source_time and ingested_time are model concepts, not fields on either live
surface. The published schema carries source_time_ns only on the trade- and
quote-candle messages, which the beta does not emit.
Nanoseconds, everywhere, and the 2^53 trap
Every timestamp on both live surfaces is nanoseconds since the Unix epoch, UTC, and every field name says so.⚠ Nanosecond timestamps do not fit in a JavaScriptNumberA nanosecond epoch timestamp is already far past2^53. The REST snapshot emits these as JSON numbers, soJSON.parsein a browser or Node silently truncates them — you get a plausible-looking timestamp that is wrong in its low-order digits and no longer round-trips. Parse them asBigIntor as text. Protobuf JSON may instead render 64-bit integers as strings; do not coerce those through aNumbereither. The same rule applies tosequenceandsource_epoch.
Identity, duplicates, and revisions
Event identity is separate from event time. A venue event ID is preferred. Where a venue has no stable ID, Kairos uses a documented source-scoped identity that includes enough native fields to make replay deterministic. Some observations can be corrected:- candles can be revised before or after finalization
- predicted funding can be replaced
- account snapshots can supersede earlier projections
No live surface carries a revision today. The revision triple —
source_revision, revision_domain, revision_epoch — is defined on the
trade-candle, quote-candle, and funding messages in the canonical schema, and
none of those messages is published in the beta. The book snapshot has no
revision field at all: its ordering fence is (source_epoch, sequence), and
every frame is a complete replacement rather than a correction.
