> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperdash.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Streams

> Real-time WebSocket channels, billed per event you acknowledge.

One WebSocket connection carries up to 20 subscriptions. Authenticate with your key in the `Authorization` header of the upgrade request. The key needs the `streams:read` scope, and live keys need a plan that includes streams.

```
wss://data.hyperdash.com/v1/stream
```

```js theme={null}
import WebSocket from "ws";

const ws = new WebSocket("wss://data.hyperdash.com/v1/stream", {
  headers: { Authorization: `Bearer ${process.env.HYPERDASH_API_KEY}` },
});

ws.on("message", async (raw) => {
  const msg = JSON.parse(raw);
  switch (msg.op) {
    case "ready":        // authenticated: subscribe now, resuming from your saved cursor
      ws.send(JSON.stringify({ op: "subscribe", channel: "liquidations", coin: "ETH", cursor: saved.cursor }));
      break;
    case "data":
      await handle(msg.events);                 // process and checkpoint first...
      saved.cursor = msg.cursor;
      ws.send(JSON.stringify({ op: "ack", sub: msg.sub, batch: msg.batch }));  // ...then ack
      break;
    case "gap": backfillOverRest(msg.from, msg.to); break;
    case "ping": ws.send(JSON.stringify({ op: "pong" })); break;
    case "error": console.error(msg.code, msg.detail); break;
  }
});
ws.on("close", (code, reason) => reconnectWithJitter(code, reason.toString()));
```

## Channels

| Channel | Target | Data |
| - | - | - |
| `fills` | `address` | Live fills for one wallet. |
| `ledger` | `address` | Deposits, withdrawals, transfers, sends, vault, and staking moves of one wallet. |
| `twap` | `address` | TWAP status updates of one wallet. |
| `orders` | `address` | Every order event for one wallet: open, fill, cancel, trigger, and reject. Plans cap how many wallets you can subscribe to at once. |
| `trades` | `coin` | Every trade of one market, with taker and maker wallets. |
| `liquidations` | `coin` | Liquidations of one market, or of every market with `"coin": "*"`. |
| `candles` | `coin` | 5-minute candle updates as trades land. |
| `ctx` | `coin` | Mark, oracle, mid, funding, open interest, and 24h volume, on change and at least every 10 seconds. |
| `book` | `coin` | Full 20-level order book snapshots, at most 2 per second. |
| `bbo` | `coin` | Best bid and offer, at most 4 updates per second. |
| `liquidation-levels` | `coin` | The market's liquidation ladder, at most once per second. |
| `stop-levels` | `coin` | The market's resting stop-order ladder, at most once per second. |

## Messages

| From | `op` | Fields |
| - | - | - |
| You | `subscribe` | `channel`, `address`, or `coin`, optional `cursor` |
| You | `ack` | `sub`, `batch` |
| You | `unsubscribe` | `sub` |
| You | `pong` | Optional reply to `ping` |
| Server | `ready` | `key_id`, `environment` |
| Server | `subscribed` | `sub`, `channel`, target, `cursor` |
| Server | `data` | `sub`, `batch`, `cursor`, `events`, `credits` |
| Server | `acked` | `sub`, `batch`, `credits_charged` |
| Server | `unsubscribed` | `sub` |
| Server | `gap` | `sub`, `from`, `to`, `detail` |
| Server | `credits_low` | `remaining` |
| Server | `ping` | Sent every 5 seconds |
| Server | `error` | `code`, `detail`, and optional `sub` and `retry_after_s` |

## Delivery and billing

* Events arrive in `data` batches of up to 100. The next batch waits until you acknowledge the previous one. If you don't acknowledge a batch within 10 seconds, the subscription ends with `ack_timeout`; resubscribe from your last cursor.
* Every channel costs 1 credit per acknowledged event. Replays of events you already paid for are free. A key's per-request maximum applies to each batch.
* Test keys receive a synthetic event every 2 seconds, free.

## Resuming

Keep the `cursor` from each `data` message. After a reconnect, subscribe with it to continue after your last acknowledged batch. Events stay available for about 15 minutes. If what you need is older, or was lost in an ingest outage, you get a `gap` message naming the missing range so you can backfill over REST. You never miss events silently.

## Limits

* 20 subscriptions per connection, and one live subscription per key, channel, and target.
* Connections per workspace follow your plan: Starter 5, Growth 25, Scale 50.
* Wallets on the `orders` channel at once: Starter 10, Growth 50, Scale 200. A subscription can also be refused with `orders stream capacity reached` while server-wide capacity is full; retry later.
* Workspaces that leave 5 or more batches unacknowledged within 10 minutes (including batches dropped by unsubscribing or disconnecting) can't open new subscriptions for a few minutes.
* Messages you send can be at most 64 KiB.

## Close codes

| Code | Meaning |
| - | - |
| 1012 | Server restart. Reconnect with backoff and resume from your cursor. |
| 1008 | Fatal error. The close reason is the error code, for example `credits_exhausted`, `max_credits_exceeded`, `rate_limited`, `invalid_key`, `insufficient_scope`, `feature_not_in_plan`, or `unavailable`. |

The server re-checks your key every 5 seconds, so a revoked key or an exhausted balance closes the connection promptly.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.