> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.immix.xyz/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.immix.xyz/_mcp/server.

# Overview

**`Authenticate the session — sent`**

```json title="Authenticate the session — sent"
{
  "op": "auth",
  "reqId": "<string>",
  "params": {
    "token": "<string>"
  }
}
```

**`Join topics — sent`**

```json title="Join topics — sent"
{
  "op": "subscribe",
  "reqId": "<string>",
  "params": {
    "topics": [
      "order"
    ]
  }
}
```

**`Leave topics — sent`**

```json title="Leave topics — sent"
{
  "op": "unsubscribe",
  "reqId": "<string>",
  "params": {
    "topics": [
      "order"
    ]
  }
}
```

**`Authentication succeeded — received`**

```json title="Authentication succeeded — received"
{
  "op": "auth",
  "reqId": "<string>",
  "success": true,
  "session": {
    "capabilities": [
      "users:manage"
    ],
    "expiresAtNs": "<string>"
  }
}
```

**`Subscribe or unsubscribe succeeded — received`**

```json title="Subscribe or unsubscribe succeeded — received"
{
  "op": "subscribe",
  "reqId": "<string>",
  "success": true
}
```

**`A request was refused — received`**

```json title="A request was refused — received"
{
  "op": "<string>",
  "reqId": "<string>",
  "success": false,
  "code": "NOT_PRIMED",
  "message": "<string>",
  "retryable": true,
  "failedTopicIndex": 0
}
```

**`Session liveness and stream freshness — received`**

```json title="Session liveness and stream freshness — received"
{
  "event": "heartbeat",
  "msgType": "heartbeat",
  "data": {
    "streamAgeMs": 0
  }
}
```

**`This session's credential lapses soon — received`**

```json title="This session's credential lapses soon — received"
{
  "event": "sessionExpiring",
  "msgType": "sessionExpiring",
  "data": {
    "expiresAtNs": "<string>",
    "inMs": 0
  }
}
```

**`Why this session is about to be closed — received`**

```json title="Why this session is about to be closed — received"
{
  "event": "sessionClosing",
  "msgType": "sessionClosing",
  "data": {
    "code": 4001,
    "reason": "SESSION_EXPIRED",
    "retryable": true
  }
}
```

Each frame is its shape, read off the contract: `<string>` stands for a value, and a union shows its first form.

**URL** — No public environment serves this socket yet.

Authenticate with `op: auth`, then subscribe to any of six channels; each subscription is acknowledged and then pushed a complete image as numbered snapshot parts, after which every change to a row arrives as a delta on the same channel.

Every channel is the session's organization's whole set. There is no account, symbol or organization parameter on `subscribe` — the topic vocabulary is a closed set of bare channel names, and a client filters what it wants. That is deliberate: a predicate with no parameter has no surface to be widened on.

The client's rule for every channel is **upsert by key into a map that `part: 1` cleared**. Snapshot parts and deltas are the same shape and are applied the same way; the image is complete at `last: true`. A repeat `subscribe` for a held topic re-pushes the image, which is how a client forces a resync — there is no separate op for it.

Writes — `submitOrder` and `cancelOrder` — are **served from 1.1.0**. A success is an OFFER, not an acceptance: it says the command reached the stream and nothing more. The outcome arrives on the `order` channel, correlated by the `clientOrderId` you chose — `orderUpdate` with `status: QUEUED` when the owner admits it, `orderRejected` when it refuses. Do not treat the ack as a placed order.

**Telling two images apart.** A repeat `subscribe` re-pushes the image, so a client can start image N+1 while N is still arriving. Every snapshot part carries a `snapshotId`, the same across one image and different across the next: **apply only the parts whose id matches the one you are currently building, and discard the rest.** That is what keeps a straggling part of the old image out of the map the new one just cleared. The value is opaque — equality only.

**Ordering, and what a client may rely on.** Everything a session receives is produced by one thread, and the guarantees follow from that. A `subscribe` ack precedes the first part of every topic it named. A topic's parts are contiguous — no delta of that topic arrives between them — and every delta that follows carries a `seq` at or past the part's. Topics named in one `subscribe` are imaged in the order named, each complete before the next begins. Across topics there is no ordering guarantee and none is needed: each is a map of its own. A session whose send queue overflows is disconnected rather than throttled; reconnect and resubscribe, since snapshots are local reads.

A **write's ack precedes its outcome**, from the same one thread: the `submitOrder` or `cancelOrder` answer is written before any `order` frame that answers it, so a client never sees the outcome of a command it has not yet seen acknowledged.

**What a subscription delivers is the ORGANIZATION's, not the session's.** The `order` channel carries every order of your organization — every principal's, and orders placed on the HTTP lane as well as this one. A client that toasts refusals must filter to what it sent (match on the `clientOrderId` values it minted, or on `userId`), or it will report another trader's refusal as its own.

And a subscription is what makes an outcome reachable: a session that writes without holding `order` is acked and then **never told what happened** — the ack says the command reached the stream and nothing more. Subscribe to `order` before you write.

**The inbound budget.** 50 frames per second refuses and 500 per second closes, each over a tumbling one-second window, per session. Over the first, the frame is answered `RATE_LIMITED` and **applied to nothing** — the refusal carries the op it answers, so an in-flight request is still resolved. At or past the second, the session is answered and then closed with code `4004`, whatever the op: a flood is transport hygiene. Both numbers are per-deployment configuration and may move; the shape of the answer will not. A `heartbeat` is pushed every 5 seconds by default, and its `streamAgeMs` is how long ago this member last applied a platform fact — pick a dead-socket timeout from a few multiples of that interval, never from `streamAgeMs` itself, which reads high on a quiet stream.

**On `additionalProperties: false`.** Every payload below declares it, and that is a statement about the producer, not an instruction to the consumer: it is how this gateway's own tests refuse to serve a field the document does not carry. **Ignore properties you do not know.** Fields are added in minor versions — the changelog names each — and a client that refuses an unknown property will break on the first one.

**Money.** Every money value is a decimal string rendered from the scale the value itself states — never through floating point, and never at a scale taken from reference data. Parse it as a decimal and compare numerically. Do not read meaning into the digit count: the same amount recorded at different precisions serves different strings, and "2.5" and "2.500000" are the same number. The HTTP lane serves the identical string for the same value.

## Channels

| Topic             | Page                                                            |
| ----------------- | --------------------------------------------------------------- |
| `order`           | [Orders](/api-reference/trading/orders)                         |
| `execution`       | [Executions](/api-reference/trading/executions)                 |
| `accountBalance`  | [Account balances](/api-reference/trading/account-balances)     |
| `account`         | [Accounts](/api-reference/trading/accounts)                     |
| `credential`      | [Credentials](/api-reference/trading/credentials)               |
| `venueCapability` | [Venue capabilities](/api-reference/trading/venue-capabilities) |

## Order entry

| Op            | Page                                                |
| ------------- | --------------------------------------------------- |
| `submitOrder` | [Place order](/api-reference/trading/place-order)   |
| `cancelOrder` | [Cancel order](/api-reference/trading/cancel-order) |

## Authenticate the session

The first op of every session: every other op before it answers UNAUTHENTICATED. The answer carries the GRANT, not the grantee — what this session may do and until when, with no identifier in it, because the client presented the token and already knows who it is.

A session may re-auth with a fresh credential for the SAME principal, which renews its lease. A credential naming a different principal is refused FORBIDDEN\_PRINCIPAL and the session keeps the one it was opened with: the identity is immutable for the life of the socket.

| Parameter | Type   | Required | Description                                                                                     |
| --------- | ------ | -------- | ----------------------------------------------------------------------------------------------- |
| `op`      | string | Yes      | `auth`                                                                                          |
| `reqId`   | string | Yes      | Echoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED. |
| `params`  | object | Yes      |                                                                                                 |
| > `token` | string | Yes      | The bearer token, verbatim.                                                                     |

## Join topics

Validated whole, then answered, then armed — in that order. A frame naming several topics where one is bad arms NONE of them and names the offender in `failedTopicIndex`: a client that had to work out which half of its request took effect could not retry safely.

Membership is a set, so a repeat subscribe for a held topic succeeds AND re-pushes the image. That is the documented resync.

| Parameter  | Type             | Required | Description                                                                                                                                                                                                                                                                                                                          |
| ---------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `op`       | string           | Yes      | `subscribe`                                                                                                                                                                                                                                                                                                                          |
| `reqId`    | string           | Yes      | Echoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED.                                                                                                                                                                                                                                      |
| `params`   | object           | Yes      |                                                                                                                                                                                                                                                                                                                                      |
| > `topics` | array of strings | Yes      | A bare channel name — the whole closed vocabulary. The six served names carry data; the four reserved ones are real names whose domains have not landed and answer TOPIC\_NOT\_ACTIVE, which is a different thing from a typo (UNKNOWN\_TOPIC) and calls for a different response: wait for a release, rather than correct yourself. |

## Leave topics

State, not history: leaving a topic never held succeeds, because the outcome asked for — not holding it — is already true.

| Parameter  | Type             | Required | Description                                                                                                                                                                                                                                                                                                                          |
| ---------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `op`       | string           | Yes      | `unsubscribe`                                                                                                                                                                                                                                                                                                                        |
| `reqId`    | string           | Yes      | Echoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED.                                                                                                                                                                                                                                      |
| `params`   | object           | Yes      |                                                                                                                                                                                                                                                                                                                                      |
| > `topics` | array of strings | Yes      | A bare channel name — the whole closed vocabulary. The six served names carry data; the four reserved ones are real names whose domains have not landed and answer TOPIC\_NOT\_ACTIVE, which is a different thing from a typo (UNKNOWN\_TOPIC) and calls for a different response: wait for a release, rather than correct yourself. |

## Authentication succeeded

The grant, never the grantee. `capabilities` are the register row's bits — not token claims, so they reflect what an administrator has granted rather than what was true when the token was issued — read **at admission** and fixed for the session. An administrator clearing one does not change an open session's grant: re-auth over the socket to pick up the new set. `expiresAtNs` is when the session closes; schedule a re-auth off it rather than decoding the token.

| Parameter        | Type             | Required | Description                                                                                                                                                                                           |
| ---------------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `op`             | string           | Yes      | `auth`                                                                                                                                                                                                |
| `reqId`          | string           | Yes      | Echoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED.                                                                                                       |
| `success`        | boolean          | Yes      | `true`                                                                                                                                                                                                |
| `session`        | object           | Yes      |                                                                                                                                                                                                       |
| > `capabilities` | array of strings | Yes      | Scope strings in choice order — the same vocabulary as the HTTP lane's GET /me, published here as an enum rather than promised in prose. Shape your affordances from these, never from a token claim. |
| > `expiresAtNs`  | string           | Yes      | When this session's credential lapses and the session is closed. "0" for a roster binding, which never expires (local and test only).                                                                 |

## Subscribe or unsubscribe succeeded

For a subscribe, the snapshots follow on the same lane, in the order the topics were named. The ack always precedes them.

| Parameter | Type    | Required | Description                                                                                     |
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------- |
| `op`      | string  | Yes      | One of `subscribe`, `unsubscribe`.                                                              |
| `reqId`   | string  | Yes      | Echoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED. |
| `success` | boolean | Yes      | `true`                                                                                          |

## A request was refused

Answered on the op it answers, so a client routes refusals exactly as it routes successes. The one exception is a frame whose `op` could not be read at all, which answers with `op: "error"` — the only op-less shape on this wire.

`retryable` says whether the IDENTICAL frame may be re-sent after a back-off. It is on the wire rather than left to prose because prose about which codes are retryable is how a client ends up retrying something that will never succeed.

| Parameter          | Type             | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------ | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `op`               | string           | Yes      | The op being answered, or "error" when it could not be read.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `reqId`            | string, nullable | Yes      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `success`          | boolean          | Yes      | `false`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `code`             | string           | Yes      | A closed enum, but tolerate an unknown value: codes are appended as the surface grows, and `retryable` tells you what to do whatever the code says. The door's codes — `INVALID_*`, `UNKNOWN_INSTRUMENT`, `UNKNOWN_ACCOUNT`, `UNKNOWN_ORDER`, `NOT_SERVING`, `OWNER_ABSENT`, `BACKPRESSURE` — arrived in 1.1.0 beside the ops that write, and are the whole of what that version added here. A client generated against 1.0.0 meets them the first time it sends a write. `OWNER_ABSENT` is **reserved and not emitted by this version**: when the orders owner is not established, a write refuses `NOT_SERVING` today. It is published so that a client's handling of it is written once rather than added later, but do not expect to observe it before a release says otherwise. One of `NOT_PRIMED`, `UNAUTHENTICATED`, `SESSION_EXPIRED`, `RATE_LIMITED`, `MALFORMED`, `UNKNOWN_OP`, `INVALID_TOKEN`, `FORBIDDEN_PRINCIPAL`, `ORG_NOT_ACTIVE`, `AWAITING_ADMISSION`, `FORBIDDEN_CAPABILITY`, `UNKNOWN_TOPIC`, `TOPIC_NOT_ACTIVE`, `TOO_MANY_TOPICS`, `INVALID_FIELD`, `INVALID_PRICE`, `INVALID_QTY`, `INVALID_CLIENT_ORDER_ID`, `UNKNOWN_INSTRUMENT`, `UNKNOWN_ACCOUNT`, `UNKNOWN_ORDER`, `NOT_SERVING`, `OWNER_ABSENT`, `BACKPRESSURE`. |
| `message`          | string           | Yes      | Display text. May change between versions; never parse it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `retryable`        | boolean          | Yes      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `failedTopicIndex` | integer          | No       | Present on a topic refusal: the zero-based index into `params.topics` AS SENT of the entry that caused it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |

## Session liveness and stream freshness

`streamAgeMs` is the stream-freshness floor, which is what lets a client tell a quiet market from a stalled member.

| Parameter       | Type    | Required | Description |
| --------------- | ------- | -------- | ----------- |
| `event`         | string  | Yes      | `heartbeat` |
| `msgType`       | string  | Yes      | `heartbeat` |
| `data`          | object  | Yes      |             |
| > `streamAgeMs` | integer | Yes      |             |

## This session's credential lapses soon

Sent once per credential, one lead time before the lapse. Re-auth over the open socket with a fresh credential for the same principal and keep your subscriptions; renewing re-arms the hint. It exists because a client that schedules its own refresh may simply not be running when its timer fires — a throttled background tab — where an inbound frame is something the browser will deliver.

| Parameter       | Type    | Required | Description       |
| --------------- | ------- | -------- | ----------------- |
| `event`         | string  | Yes      | `sessionExpiring` |
| `msgType`       | string  | Yes      | `sessionExpiring` |
| `data`          | object  | Yes      |                   |
| > `expiresAtNs` | string  | Yes      |                   |
| > `inMs`        | integer | Yes      |                   |

## Why this session is about to be closed

Sent immediately before an edge-initiated close, so a client can tell a credential lapse from a network drop and act differently. `retryable` says whether reconnecting can succeed at all; `reason` says what to do about it. SESSION\_EXPIRED wants a fresh credential, RATE\_LIMITED wants a back-off and the same one, and a `retryable: false` close means the register is the obstacle — reconnecting is refused again however long you wait and whatever you present.

The `code` values are RFC 6455's private-use range, and the SAME code travels on the WebSocket close frame that follows. Read either: this message if you are parsing frames and want `retryable` with it, or the close event's `code` if you are not — a browser surfaces that even when the last message was never read.

| Parameter     | Type    | Required | Description                                                                   |
| ------------- | ------- | -------- | ----------------------------------------------------------------------------- |
| `event`       | string  | Yes      | `sessionClosing`                                                              |
| `msgType`     | string  | Yes      | `sessionClosing`                                                              |
| `data`        | object  | Yes      |                                                                               |
| > `code`      | integer | Yes      | One of `4001`, `4002`, `4003`, `4004`.                                        |
| > `reason`    | string  | Yes      | One of `SESSION_EXPIRED`, `AUTH_FAILED`, `PRINCIPAL_REVOKED`, `RATE_LIMITED`. |
| > `retryable` | boolean | Yes      |                                                                               |