Skip to main content

Kline (Candlestick)

Channel Name

spot:kline:{symbol}:{interval}

Authentication: not required (public channel).

Supported intervals: 1m, 5m, 15m, 1h, 4h, 1d. See Enums — K-line Intervals.

Description

Provides the latest candle as a snapshot on subscribe, then pushes a running OHLCV update after every fill that falls within the current candle's time window. When the window elapses, the next push carries is_closed: true. Subscribing to multiple intervals for the same symbol produces one push per interval per fill.

Subscribe

Send:

{ "type": "subscribe", "channel": "spot:kline:DFUSDT:1m" }

Response:

{ "type": "subscribed", "channel": "spot:kline:DFUSDT:1m" }

A spot_kline_snapshot is sent immediately after the ack.

Push Format

spot_kline_snapshot

Sent once on subscribe. Contains the latest completed or in-progress candle from the database.

{
"type": "spot_kline_snapshot",
"channel": "spot:kline:DFUSDT:1m",
"data": {
"symbol": "DFUSDT",
"interval": "1m",
"open_time": 1778399940,
"close_time": 1778399999,
"open": "0.4800",
"high": "0.5100",
"low": "0.4700",
"close": "0.5000",
"volume": "10000",
"quote_volume": "4900",
"trade_count": 234,
"is_closed": false
}
}

spot_kline_update

Pushed after every fill that lands inside the current candle's window. The data format is identical to spot_kline_snapshot.

{
"type": "spot_kline_update",
"channel": "spot:kline:DFUSDT:1m",
"data": {
"symbol": "DFUSDT",
"interval": "1m",
"open_time": 1778399940,
"close_time": 1778399999,
"open": "0.4800",
"high": "0.5100",
"low": "0.4700",
"close": "0.5010",
"volume": "10030",
"quote_volume": "4915",
"trade_count": 235,
"is_closed": false
}
}

When is_closed transitions to true, the candle is complete. The next push will carry the new candle's open_time.

FieldTypeDescription
symbolstringMarket identifier.
intervalstringCandle interval, e.g. 1m.
open_timeintegerCandle open — unix seconds.
close_timeintegerCandle close — unix seconds. Equal to open_time + interval_seconds − 1.
openstring (decimal)Opening price of the candle.
highstring (decimal)Highest fill price so far in this candle.
lowstring (decimal)Lowest fill price so far in this candle.
closestring (decimal)Most recent fill price in this candle.
volumestring (decimal)Total base volume in this candle.
quote_volumestring (decimal)Total quote volume in this candle.
trade_countintegerNumber of fills in this candle.
is_closedbooleantrue once the candle's time window has elapsed.

All timestamps are unix seconds.

Update Cadence

  • One spot_kline_update per fill that lands in the interval's time window.
  • Subscribing to 1m + 5m + 1h for the same symbol produces three pushes per fill (one per interval, each updating the respective candle).
  • No fixed polling timer — updates are purely event-driven.

Because each push replaces the running candle completely, a missed push is overwritten by the next one. No resync is needed. See Snapshot ↔ Live Sequencing.

Code Example

const ws = new WebSocket('wss://api-sepolia.p99.world/ws');

// Local candle state keyed by interval
const candles = {};

ws.onopen = () => {
ws.send(JSON.stringify({ type: 'subscribe', channel: 'spot:kline:DFUSDT:1m' }));
ws.send(JSON.stringify({ type: 'subscribe', channel: 'spot:kline:DFUSDT:1h' }));
setInterval(() => ws.send(JSON.stringify({ type: 'ping' })), 30000);
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);

if (msg.type === 'spot_kline_snapshot' || msg.type === 'spot_kline_update') {
const d = msg.data;
candles[d.interval] = d;

if (d.is_closed) {
console.log(`[${d.interval}] Candle closed: O=${d.open} H=${d.high} L=${d.low} C=${d.close} V=${d.volume}`);
// Advance your chart to the next candle
} else {
console.log(`[${d.interval}] Live candle: C=${d.close} V=${d.volume}`);
// Repaint the live (rightmost) bar on your chart
}
}
};