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.BTC, BTC-PERP, or xyz:BTC is not a primary key. It
is a display label that can change. Identity is the canonical instrument id
plus the venue, environment, and integration that scope it.
Beta: The full public
InstrumentRef is carried by every v2 perpetual
book. Private account and execution identities remain outside the public
market-data beta.Instrument reference
Every public and private record carries an instrument reference. These are the field names ofkairos.v2.InstrumentRef, carried on every v2 book snapshot:
An integration and environment are part of identity. Test and production data,
or two independently configured venue connections, must never collide.
What the gateway refuses
The public gateway drops a snapshot whose:instrument_typeis notINSTRUMENT_TYPE_PERPETUALnative_quantity_unitis neitherBASE_ASSETnorCONTRACTSvenue_instrument_id,display_symbol,base_asset_id,quote_asset_id,collateral_asset_id,environment, orintegration_idis empty
settlement_asset_id is the one asset role the schema marks optional and the
gateway does not require.
The rejection is silent. An invalid message is dropped before fan-out. There is no client error frame. From the consumer’s side this is indistinguishable from an instrument that simply has no updates.
environmentis per venue and is not uniform. Hyperliquid and Polymarket Perps reportmainnet; Kalshi Margin reportsproduction. Compare it exactly rather than assuming one spelling.
Asset roles are not interchangeable
Base, quote, collateral, and settlement assets can differ. A price may be quoted in one asset while collateral and realized PnL use another. Use the named role. Do not assume every market is base/USDC with USDC settlement. Market Data API snapshots expose these roles asbase_asset_id,
quote_asset_id, collateral_asset_id, and settlement_asset_id. All four
are required there.
Extra fields from the instruments catalog
GET /perpetuals/instruments additionally carries price_increment,
size_increment, contract_multiplier, max_leverage, isolated_only, and a
status of active, inactive, closed, delisted, or unknown.
Each instrument also carries a venue-discriminated metadata object — keyed by
kind, which must equal the instrument’s venue — holding facts that have no
cross-venue meaning:
Hyperliquid instrument ids
Hyperliquid’s standard main-dex perpetuals have a fixed canonical id:
The quote asset defaults to USDT, with per-symbol exceptions — currently
HYPE and PURR, which quote in USDC. Collateral and settlement are USDC
for all of them, so quote, collateral, and settlement roles must stay separate.
This is one identifier used everywhere: the streamed book, the funding
observations, the trade facts, and the Market Data API snapshot all key on it,
which is what makes them joinable. The rule lives in a single shared contract
file and is code-generated into every consumer rather than hand-copied — a
drifted copy would change an instrument id and silently orphan every fact for
it.
Venue coin names are case-sensitive; canonical ids are not
You cannot recover a venue coin from a canonical id by string
manipulation.
kPEPE is the venue’s spelling; KPEPE and kpepe are not
coins the venue accepts. Because the canonical id lowercases the symbol,
kPEPE and KPEPE both collapse to hl-mainnet-kpepe-usdt — and only one
of them exists.A wrong-cased coin fails invisibly. Subscribing to Hyperliquid’s
WebSocket with one closes the socket with no error and no close frame,
which is indistinguishable from a network drop. Handle it explicitly.
Native quantity
native_quantity_unit determines what the venue’s quantity means:
The canonical model defines all three; the v2 gateway accepts only
BASE_ASSET and CONTRACTS on a book snapshot, as listed above.
Normalized base quantity and quote notional can be published alongside native
quantity only when the conversion inputs and rules are known.
Lifecycle
Perpetuals do not have a scheduled expiry, but they still have lifecycle state. An instrument can be:- listed but not yet active
- active
- halted
- close-only or reduce-only
- delisted
Alias resolution
Venue symbols and aliases are resolved at ingestion. The resolution result must include the venue, environment, and effective period. Silent alias fallback is unsafe: if a symbol is unknown or ambiguous, ingestion fails until metadata establishes the identity. The streamer implements exactly that for Hyperliquid. A canonical id is resolved back to a venue coin from the venue’s own asset universe, cached for five minutes with a thirty-second floor between refetches after a miss.
In both cases the adapter refuses to subscribe rather than guessing a symbol.
What an unknown instrument looks like
Each surface fails differently. This table is worth memorizing before you debug a silent stream:On the WebSocket, “acknowledged” does not mean “exists”. A misspelled
instrument id produces a healthy-looking subscription that is silent
forever. If you see no frames, verify the id against
GET /perpetuals/instruments before suspecting the network.Consumer invariants
- Join on stable IDs, not display symbols.
- Partition venue-native IDs by provider and environment.
- Treat asset roles and quantity units as required.
- Do not treat delisted instruments as expired prediction markets.
- Keep venue-native metadata for audit and replay.

