# candles

{% hint style="info" %}

### Currently we offer 1s candlesticks which are not available on Hyperliquid natively. Our candlesticks endpoint also return more than 5k last candles available through the native Hyperliquid API.

{% endhint %}

Streams real-time candle updates as trades happen. Each message contains the latest state of the current candle for the subscribed coin and interval. When a candle closes and a new one opens, both events are sent.

### Subscribe

```json
{
    "method": "subscribe",
    "subscription": {
        "type": "candle",
        "coin": "BTC",
        "interval": "1m"
    }
}
```

| Field      | Type   | Required | Description                                                                                                    |
| ---------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `coin`     | string | Yes      | Coin name (e.g. `"BTC"`, `"ETH"`, `"hyna:ETH"`)                                                                |
| `interval` | string | Yes      | Candle interval: `1s`\*, `1m`, `3m`, `5m`, `15m`, `30m`, `1h`, `2h`, `4h`, `8h`, `12h`, `1d`, `3d`, `1w`, `1M` |

\*`1s` requires **Growth** tier or above.

### Unsubscribe

```json
{
    "method": "unsubscribe",
    "subscription": {
        "type": "candle",
        "coin": "BTC",
        "interval": "1m"
    }
}
```

### Update data format

Each message contains a full candle snapshot. The `x` field indicates whether the candle is finalized (`true`) or still accumulating trades (`false`).

```json
{
    "type": "candle",
    "seq": 42,
    "cursor": "1700000040000",
    "data": {
        "s": "BTC",
        "i": "1m",
        "t": 1700000040000,
        "T": 1700000099999,
        "o": "45000.00",
        "h": "45100.50",
        "l": "44980.00",
        "c": "45050.25",
        "v": "123.45",
        "q": "5560125.00",
        "n": 312,
        "x": false
    }
}
```

### Field definitions

**Envelope fields:**

| Field    | Type   | Description                                                            |
| -------- | ------ | ---------------------------------------------------------------------- |
| `type`   | string | Always `"candle"`                                                      |
| `seq`    | number | Per-subscription sequence number (starts at 1, increments per message) |
| `cursor` | string | Candle open time as millisecond timestamp string (for session replay)  |

**Candle fields (`data`):**

| Field | Type    | Description                                                     |
| ----- | ------- | --------------------------------------------------------------- |
| `s`   | string  | Coin name                                                       |
| `i`   | string  | Interval string                                                 |
| `t`   | number  | Candle open time (milliseconds, interval start)                 |
| `T`   | number  | Candle close time (milliseconds, interval end)                  |
| `o`   | string  | Open price                                                      |
| `h`   | string  | High price                                                      |
| `l`   | string  | Low price                                                       |
| `c`   | string  | Close (latest) price                                            |
| `v`   | string  | Volume in base asset                                            |
| `q`   | string  | Quote volume (notional value)                                   |
| `n`   | number  | Number of trades                                                |
| `x`   | boolean | `true` if the candle is closed/finalized, `false` if still open |

### Examples

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const WebSocket = require('ws');

const ws = new WebSocket(`wss://api.hydromancer.xyz/ws?token=${process.env.HYDROMANCER_API_KEY}`);

ws.on('message', (data) => {
    const msg = JSON.parse(data);

    if (msg.type === 'connected') {
        ws.send(JSON.stringify({
            method: 'subscribe',
            subscription: {
                type: 'candle',
                coin: 'BTC',
                interval: '1m'
            }
        }));
    } else if (msg.type === 'ping') {
        ws.send(JSON.stringify({ type: 'pong' }));
    } else if (msg.type === 'candle') {
        const c = msg.data;
        const status = c.x ? 'CLOSED' : 'open';
        console.log(`[${status}] ${c.s} ${c.i}  O=${c.o} H=${c.h} L=${c.l} C=${c.c} V=${c.v} trades=${c.n}`);
    }
});
```

{% endtab %}

{% tab title="Python" %}

```python
import websocket
import json
import os

def on_message(ws, message):
    msg = json.loads(message)

    if msg['type'] == 'connected':
        ws.send(json.dumps({
            "method": "subscribe",
            "subscription": {
                "type": "candle",
                "coin": "BTC",
                "interval": "1m"
            }
        }))
    elif msg['type'] == 'ping':
        ws.send(json.dumps({'type': 'pong'}))
    elif msg['type'] == 'candle':
        c = msg['data']
        status = 'CLOSED' if c['x'] else 'open'
        print(f"[{status}] {c['s']} {c['i']}  O={c['o']} H={c['h']} L={c['l']} C={c['c']} V={c['v']} trades={c['n']}")

ws = websocket.WebSocketApp(
    f"wss://api.hydromancer.xyz/ws?token={os.environ.get('HYDROMANCER_API_KEY')}",
    on_message=on_message
)
ws.run_forever()
```

{% endtab %}
{% endtabs %}

### Common errors

| Error                | Cause                                                           |
| -------------------- | --------------------------------------------------------------- |
| `Invalid interval`   | Interval string not in the valid list                           |
| `Invalid coin`       | Coin contains invalid characters or exceeds max length          |
| `Connection timeout` | Not responding to ping messages — reply with `{"type": "pong"}` |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hydromancer.xyz/readme/websocket/candles.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
