category(1–9) identifies the series. It appears on every round object and everyroundsWebSocket frame, and filtersGET /v1/rounds.feed(0–2) identifies the price source. It scopesGET /v1/oracle/priceand appears on everyoracleWebSocket frame.
The registry
Several series share one feed: all three BTC cadences settle against feed 0.
Going the other way is unambiguous — a category maps to exactly one feed.
The venue API speaks in integers:
market_id, round_number, category,
feed. Human tickers like OB-XAU-UD-60S-260917-025111 are a display
convention of the web app and are not fields on any venue endpoint. Do not
parse them out of the API; derive your own labels from category.Getting every live market
GET /v1/markets?status=trading returns live slots across all nine series
in one page — one market per series while every feed is up.
market_id → category mapping for the life of the round only.
market_id is recycled, and a recycled slot can come back in a different
series. Re-read the round before acting on a cached mapping. See
Rounds and markets.
Getting one asset
GET /v1/rounds takes an optional category filter and returns that series’
rounds newest round_number first:
?category=N&limit=1 a usable “current round for this series” — but check
status, because it will read frozen or settled during the gap between
rounds, and the pre-created rounds waiting behind it are not listed yet.
To follow one asset across all three cadences, accept its three categories
(BTC: 1, 2, 3 — gold: 4, 5, 6 — crude: 7, 8, 9). There is no “subscribe by
category”: you pass market_ids on the per-market channels, and filter the
global rounds channel on category yourself.
Prices, per asset
GET /v1/oracle/price takes an optional feed:
- Omitting
feedmeans feed 0, so every client written before multi-asset keeps its exact meaning. - The response does not echo the feed. Track which feed you asked for. The
WebSocket
oraclechannel does name it — see Channels. priceis an integer in units of 1e-8 USD, as a decimal string. The magnitudes differ by orders of magnitude across assets: BTC around10000000000000, gold around424518000000, crude around6231000000. Never infer the asset from the magnitude, and never hold these in a float.fresh_source_countis how many independent sources were live behind the median. BTC medians up to five CEX perp streams; gold and WTI each come from a single QFEX underlier, so1is normal and healthy for them. Do not hardcode a floor of 3.- A
feedthat is not a u16 is rejected400. A valid-but-unknown feed is not an error — it answers the zero sentinel below.
Market hours and dark feeds
BTC trades 24/7. Gold and crude do not.
When a session closes, the upstream feed stops publishing and the venue stops
opening new rounds for every series on that feed. The round that was already
trading freezes and settles normally; nothing is stranded.
There is no session calendar on the API.
GET /v1/exchange/schedule covers
venue maintenance windows, not market hours. The venue deliberately reacts to
the feed actually being dark rather than trusting a hardcoded timetable, so it
covers upstream outages as well as scheduled closes.price: "0" means “no valid tick” — closed session, upstream outage, or a
venue that has just restarted and not yet folded a tick. It is a normal 200,
not an error, and no traded asset is ever really worth 0. Poll
GET /v1/oracle/price?feed=N and treat price == "0" as “this asset is not
opening rounds right now”.
WebSocket
Theoracle and rounds channels are global. They are not per-market and
take no market_ids: one subscription receives every tick from every feed and
every lifecycle event from all nine series, interleaved. Scope them client-side
on the feed and category fields that each frame carries.
The per-market channels (orderbook_snapshot, orderbook_delta, trades) are
unchanged — you name the market_ids you want, and one subscription can span
markets from different assets.
See Channels for payloads and filtering examples.
Related
- Rounds and markets — identifiers, settlement, recycling
- Pauses and rounds — freeze, dark feeds, cancel-all
- Channels —
feedandcategoryon the global channels - Your first request — the discovery calls end to end