> For the complete documentation index, see [llms.txt](https://docs.dmex.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dmex.app/api-docs/websocket/chart-klines.md).

# Chart KLines

## Chart WebSocket API

Real-time kline (candlestick) data streaming via WebSocket.

### Connection

```
ws://back.dmex.app/ws/chart
```

### Message Format

All messages use JSON with the following structure:

```json
{
  "type": "message_type",
  "data": { ... }
}
```

### Client → Server Messages

#### Subscribe to Kline Stream

Subscribe to real-time candlestick updates for a symbol/interval pair.

```json
{
  "type": "subscribeKlineStream",
  "data": {
    "symbol": "BTCUSDT",
    "interval": "1m"
  }
}
```

**Parameters:**

* `symbol` - Trading pair (e.g., `BTCUSDT`, `ETHUSDT`)
* `interval` - Candle interval (e.g., `1m`, `5m`, `15m`, `1h`, `4h`, `1d`)

#### Unsubscribe from Kline Stream

```json
{
  "type": "unsubscribeKlineStream",
  "data": {
    "symbol": "BTCUSDT",
    "interval": "1m"
  }
}
```

#### Ping

Keep connection alive with application-level ping.

```json
{
  "type": "ping",
  "data": null
}
```

### Server → Client Messages

#### Subscription Confirmed

Sent after successful subscription.

```json
{
  "type": "subscriptionConfirmed",
  "data": {
    "symbol": "BTCUSDT",
    "interval": "1m"
  }
}
```

#### Kline Stream Update

Real-time candle data pushed to subscribed clients.

```json
{
  "type": "klineStreamUpdate",
  "data": {
    "stream": "btcusdt_1m",
    "data": {
      "k": {
        "t": 1704067200000,
        "o": "42000.00",
        "h": "42150.00",
        "l": "41950.00",
        "c": "42100.00",
        "v": "125.5",
        "x": false
      }
    }
  }
}
```

**Candle fields (`k`):**

| Field | Description                |
| ----- | -------------------------- |
| `t`   | Candle open time (Unix ms) |
| `o`   | Open price                 |
| `h`   | High price                 |
| `l`   | Low price                  |
| `c`   | Close price                |
| `v`   | Volume                     |
| `x`   | Is candle closed           |

#### Pong

Response to client ping.

```json
{
  "type": "pong",
  "data": null
}
```

### Example Usage (JavaScript)

```javascript
const ws = new WebSocket('ws://back.dmex.app/ws/chart');

ws.onopen = () => {
  // Subscribe to BTC 1-minute candles
  ws.send(JSON.stringify({
    type: 'subscribeKlineStream',
    data: { symbol: 'BTCUSDT', interval: '1m' }
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  
  switch (msg.type) {
    case 'subscriptionConfirmed':
      console.log('Subscribed to:', msg.data.symbol, msg.data.interval);
      break;
    case 'klineStreamUpdate':
      const candle = msg.data.data.k;
      console.log('Candle update:', candle);
      break;
    case 'pong':
      console.log('Pong received');
      break;
  }
};

// Keep-alive ping every 30 seconds
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: 'ping', data: null }));
  }
}, 30000);
```

### Connection Management

* **Ping/Pong**: Server sends WebSocket ping frames every 54 seconds
* **Read timeout**: 60 seconds (reset on pong)
* **Connection cleanup**: Stale connections removed after 120 seconds of inactivity
* **Throttling**: Updates are throttled to max 1 broadcast per 300ms per symbol to prevent flooding

### Multiple Subscriptions

You can subscribe to multiple symbol/interval pairs on a single connection:

```javascript
// Subscribe to multiple streams
ws.send(JSON.stringify({ type: 'subscribeKlineStream', data: { symbol: 'BTCUSDT', interval: '1m' } }));
ws.send(JSON.stringify({ type: 'subscribeKlineStream', data: { symbol: 'BTCUSDT', interval: '5m' } }));
ws.send(JSON.stringify({ type: 'subscribeKlineStream', data: { symbol: 'ETHUSDT', interval: '1m' } }));
```

### Notes

* Symbol names are case-insensitive (internally converted to lowercase)
* Subscription keys are formatted as `{symbol}_{interval}` (e.g., `btcusdt_1m`)
* The `stream` field in updates matches this subscription key format
