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

# WebSocket overview

> One connection, signed handshake, multiplexed channels.

```
wss://api.raeth.exchange/v1/ws
```

One connection carries every channel. Use it instead of polling — the private
channel gives you a live copy of your orders, positions and balances without a
single `GET`.

## Authenticating the handshake

The upgrade request carries the same three `DX-ACCESS-*` headers as REST. The
canonical string is fixed:

```
<timestamp>\nGET\n/v1/ws\n
```

with an empty body. A bad signature is rejected with `401`. There is no
anonymous WebSocket access.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import base64, hashlib, hmac, time
import websocket   # pip install websocket-client

SECRET = base64.b64decode("<your base64 secret>")
ts = str(int(time.time() * 1000))
sig = base64.b64encode(
    hmac.new(SECRET, f"{ts}\nGET\n/v1/ws\n".encode(), hashlib.sha256).digest()
).decode()

ws = websocket.create_connection(
    "wss://api.raeth.exchange/v1/ws",
    header=[
        "DX-ACCESS-KEY: 6",
        f"DX-ACCESS-TIMESTAMP: {ts}",
        f"DX-ACCESS-SIGNATURE: {sig}",
    ],
)
```

The ±5 second clock window applies here too. Because it is checked once at
handshake, a long-lived connection is unaffected by later drift — but a
reconnect with a stale clock will fail.

## Commands

Client to server:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "id": 1, "cmd": "subscribe", "params": { "channels": ["ticker"], "market_ids": [66] } }
```

`cmd` is `subscribe`, `unsubscribe` or `list_subscriptions`. `id` is yours and
is echoed back. Public channels need `market_ids`.

The reply assigns a subscription id, one per channel:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "id": 1, "type": "subscribed", "sid": 3, "channel": "ticker" }
```

## Data envelope

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "sid": 3, "seq": 17, "type": "ticker", "msg": { "...": "..." } }
```

`seq` is **per subscription** and contiguous from 1.

<Warning>
  **A gap in `seq` means you lost data.** Public channels have no replay — the
  recovery is to resubscribe, which starts a fresh snapshot-then-deltas sequence.

  Track `seq` per `sid` and treat any hole as "resubscribe", not as something to
  paper over. The private `user` channel is the exception: it has its own
  `channel_seq` and supports replay.
</Warning>

## Command errors

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "id": 1, "type": "error", "msg": { "wscode": 6, "text": "already subscribed" } }
```

| `wscode` | Meaning                    |
| -------- | -------------------------- |
| 1        | Unable to process          |
| 2        | Params required            |
| 3        | Unknown command            |
| 4        | Unknown channel            |
| 5        | Unknown sid                |
| 6        | Already subscribed         |
| 7        | Auth or scope insufficient |
| 8        | Invalid parameter          |
| 9        | `market_ids` required      |
| 10       | Rate limited               |

## Next

[Channels](/websocket/channels) — what each one carries.
