Candle Channel
Live 1-minute candle updates per market
Channel name: candle
The candle channel streams the in-progress 1-minute candle built from the same source as the REST candle history API (BBO midpoint and trade match prices). Subscribe to receive real-time OHLCV updates without implementing price logic on the client side.
Subscription
{ "op": "sub", "channel": "candle", "params": { "market": "BTC-PERP" } }params.market is required.
Message Types
Snapshot
On subscribe, the server sends the current in-progress 1-minute candle (if any):
{
"channel": "candle",
"filter": "BTC-PERP",
"type": "snapshot",
"data": {
"o": "50000.00",
"h": "50050.00",
"l": "49980.00",
"px": "50020.00",
"v": "12.5",
"t": 1782186900000000000
},
"gsn": 12345,
"ts": "1782186925763419392"
}If no candle data is available yet (no trades or tight-spread BBO ticks), the snapshot is omitted.
Update
Each order execution that changes the candle state triggers an update:
{
"channel": "candle",
"filter": "BTC-PERP",
"type": "update",
"data": {
"o": "50000.00",
"h": "50050.00",
"l": "49980.00",
"px": "50025.00",
"v": "13.2",
"t": 1782186900000000000
},
"gsn": 12350,
"ts": "1782186930482715648"
}Updates fire on order executions (BBO mid sample + trade matches). Identical candle states are not re-sent.
Fields
| Field | Type | Description |
|---|---|---|
filter | string | Market ID (e.g. "BTC-PERP") |
data.o | string | Open price (first tick of the minute) |
data.h | string | High price (max price in the minute so far) |
data.l | string | Low price (min price in the minute so far) |
data.px | string | Current price (latest BBO mid or trade price, not "close" since live) |
data.v | string | Cumulative volume for this minute (total matched trade size in base asset). This is the running total - use it directly, do not accumulate across updates. |
data.t | number | Minute bucket start timestamp in nanoseconds (UTC). This is the start of the minute, not the end. e.g. t for the 12:05 minute is 12:05:00.000, covering trades from 12:05:00 to 12:05:59. |
gsn | number | Global sequence number |
ts | string | Event timestamp in nanoseconds |
Important: How to Use Updates
Each update message contains the complete state of the current minute's candle. All fields are absolute values, not deltas:
v(volume): This is the cumulative volume for the entire minute so far. Do not add it to a running total. Simply replace your displayed volume with the new value on each update.o,h,l,px: These are the current open/high/low/price for the minute. Replace them on each update.t(time): This is the start of the minute bucket, not the end. For example,t = 2026-06-23T12:05:00Zcovers the period from12:05:00.000up to (but not including)12:06:00.000.
In other words: treat every update as a full snapshot of the current candle. No client-side accumulation needed.
Minute Rollover
When data.t changes from the previous message, the old minute's candle has sealed and a new one has started. The last update before t changed was the final state of the sealed candle. Load historical sealed candles from the REST candles endpoint.
Price Source
Candle data is computed server-side from the same source used by the REST candles endpoint. The WebSocket channel streams the live state; the REST API serves sealed historical candles.