Message types
Every message is a single JSON object with a type string. Every quote and trade frame carries its event time in ts (unix ms) on every channel; numeric field encoding still differs by asset family.
All frame types
| Type | Sent on | Carries |
|---|---|---|
system | Every connection | Ready, subscribe and unsubscribe acknowledgements, pong, disconnect |
quote | *.quotes | Bid, ask and their sizes |
trade | *.trades | Price and size of a trade |
change | *.quotes *.trades | Previous close and the move against it, with view "full" |
mark | perpetuals.marks | Composite mark price |
rate | bonds.quotes | Daily government bond yield |
status | stocks.status | US trading halt and resume events |
agg | stocks.agg etfs.agg | One settled OHLCV bar |
error | Any channel | A failed client action or a breached limit |
System
Control frames, type: "system", sent in response to connection events and client actions.
| Event | Meaning |
|---|---|
ready | Sent right after a successful upgrade, with ts (unix ms). Wait for it before subscribing. |
subscribed | Echoes the normalized channels and symbols. |
unsubscribed | Echoes the removed channels and symbols. |
pong | Reply to { "action": "ping" }, with the server ts. |
disconnect | The server is closing the socket: HEARTBEAT_TIMEOUT after missed native pongs, or SERVER_RESTART right before a release closes the stream with code 1012. |
{
"type": "system",
"event": "ready",
"ts": 1743512400000
}Quote
type: "quote" on the *.quotes channels. Every frame carries ts (event time, unix ms) and asset; how numbers are encoded depends on the asset family.
| Asset family | Numbers as | Time fields |
|---|---|---|
| Crypto, forex, stocks, perpetuals, futures CFDs | Strings, for example "bid": "62.41" | ts |
| Indices, ETFs, commodities | Numbers on most frames; some tick-driven ETF and index frames arrive as strings. Accept both: one frame never mixes them. | ts, plus timestamp, a mirror kept for older clients. Read ts in new code. |
- Sizes
bid_size,ask_sizeand tradesizearenumber | null(string-encoded on the string channels);nullmeans the consolidated feed has no size at that moment.- Snapshot frames
- Frames replayed from cache right after subscribe carry
"snapshot": true. They appear on stocks, ETFs, indices and commodities; crypto and forex stream continuously and replay only with"view": "full". See Subscriptions. - Futures CFDs
- Quotes on
futures.quotesadd the contract month, its calendar dates, a per-symbolseqand microsecond times. Full reference: Futures CFDs. - Entitlements
- A channel can stay silent until coverage is enabled for your account.
{
"type": "quote",
"channel": "crypto.quotes",
"asset": "crypto",
"symbol": "BTCUSD",
"bid": "84210.12",
"ask": "84210.45",
"bid_size": "1.2",
"ask_size": "0.8",
"ts": 1743512400000
}Trade
type: "trade" on the *.trades channels, with the same encoding rules as quotes. size may be left out or null when the tape has no lot size.
{
"type": "trade",
"channel": "crypto.trades",
"asset": "crypto",
"symbol": "BTCUSD",
"price": "84215.42",
"size": "0.53",
"ts": 1743512400000
}Change
type: "change" goes only to a subscribe with "view": "full". It carries the previous close and the move against it, the same values GET /{asset}/snapshot returns. One frame per symbol, sent whenever a value moves.
- Numbers
prev_close,changeandchange_percentare JSON numbers, on every asset class.changeandchange_percentcan benullwhen no move can be measured. When the previous close rolls to a new day, a frame with all threenulltakes the old values back until the new ones follow.ts- Event time of the price the change is measured from: the last trade, or the book while nothing has printed. It is not unique per symbol, so apply change frames in the order they arrive.
channel- The trades channel of the asset class when you subscribed to it, otherwise the quotes channel. The first frame after subscribe is marked
"snapshot": true.
{
"type": "change",
"channel": "stocks.trades",
"asset": "stocks",
"symbol": "US:KO",
"prev_close": 88.05,
"change": 0.92,
"change_percent": 1.0449,
"ts": 1791818728130
}Mark
type: "mark" on perpetuals.marks: the composite mark price of a perpetual futures contract, the reference its market uses to value positions, as a string with ts. Full reference: Perpetuals.
- Quotes and trades
- Perpetuals reuse
quoteonperpetuals.quotesandtradeonperpetuals.trades. source_count- On every quote and mark: the number of independent sources behind the value.
side- On a trade,
buyorsellwhen the aggressor is known.
{
"type": "mark",
"channel": "perpetuals.marks",
"asset": "perpetuals",
"symbol": "XAUUSDT",
"mark_price": "4316.244",
"source_count": 6,
"ts": 1789640505932
}Rate
type: "rate" on bonds.quotes: the latest published government bond yield for a CC:TENOR symbol. Yields are daily observations, not ticks: the current one arrives as a snapshot right after you subscribe, then one frame per new observation, in practice once per business day, so a quiet hour is normal. Numbers are numbers, and the fields match GET /bond/snapshot.
{
"type": "rate",
"channel": "bonds.quotes",
"asset": "bonds",
"symbol": "US:10Y",
"rate": 4.79,
"unit": "percent",
"date": "2026-09-02",
"prev_rate": 4.76,
"prev_date": "2026-09-01",
"change": 0.03,
"change_bps": 3,
"change_percent": 0.6303,
"ts": 1788307200000,
"timestamp": 1788307200000
}- Dates
tsandtimestampare the observation date (UTC midnight ofdate), never the send time.dateagainstprev_dateis the interval the change covers.- Change fields
changein percentage points,change_bpsin basis points,change_percentrelative toprev_rate. Theprev_*and change fields arenullwhile only one observation exists.- Snapshot
- The frame replayed on subscribe carries
"snapshot": true; frames for a new observation do not.
Status
type: "status" on stocks.status: trading halt and resume events for US-listed equities. Subscribe with symbols (US:KO) or, with the market wildcard add-on, US:* for every US listing. Events arrive from subscribe time on and are never replayed, because a cached status may no longer hold.
{
"type": "status",
"channel": "stocks.status",
"asset": "stocks",
"symbol": "US:KO",
"status": "halted",
"reason": "news_pending",
"ts": 1743512400000
}| status | Meaning |
|---|---|
halted | Trading halted. |
paused | A volatility or limit-up/limit-down pause. |
quoting | Quotations resumed while trading is still halted, the step before some resumptions. |
resumed | Trading resumed. |
reason- Our classification of why:
volatility,market_wide,news_pending,news_released,information_requested,regulatory,corporate_action,operationaloripo. Left out when none applies; new values may be added, so decode it tolerantly. - Scope
- Halt lifecycle events for US equities only: no auction imbalances, price indications or short sale restriction notices. Both fields are derived classifications, under the data notice that covers every feed.
Agg (OHLCV bar)
type: "agg" on stocks.agg: one settled OHLCV bar per subscribed US symbol and interval, with the letters the REST aggregate routes use (o h l c v), the trade count n and the volume-weighted average price vw. ts is the bar start, never the send time; the frame arrives a few seconds after the window closes, and nothing is replayed on subscribe.
{
"type": "agg",
"channel": "stocks.agg",
"asset": "stocks",
"symbol": "US:KO",
"interval": "1m",
"session": "regular",
"o": 88.48,
"h": 88.52,
"l": 88.46,
"c": 88.5,
"v": 41230,
"n": 312,
"vw": 88.4917,
"ts": 1789133400000
}interval1m,5m,15m,1h,4hor1d, chosen per subscribe (default1m).sessionpre,regularorpost: where in the trading day the bar starts. Intraday bars cover the regular session (09:30 to 16:00 ET, early closes honored) on the/stocks/agggrid unless you subscribe with"session": "extended", which adds pre-market and after-hours bars for 1m, 5m and 15m. The daily bar carries the official open and close, labelled at the session date's UTC midnight like the daily REST bar.nandvw- Left out when not available for a bar.
The full contract, including when each interval settles, is in Stocks: OHLCV bars over WebSocket.
etfs.agg sends the same frame for US-listed ETFs, with "channel": "etfs.agg", "asset": "etfs" and the ETF symbol as /etfs/symbols lists it. See ETFs: OHLCV bars over WebSocket.
Error
type: "error" when a client action fails validation or a limit is breached after the connection is open. Subscribe failures use event: "subscribe_failed" (or subscribe_partial_failed). There is no details object; rejected symbols appear in rejected when present.
{
"type": "error",
"event": "subscribe_failed",
"code": "SYMBOL_LIMIT_EXCEEDED",
"message": "rate limit exceeded"
}Every error code is listed on Errors & troubleshooting.