Private Channels
Private channels stream account-specific events. They require a private session token for the 20-byte engine account. Issue the token over HTTP first, then use it in the WebSocket connection. Do not send owner wallet signatures or HMAC secrets inside WebSocket messages.
Channels
| Channel | Purpose |
|---|---|
orders | Order acknowledgements, amendments, cancels, terminal states |
fills | Execution events with fee and liquidity role |
balances | Collateral changes, holds, releases, settlement adjustments |
positions | Position changes, realized and unrealized PnL updates |
risk | Margin, liquidation, and account health updates |
withdrawals | Withdrawal request, checkpoint, proof, and execution status |
Authentication
Issue a private WebSocket token:
POST /api/v1/ws/token
Content-Type: application/json
Authorization: Bearer <private-read-token>
{
"account": "0x2222222222222222222222222222222222222222",
"ttlMs": 600000,
"clientId": "mm-quote-engine-1",
"scope": "private"
}
Use the returned spws1... token as a bearer credential for the private
WebSocket upgrade or subscribe message, according to the endpoint contract for
your deployment:
GET /api/v1/ws/private/0x2222222222222222222222222222222222222222
Authorization: Bearer spws1...
The {account} path parameter is the 20-byte engine account. It is not the
32-byte accountIdHex.
Sequence scope
Private streams are sequenced by account. Clients should persist the last processed account sequence and use it during reconnect to avoid double-processing fills or terminal order states.
Delivery model
Private/drop-copy events are delivered ring-first: reads are served from an
in-memory, per-account replay buffer (a bounded VecDeque) before falling back
to SQL. The buffer is bounded by both a maximum event count and a retention
window (max_events / retention_ms), so it covers the most recent events for
each account. When a requested range is not fully covered by the buffer - for
example after a long disconnect or beyond the retention window - the server
transparently falls back to a SQL read to backfill the gap, then resumes from
the ring.
The ring optimizes the consumer read path: it removes the database read from event fan-out to connected clients. It does not remove the database write from the projection pipeline. The produce path remains DB-write-first: each event is committed and its identifier is derived from the database sequence first, and only then pushed into the in-memory replay buffer. As a result, sequence numbers and ordering are identical whether an event is served from the ring or from SQL.
Ring-first delivery is in effect for WebSocket private channels. FIX drop-copy shares the same replay buffer.
Security notes
- Keep delegated credentials scoped and time-limited.
- Separate read-only stream credentials from trading credentials where possible.
- Treat private stream disconnects as operational alerts for unattended trading.