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

# Stream protocol

> The market-maker WebSocket: channels, frames and limits.

```
wss://api.zeustrade.io/mm/stream
```

Send the key in the `x-api-key` header of the upgrade request. The SDK does this on Node and Bun. Browsers, Deno and Workers cannot set WebSocket headers, so there it goes in the query as `?key=<key>`, which can end up in proxy logs. A wrong key gets 401 on the upgrade and a sixth connection of one key gets 429.

## Client frames

```json theme={null}
{ "op": "subscribe", "channel": "fills", "accounts": ["0x…"] }
{ "op": "subscribe", "channel": "prices", "symbols": ["BTC", "ETH"] }
{ "op": "subscribe", "channel": "exposure" }
{ "op": "unsubscribe", "channel": "keeper" }
```

A new subscribe to a channel replaces the previous one.

## Server frames

Every frame is `{ "channel": "...", "data": ..., "ts": <ms> }`.

| Channel | Data |
| - | - |
| `subscribed`, `unsubscribed` | The subscription |
| `fills` | One fill: account, request key, status, market, side, size, fill price, fees, keeper transaction, time gap, block |
| `exposure` | `/mm/exposure` merged with `/mm/hedge-recommendation`, on subscribe and every 5 seconds |
| `keeper` | `{ medianMs, p95Ms, queueLength }`, on subscribe and every 5 seconds |
| `prices` | `[{ symbol, price, publishTime }]`, publish time in Unix seconds |
| `error` | `{ code, message }` with `BAD_REQUEST`, `TOO_MANY_ACCOUNTS`, `PRICES_DISABLED` or `SOURCE_UNAVAILABLE` |

## Limits

* 5 connections per key and 200 accounts per `fills` subscription.
* The server pings every 15 seconds and closes a connection that misses two pings.
* A connection with more than 1 MB unsent stops receiving everything except `fills` until it catches up. One with more than 8 MB unsent is closed.
* A client frame can be at most 64 KB; a larger one closes the connection with code 1009.
* A connection can send at most 50 frames per second; more closes it with code 1008. The SDK sends one frame per channel for all handles added or stopped in the same tick.
* A new subscriber to `exposure` or `keeper` gets the latest snapshot, at most 5 seconds old.


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