# WebSocket reference

The narrative guides live under [Real-time](https://docs.troncharts.xyz/docs/realtime/connecting/). This
page is the flat index — every frame, in one place. The authoritative schema for
each payload is the [AsyncAPI document](https://docs.troncharts.xyz/docs/reference/specs/).

## Endpoints

| Environment | URL |
| --- | --- |
| Production | `wss://api.troncharts.xyz` |

Channels: `/ws/risk`, `/ws/market`, `/ws/quotes`. Append `?encoding=msgpack` to
any of them for binary server→client frames.

## `/ws/risk` — client → server

| Frame | Tier | Purpose |
| --- | --- | --- |
| `Authenticate` | `readonly` | First message on the socket. |
| `Ping` | `readonly` | Heartbeat. Server replies `Pong`. |
| `Alive` | `readonly` | Legacy heartbeat, no reply. |
| `Resume` | `readonly` | Replay buffered frames after `lastSeq`. |
| `Subscribe` / `Unsubscribe` | `readonly` | Add or drop `topics`; `Subscribe` optionally re-scopes to an owned `accountId`. |
| `Get-Margin` | `readonly` | Margin snapshot. |
| `Get-Balance` | `readonly` | Balance snapshot. |
| `Get-Risk-Update` | `readonly` | Risk snapshot. |
| `Get-Position-Update` | `readonly` | Position snapshot. |
| `Get-open-orders` | `readonly` | Working-order snapshot. |
| `Request-Trade-History` | `readonly` | Recent trades. |
| `Order-Sign-Result` | `liquidation` | Return a client-side signature. |
| `Cancel-Order-Intent` | `liquidation` | Cancel a working order. |
| `Replace-Order-Intent` | `liquidation` | Re-price or re-size a working order. |
| `Bracket-Insert` | `liquidation` | Attach TP/SL legs. |
| `Bracket-Modify` | `liquidation` | Move a leg. |
| `Bracket-Cancel` | `liquidation` | Remove a leg. |
| `Position-Close` | `liquidation` | Close a position. |

The tier column is the **minimum**; a higher tier always passes. The socket
only distinguishes `readonly` from the rest — every write frame above is open
to `liquidation` and `fullTrading` alike, and `readonly` is rejected with
`Result { ok: false, error: "tier_readonly" }`. The REST `/api/v1/oms/*`
surface draws a finer line; see [tiers](https://docs.troncharts.xyz/docs/auth/scopes/).

`Subscribe` requires a non-empty `topics` array. The socket receives no push
frames until it subscribes — see
[topics](https://docs.troncharts.xyz/docs/realtime/connecting/#subscribe-to-topics) for the full list and
the frames each one unlocks.

## `/ws/risk` — server → client

| Frame | Carries |
| --- | --- |
| `Authenticated` | Handshake success. Unsequenced. |
| `Result` | Per-frame outcome, including rejections. |
| `Pong` | Heartbeat reply. Unsequenced. |
| `Account-State-Update` | Aggregate account state. |
| `Balance-Update` | Balance. |
| `Margin-Update` | Margin. |
| `Funding-Update` | Funding and fee rows. |
| `Risk-Update` | Risk metrics. |
| `Blocking-Update` | Trading blocks on the account. |
| `Position-Update` | One position changed. |
| `Position-Removed` | A position closed. |
| `Position-Snapshot` | Full position set — seeds your view. |
| `Open-Orders-Update` | Working-order book. |
| `Order-Intent` | An intent was accepted. |
| `Order-Intent-Update` | Lifecycle progress, venue ids, fills, terminal state. |
| `Order-Update` | Order state in the external vocabulary. |
| `Trade-Update` | A round trip closed. |
| `Fill` | One execution. Never coalesced. |
| `Trade-History-Result` | Reply to `Request-Trade-History`. |
| `Account-Event` | Account lifecycle event. |
| `Prop-Account-Update` | Challenge progress and status. |
| `Prop-Account-Status-Changed` | A prop account changed state. |
| `Companion-Event` | Derived risk / position note. |
| `IP-Update` | Session IP changed. |
| `LoggedOff` | The session ended server-side. Carries `reason` and a `ts`. |
| `Resync-Required` | Drop local state and re-snapshot. |

Note `LoggedOff` has no hyphen on the wire. There is **no** `Bracket-Info`
push: bracket-leg state arrives on `Open-Orders-Update` and
`Order-Intent-Update` like any other working order.

Every frame that leaves the outbox carries a monotonic `seq`; `Pong` and
`Authenticated` do not. See
[sequence numbers](https://docs.troncharts.xyz/docs/realtime/risk/#sequence-numbers--detect-a-gap).

## `/ws/quotes`

Public — no `Authenticate` required.

Client → server: `Subscribe-Quote { venue, symbol }`,
`Subscribe-Quotes-Bulk { items }` (up to 200 pairs), `Unsubscribe-Quote`,
`Unsubscribe-All`, `Get-Quote`, `Authenticate`, `Ping`.

Server → client: `Quote-Update`, `Authenticated`, `Pong`, `Result`.

`Quote-Update` carries `{ venue, symbol, mid, bid, ask, last, source, ts }`,
plus `marketStatus` on futures and B3. The mark is `mid`, a decimal string;
`bid`, `ask` and `last` are reserved and always `null`. `ts` is ISO-8601.

## `/ws/market`

Public — no `Authenticate` required.

Client → server: `Subscribe-Depth`, `Subscribe-Depth-L3`, `Subscribe-Tape`,
`Subscribe-VAP`, `Subscribe-BBO`, `Subscribe-Candles`, each with its matching
`Unsubscribe-*`, plus `Unsubscribe-All`, `Authenticate`, `Ping`. Every
subscribe frame takes `venue` and `symbol` as separate fields; the candle pair
also takes `interval`.

Server → client: `Depth-Update`, `Order-Book-Update`, `Tape-Update`,
`VAP-Update`, `BBO-Update`, `Candle-Update`, `Authenticated`, `Pong`, `Result`.

Each stream serves its own set of venues and rejects the rest as
`invalid_frame` — see [Market channel](https://docs.troncharts.xyz/docs/realtime/market/) for the table.
The tape is batched into one frame per flush window; iterate `trades`.

## Webhooks

Not a socket, but documented alongside the frames because it answers the same
need. See [Webhooks](https://docs.troncharts.xyz/docs/realtime/webhooks/) for the envelope, headers, retry
schedule, signature verification, and the six subscribable event categories.