---
title: "Private WebSocket"
method: GET
path: "/ws/private"
tags: ["WebSocket"]
---

# Private WebSocket

`GET /ws/private`

Upgrade to an authenticated WebSocket connection for private account streams.

Send `X-API-KEY`, `X-TIMESTAMP`, and `X-SIGNATURE` headers on the HTTP
upgrade request. Sign the upgrade request with an empty body string.

## Subscribe

```json
{"action":"subscribe","channel":"orders"}
{"action":"subscribe","channel":"fills"}
{"action":"subscribe","channel":"balances"}
```

## Unsubscribe

```json
{"action":"unsubscribe","channel":"orders"}
{"action":"unsubscribe","channel":"fills"}
{"action":"unsubscribe","channel":"balances"}
```

Private channels are account-wide and do not use a `market` parameter.

## Server frames

**orders**
```json
{"channel":"subscribed","subscription":"orders"}
{"channel":"orders","data":{}}
{"channel":"error","message":"..."}
```

**fills** - private trade fills for the authenticated account:
```json
{"channel":"subscribed","subscription":"fills"}
{
  "channel": "fills",
  "data": {
    "trade_id": "33b18c87-1088-4dc7-8bf2-42910a96be76",
    "order_id": "46402c10-64f3-5dcc-8702-9d21ed6aa7bc",
    "client_order_id": "7ec370f1-c77d-4276-b492-0d8a4ecb8ffd",
    "market": "BTCZAR",
    "side": "buy",
    "price": "1050000.00000000",
    "fill_delta": "0.02500000",
    "filled": "0.07500000",
    "remaining": "0.12500000",
    "quantity": "0.02500000",
    "total_value": "26250.00000000",
    "fee": "157.50000000",
    "timestamp": 1784289007
  }
}
```

The `fills` channel emits new private trade fills while you are subscribed.
Use `fill_delta` for the amount filled by this execution, and `filled` / `remaining` for the updated order totals.

| Field | Description |
|---|---|
| `trade_id` | Unique trade public UUID for this fill. |
| `order_id` | UUID of the authenticated user's affected order. |
| `client_order_id` | Client-supplied order ID, present only when the original order included one. |
| `market` | Trading pair symbol. |
| `side` | User-side of the fill, `buy` or `sell`. |
| `price` | Execution price for this fill. |
| `fill_delta` | Amount filled by this execution. |
| `quantity` | Same amount as `fill_delta`, included for consistency with trade history. |
| `filled` | Total order quantity filled after this execution. |
| `remaining` | Total order quantity remaining after this execution. |
| `total_value` | Quote value of this fill. |
| `fee` | Fee charged for this fill. |
| `timestamp` | Unix seconds when the fill executed. |

**balances** - full snapshot pushed every second:
```json
{"channel":"subscribed","subscription":"balances"}
{
  "channel": "balances",
  "data": [
    {"currency":"ZAR","available":"125000.00000000","reserved":"5000.00000000","total":"130000.00000000"},
    {"currency":"BTC","available":"0.45000000","reserved":"0.05000000","total":"0.50000000"},
    {"currency":"ETH","available":"3.20000000","reserved":"0.00000000","total":"3.20000000"}
  ]
}
```

`available` is free to use; `reserved` is locked in open orders; `total` is the sum of both.
The `balances` channel mirrors `GET /balances` exactly.

## Poll intervals

| Channel | Interval | Notes |
|---|---|---|
| `orders` | 1 second | Pushed when order status or filled quantity changes. |
| `fills` | 1 second | Pushed once for each new private trade fill. |
| `balances` | 1 second | Full balance snapshot on every tick. |

## Other responses

- `101` — Switching Protocols - WebSocket upgrade successful.
- `401` — Unauthorized - missing or invalid API key.
- `503` — Trading service unavailable.

---

[API](https://skmtc.dev/altcointrader/apis/altcointrader-api.md) · [All operations](https://skmtc.dev/altcointrader/apis/altcointrader-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/altcointrader/altcointrader-api/revisions/fcbbd5bcd699/schema)
