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

# WebSocket Events

> Real-time event reference for the Limitless WebSocket API

## Connection

**URL:** `wss://ws.limitless.exchange`
**Namespace:** `/markets`
**Transport:** WebSocket only (no polling fallback)

Authenticated channels (positions, order events) require an HMAC-signed handshake. Sign a fixed canonical message — `{ISO-8601 timestamp}\nGET\n/socket.io/?EIO=4&transport=websocket\n` — with the base64-decoded `secret` and pass three headers as `extraHeaders`:

```typescript theme={null}
import { createHmac } from 'crypto';
import { io } from 'socket.io-client';

function wsAuthHeaders(tokenId: string, secret: string) {
  const timestamp = new Date().toISOString();
  const message = `${timestamp}\nGET\n/socket.io/?EIO=4&transport=websocket\n`;
  const signature = createHmac('sha256', Buffer.from(secret, 'base64'))
    .update(message)
    .digest('base64');
  return { 'lmts-api-key': tokenId, 'lmts-timestamp': timestamp, 'lmts-signature': signature };
}

const socket = io('wss://ws.limitless.exchange/markets', {
  transports: ['websocket'],
  extraHeaders: wsAuthHeaders(TOKEN_ID, SECRET),
});
```

See [Authentication](/developers/authentication) for how to generate `TOKEN_ID` and `SECRET`. If you use an official SDK, prefer its WebSocket client, which signs the handshake automatically from `hmacCredentials` (TypeScript) / `hmac_credentials` (Python) / `WithHMACCredentials` (Go).

## Subscribing to Market Data

Subscribe to price and orderbook updates by emitting `subscribe_market_prices`:

```typescript theme={null}
// AMM price updates
socket.emit('subscribe_market_prices', {
  marketAddresses: ['0x1234...']
});

// CLOB orderbook updates
socket.emit('subscribe_market_prices', {
  marketSlugs: ['btc-100k-weekly']
});

// Both at once (recommended to avoid overwriting subscriptions)
socket.emit('subscribe_market_prices', {
  marketAddresses: ['0x1234...'],
  marketSlugs: ['btc-100k-weekly']
});
```

<Warning>
  Subscriptions **replace** previous ones. If you want both AMM prices and CLOB orderbook, send both `marketAddresses` and `marketSlugs` together in a single call.
</Warning>

## Subscribing to Position Updates

Subscribe to real-time position changes by emitting `subscribe_positions`. This requires an HMAC-signed handshake — see [Authentication](/developers/authentication).

`subscribe_positions` accepts the same payload as `subscribe_market_prices`:

| Field             | Type       | Description                        |
| ----------------- | ---------- | ---------------------------------- |
| `marketAddresses` | `string[]` | Contract addresses for AMM markets |
| `marketSlugs`     | `string[]` | Slugs for CLOB markets             |

```typescript theme={null}
import { io } from 'socket.io-client';

const socket = io('wss://ws.limitless.exchange/markets', {
  transports: ['websocket'],
  extraHeaders: wsAuthHeaders(TOKEN_ID, SECRET),
});

socket.on('connect', () => {
  // Subscribe to position updates for specific markets
  socket.emit('subscribe_positions', {
    marketAddresses: ['0x1234...'],   // AMM markets
    marketSlugs: ['btc-100k-weekly'], // CLOB markets
  });
});

// Confirmation
socket.on('system', (data) => {
  console.log(data);
  // { message: 'Successfully subscribed to position updates', markets: { addresses: [...], slugs: [...] } }
});

// Position updates
socket.on('positions', (data) => {
  console.log('Position update:', data);
});
```

<Warning>
  Like `subscribe_market_prices`, calling `subscribe_positions` again **replaces** the previous subscription. Include all markets in a single call.
</Warning>

<Note>
  Position updates are pushed automatically when your balances change (e.g. after a trade is mined). You do not need to poll.
</Note>

## Subscribing to Order Events

Subscribe to the full lifecycle of your CLOB orders by emitting `subscribe_order_events`. Requires an HMAC-signed handshake — see [Authentication](/developers/authentication). The subscription takes no payload — it is a per-user channel that delivers events for every order you are party to.

Several event shapes arrive on the same Socket.IO event name `orderEvent`. Distinguish first by `source`, then by `type`:

* **`OME`** — off-chain matching engine updates: resting-order state changes (`PLACEMENT`, `UPDATE`, `CANCELLATION`) and the terminal result of an immediate-or-cancel order (`EXECUTION`).
* **`SETTLEMENT`** — settlement lifecycle for CLOB trades: a provisional `MATCHED` the moment the engine fills your order (before the on-chain transaction), then a terminal `MINED` or `FAILED`.

```typescript theme={null}
import { io } from 'socket.io-client';

const socket = io('wss://ws.limitless.exchange/markets', {
  transports: ['websocket'],
  extraHeaders: wsAuthHeaders(TOKEN_ID, SECRET),
});

socket.on('connect', () => {
  socket.emit('subscribe_order_events');
});

socket.on('system', (msg) => {
  // { message: 'Successfully subscribed to order event updates' }
  console.log(msg);
});

socket.on('orderEvent', (data) => {
  if (data.source === 'OME' && data.type === 'EXECUTION') {
    console.log(`[EXECUTION ${data.status}] order=${data.orderId} remaining=${data.remainingSize}`);
  } else if (data.source === 'OME') {
    console.log(`[OME ${data.type}] order=${data.orderId} clientOrder=${data.clientOrderId ?? '(none)'}`);
  } else {
    console.log(
      `[SETTLEMENT ${data.type}] order=${data.orderId} clientOrder=${data.clientOrderId ?? '(none)'} tx=${data.txHash ?? '(none)'}`,
    );
  }
});
```

<Warning>
  **One subscription per connection.** Sending `subscribe_order_events` a second time re-binds; the previous subscription is cancelled. There is no payload.
</Warning>

<Note>
  **Channel is per-user, not per-market.** You receive events for every order you are party to (as taker or maker) — the subscription cannot be narrowed by market. Filter client-side on `marketId` / `marketSlug` if needed.
</Note>

<Warning>
  **Ordering is not guaranteed across sources.** OME and SETTLEMENT events for the same order can arrive in either order within a few seconds — settlement can land before the corresponding `UPDATE`, or vice versa. Treat them as independent streams that both reference `orderId` / `takerOrderId`.
</Warning>

<Note>
  **Resubscribe on reconnect.** Subscriptions are not persisted server-side across disconnects — your `connect` handler must re-emit `subscribe_order_events`.
</Note>

<Note>
  **Server-side deduplication.** Repeated emissions within a 60-second sliding window are dropped, so retries and replays will not double-deliver. Client-side dedup is only required if you persist events across reconnects yourself.
</Note>

<Warning>
  **Auth failures surface on the `exception` channel.** If the HMAC auth headers are missing, invalid, or revoked, the guard emits a `WsException` to the client's `exception` event and no `orderEvent` frames arrive. Subscribe to `socket.on('exception', ...)` if you want to detect auth failures rather than silently miss the stream.
</Warning>

<Note>
  **Taker delay — order submission can be asynchronous.** Some markets apply a short hold to marketable (taker) orders before the matching engine fills them. On such a market, `POST /orders` returns right away with `execution.settlementStatus: "DELAYED"` and an `eligibleAt` timestamp instead of blocking until settlement — so this stream is how you observe the fill: wait for the provisional `MATCHED` frame, then the terminal `MINED` / `FAILED`, correlating by `clientOrderId` / `tradeEventId`. Maintenance mode can postpone delayed fills beyond `eligibleAt`; keep the order open in your integration until a terminal event arrives. `postOnly` (maker) orders are never delayed. A market's current delay is readable as `settings.takerDelayMs` (milliseconds; `0` = none) on the market response.
</Note>

## Subscribing to Market Lifecycle Events

Subscribe to market creation and resolution events by emitting `subscribe_market_lifecycle`. No authentication required.

```typescript theme={null}
socket.on('connect', () => {
  socket.emit('subscribe_market_lifecycle');
});

socket.on('marketCreated', (data) => {
  console.log('New market:', data.slug, data.title);
});

socket.on('marketResolved', (data) => {
  console.log('Market resolved:', data.slug, data.winningOutcome);
});
```

<Note>
  `marketResolved` is also emitted to existing per-market room subscribers automatically (CLOB: `market:{slug}`, AMM: `market:{address}`) — you don't need a separate lifecycle subscription to receive resolution events for markets you're already watching.
</Note>

To unsubscribe:

```typescript theme={null}
socket.emit('unsubscribe_market_lifecycle');
```

## Event Reference

| Event                          | Direction       | Auth Required | Description                                                                   |
| ------------------------------ | --------------- | ------------- | ----------------------------------------------------------------------------- |
| `connect`                      | Server → Client | No            | Connection established                                                        |
| `disconnect`                   | Server → Client | No            | Connection lost                                                               |
| `subscribe_market_prices`      | Client → Server | No            | Subscribe to price/orderbook updates                                          |
| `subscribe_positions`          | Client → Server | Yes           | Subscribe to position updates                                                 |
| `subscribe_order_events`       | Client → Server | Yes           | Subscribe to OME and settlement events for your CLOB orders                   |
| `subscribe_market_lifecycle`   | Client → Server | No            | Subscribe to market creation/resolution events                                |
| `unsubscribe_market_lifecycle` | Client → Server | No            | Unsubscribe from market lifecycle events                                      |
| `newPriceData`                 | Server → Client | No            | AMM market price update                                                       |
| `orderbookUpdate`              | Server → Client | No            | CLOB orderbook update                                                         |
| `marketCreated`                | Server → Client | No            | New market created and visible                                                |
| `marketResolved`               | Server → Client | No            | Market resolved with winning outcome                                          |
| `positions`                    | Server → Client | Yes           | Position balance update                                                       |
| `orderEvent`                   | Server → Client | Yes           | OME lifecycle, FAK/FOK execution, and settlement updates for your CLOB orders |
| `system`                       | Server → Client | No            | System notifications                                                          |
| `authenticated`                | Server → Client | Yes           | Authentication confirmation                                                   |
| `exception`                    | Server → Client | No            | Error notifications                                                           |

## Event Payloads

### `newPriceData`

```json theme={null}
{
  "marketAddress": "0x1234...",
  "updatedPrices": {
    "yes": "0.65",
    "no": "0.35"
  },
  "blockNumber": 12345678,
  "timestamp": "2024-01-01T00:00:00.000Z"
}
```

### `orderbookUpdate`

Emitted for CLOB markets when the book changes (new bids/asks, removals, or fills). `orderbook` carries the full updated book — each side is a sorted array of price levels.

```json theme={null}
{
  "marketSlug": "btc-100k-weekly",
  "orderbook": {
    "bids": [
      { "price": 0.53, "size": 100 },
      { "price": 0.52, "size": 250 }
    ],
    "asks": [
      { "price": 0.55, "size": 80 },
      { "price": 0.56, "size": 300 }
    ]
  },
  "timestamp": "2024-01-01T00:00:00.000Z"
}
```

| Field            | Type                                | Description                     |
| ---------------- | ----------------------------------- | ------------------------------- |
| `marketSlug`     | `string`                            | CLOB market slug                |
| `orderbook.bids` | `{ price: number, size: number }[]` | Bid levels, highest price first |
| `orderbook.asks` | `{ price: number, size: number }[]` | Ask levels, lowest price first  |
| `timestamp`      | `string`                            | ISO-8601 event timestamp        |

<Note>
  `price` and `size` are JSON numbers; coerce defensively to preserve decimal precision. For a one-shot snapshot, use [`GET /markets/{slug}/orderbook`](/api-reference/trading/orderbook) — the same shape.
</Note>

### `positions`

Position updates have different shapes depending on market type.

**AMM markets:**

```json theme={null}
{
  "account": "0xabcd...",
  "marketAddress": "0x1234...",
  "positions": [
    {
      "tokenId": "123456",
      "balance": "1000000",
      "outcomeIndex": 0,
      "collateralOutOnSell": "950000"
    }
  ],
  "type": "AMM"
}
```

**CLOB markets:**

```json theme={null}
{
  "account": "0xabcd...",
  "marketSlug": "btc-100k-weekly",
  "positions": [
    {
      "tokenId": "19633204485790...",
      "ctfBalance": "10000000",
      "averageFillPrice": "0.65",
      "costBasis": "6500000",
      "marketValue": "7000000",
      "marketId": 7348
    }
  ],
  "tokenIds": ["19633204485790..."],
  "type": "CLOB"
}
```

### `marketCreated`

Emitted when a new market is funded and visible. Hidden markets are excluded.

```json theme={null}
{
  "slug": "btc-above-110k-apr-2026",
  "title": "$BTC above $110,000 on Apr 5, 2026?",
  "type": "CLOB",
  "groupSlug": "btc-price-markets",
  "categoryIds": [1, 5],
  "createdAt": "2026-04-02T12:00:00.000Z"
}
```

| Field         | Type              | Description                                |
| ------------- | ----------------- | ------------------------------------------ |
| `slug`        | `string`          | Market slug identifier                     |
| `title`       | `string`          | Market title                               |
| `type`        | `'AMM' \| 'CLOB'` | Market type                                |
| `groupSlug`   | `string?`         | Parent group slug (for NegRisk submarkets) |
| `categoryIds` | `number[]?`       | Category IDs the market belongs to         |
| `createdAt`   | `string`          | ISO-8601 creation timestamp                |

### `marketResolved`

Emitted when a market resolves. Sent to both `market_lifecycle` subscribers and existing `market:{slug}` room subscribers.

```json theme={null}
{
  "slug": "btc-above-110k-apr-2026",
  "type": "CLOB",
  "winningOutcome": "YES",
  "winningIndex": 0,
  "resolutionDate": "2026-04-05T14:00:00.000Z"
}
```

| Field            | Type              | Description                                    |
| ---------------- | ----------------- | ---------------------------------------------- |
| `slug`           | `string`          | Market slug identifier                         |
| `type`           | `'AMM' \| 'CLOB'` | Market type                                    |
| `winningOutcome` | `'YES' \| 'NO'`   | The winning outcome                            |
| `winningIndex`   | `0 \| 1`          | Index of the winning outcome (0 = YES, 1 = NO) |
| `resolutionDate` | `string`          | ISO-8601 resolution timestamp                  |

### `orderEvent`

Emitted for both OME state changes and on-chain settlement results. Distinguish the two shapes by the `source` field.

#### OME event (`source: "OME"`)

The `OME` source carries two shapes: ongoing **lifecycle** state changes (`PLACEMENT` / `UPDATE` / `CANCELLATION`) and a one-shot **terminal** result for immediate-or-cancel orders (`EXECUTION`). Tell them apart by `type`.

##### Lifecycle (`type: "PLACEMENT" | "UPDATE" | "CANCELLATION"`)

Emitted for every resting-order state change recorded by the matching engine. `price` and `remainingSize` are sent unquoted as JSON numbers — coerce defensively to preserve decimal precision.

```json theme={null}
{
  "source": "OME",
  "type": "PLACEMENT",
  "eventId": 1234567,
  "orderId": "550e8400-e29b-41d4-a716-446655440000",
  "clientOrderId": "client-order-001",
  "userId": 42,
  "marketId": "17",
  "token": "87893014956437093847...",
  "side": "BUY",
  "price": 0.53,
  "remainingSize": 100,
  "timestamp": "2026-04-20T10:15:30.000Z"
}
```

| Field           | Type                                        | Description                                                                                                                                                   |
| --------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`        | `'OME'`                                     | Discriminator for the OME shape                                                                                                                               |
| `type`          | `'PLACEMENT' \| 'UPDATE' \| 'CANCELLATION'` | OME state transition                                                                                                                                          |
| `eventId`       | `number`                                    | Monotonic OME event id                                                                                                                                        |
| `orderId`       | `string`                                    | UUID of the order                                                                                                                                             |
| `clientOrderId` | `string?`                                   | Client-supplied id from `POST /orders`, when the order was placed with one. Field is omitted (not `null`) when the originating order had no client id.        |
| `userId`        | `number`                                    | Internal user id of the order owner                                                                                                                           |
| `marketId`      | `string`                                    | Numeric market id (CLOB)                                                                                                                                      |
| `token`         | `string`                                    | CTF token id (decimal string)                                                                                                                                 |
| `side`          | `'BUY' \| 'SELL'`                           | Order side                                                                                                                                                    |
| `price`         | `number`                                    | Limit price (unquoted JSON number)                                                                                                                            |
| `remainingSize` | `number`                                    | Size remaining on the book (unquoted JSON number)                                                                                                             |
| `reason`        | `string?`                                   | Engine cancellation reason. `STP_MAKER_CANCELLED` on a `CANCELLATION` event when self-trade prevention cancelled your resting maker order. Omitted otherwise. |
| `timestamp`     | `string`                                    | ISO-8601 event timestamp                                                                                                                                      |

`type` transitions:

* `PLACEMENT` — order accepted by the OME.
* `UPDATE` — remaining size changed (partial fill or amend).
* `CANCELLATION` — removed from the book. Carries `reason: "STP_MAKER_CANCELLED"` when self-trade prevention cancelled your resting maker order against your own incoming order.

##### FAK/FOK terminal (`type: "EXECUTION"`)

Emitted once when an immediate-or-cancel order reaches a recorded terminal state — a FAK (fill-and-kill), which always terminates, or a FOK (fill-or-kill) **that filled**. Delivered only to the order owner. Unlike the lifecycle frames, `eventId` is a string (`terminal:<orderId>`) and the frame carries a `status` label.

```json theme={null}
{
  "source": "OME",
  "type": "EXECUTION",
  "status": "FILLED",
  "eventId": "terminal:550e8400-e29b-41d4-a716-446655440000",
  "orderId": "550e8400-e29b-41d4-a716-446655440000",
  "userId": 42,
  "marketId": "17",
  "token": "87893014956437093847...",
  "side": "BUY",
  "price": 0.53,
  "remainingSize": 0,
  "timestamp": "2026-04-20T10:15:40.000Z"
}
```

| Field           | Type                                         | Description                                                                   |
| --------------- | -------------------------------------------- | ----------------------------------------------------------------------------- |
| `source`        | `'OME'`                                      | Discriminator for the OME shape                                               |
| `type`          | `'EXECUTION'`                                | Terminal result of a FAK/FOK order                                            |
| `status`        | `'FILLED' \| 'PARTIALLY_FILLED' \| 'KILLED'` | Final outcome (see below)                                                     |
| `eventId`       | `string`                                     | `terminal:<orderId>` — string form, unlike the numeric lifecycle `eventId`    |
| `orderId`       | `string`                                     | UUID of the order                                                             |
| `userId`        | `number`                                     | Internal user id of the order owner                                           |
| `marketId`      | `string`                                     | Numeric market id (CLOB)                                                      |
| `token`         | `string`                                     | CTF token id (decimal string) — the raw token, not `YES` / `NO`               |
| `side`          | `'BUY' \| 'SELL'`                            | Order side                                                                    |
| `price`         | `number`                                     | Order price                                                                   |
| `remainingSize` | `number`                                     | Unfilled size at termination (`0` on `FILLED`, the original size on `KILLED`) |
| `timestamp`     | `string`                                     | ISO-8601 event timestamp                                                      |

`status` outcomes:

* `FILLED` — the order matched in full (a FAK that matched completely, or a FOK).
* `PARTIALLY_FILLED` — a FAK matched part of its size; the unfilled remainder was cancelled. `remainingSize` is that cancelled remainder.
* `KILLED` — a FAK matched nothing and was cancelled in full. `remainingSize` equals the original size. A taker rejected by self-trade prevention (`stpPolicy: "cancel_taker"` or `"cancel_both"`) also surfaces here as `status: "KILLED"`; this frame carries no STP reason — the `STP_TAKER_REJECTED` reason is returned only on the synchronous `POST /orders` response.

<Note>
  **`price` and `remainingSize` are JSON numbers** (as on the lifecycle frames) — coerce defensively to preserve decimal precision.
</Note>

<Note>
  **No fee or `clientOrderId` on the terminal frame.** It reports only the lifecycle outcome. For the realized fee, read the `POST /orders` response or the `MINED` settlement frame. `token` is the raw CTF token id, not the `YES` / `NO` outcome.
</Note>

<Note>
  **A FOK is all-or-nothing.** A fill-or-kill order either fills completely (`status: "FILLED"`) or is rejected with HTTP 400 and produces no event — it never emits `PARTIALLY_FILLED` or `KILLED`. Only a FAK reports a partial (`PARTIALLY_FILLED`) or zero (`KILLED`) fill.
</Note>

#### Settlement event (`source: "SETTLEMENT"`)

The `SETTLEMENT` source carries the settlement lifecycle of a CLOB trade. Each participant receives its own events — one for the taker order and one for each matched maker order, keyed by `userId`. Two `type`s arrive in sequence:

* **`MATCHED`** — *provisional*. Emitted the instant the matching engine fills your order, **before** the on-chain settlement transaction. This is the early "your order will be matched for N" signal. Fee fields are estimates (`isEstimate: true`), there is no `txHash` yet, and the fill can still be rolled back by a later `FAILED`.
* **`MINED` / `FAILED`** — *terminal*. Emitted after the settlement transaction resolves on-chain. `MINED` carries `txHash` and the taker's realized fee; `FAILED` means the trade did not execute and no funds moved.

A `MATCHED` and its terminal `MINED` / `FAILED` share the same `tradeEventId` and `orderId` but use different `eventId` namespaces (`matched:…` vs `settlement:…`), so they never dedup-collide. Correlate provisional → terminal by `tradeEventId` + `orderId` (`MATCHED` does not carry `clientOrderId`).

`takerAccount` and `makerMatches[].account` are on-chain addresses — for smart-wallet users this is the smart-wallet proxy, for EOA users it is the EOA.

##### Provisional match (`type: "MATCHED"`)

Emitted pre-chain, the moment the engine fills the order. Per-profile: the taker and each maker receive their own frame carrying their **own** side, token, size, price, and fee estimate (in a cross-outcome match the taker and maker hold opposite tokens). The taker frame aggregates the whole fill; each maker frame describes only that maker's leg.

```json theme={null}
{
  "source": "SETTLEMENT",
  "type": "MATCHED",
  "eventId": "matched:77985c10…:d45b884d…",
  "tradeEventId": "77985c10…",
  "orderId": "d45b884d…",
  "takerOrderId": "d45b884d…",
  "marketSlug": "will-abc-happen-by-2026",
  "tokenId": "27102822276156300166...",
  "token": "NO",
  "side": "BUY",
  "price": "0.53",
  "amountContracts": "25",
  "amountCollateral": "13.25",
  "configuredFeeRateBps": 30,
  "effectiveFeeBps": 27,
  "feeAmountContracts": "0.0675",
  "isEstimate": true,
  "timestamp": "2026-04-20T10:15:40.000Z"
}
```

| Field                  | Type              | Description                                                                                                                                       |
| ---------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`               | `'SETTLEMENT'`    | Discriminator for the settlement shape                                                                                                            |
| `type`                 | `'MATCHED'`       | Provisional, pre-chain match                                                                                                                      |
| `eventId`              | `string`          | `matched:<tradeEventId>:<orderId>` — distinct namespace from the terminal `settlement:…` id                                                       |
| `tradeEventId`         | `string`          | Trade id shared with the terminal `MINED` / `FAILED` for this fill                                                                                |
| `orderId`              | `string`          | UUID of the recipient's own order in this fill                                                                                                    |
| `takerOrderId`         | `string`          | UUID of the taker order in the trade                                                                                                              |
| `marketSlug`           | `string`          | CLOB market slug                                                                                                                                  |
| `tokenId`              | `string`          | CTF token id of the recipient's own side (decimal string)                                                                                         |
| `token`                | `'YES' \| 'NO'`   | Outcome the recipient filled — its own side, not necessarily the taker's                                                                          |
| `side`                 | `'BUY' \| 'SELL'` | Recipient order side                                                                                                                              |
| `price`                | `string`          | Recipient's fill price (decimal string) — the weighted-average across the fill on the taker frame, the maker's own resting price on a maker frame |
| `amountContracts`      | `string`          | Filled contract amount for the recipient order                                                                                                    |
| `amountCollateral`     | `string`          | Filled collateral amount for the recipient order                                                                                                  |
| `configuredFeeRateBps` | `number`          | Fee rate configured for the order                                                                                                                 |
| `effectiveFeeBps`      | `number`          | Effective fee rate used for the estimate                                                                                                          |
| `feeAmountContracts`   | `string?`         | Fee **estimate** in contracts — present on BUY fills                                                                                              |
| `feeAmountCollateral`  | `string?`         | Fee **estimate** in collateral — present on SELL fills                                                                                            |
| `isEstimate`           | `true`            | Always `true` on `MATCHED`: fee fields are estimates, not realized on-chain charges                                                               |
| `timestamp`            | `string`          | ISO-8601 event timestamp                                                                                                                          |

<Warning>
  **`MATCHED` is provisional — do not settle books on it.** Use it as an early acknowledgement / UI signal only. Its fee fields are estimates (`isEstimate: true`), not realized charges, and the fill can still end in `FAILED`. Reconcile on the terminal `MINED` frame, which carries `txHash` and the taker's realized fee.
</Warning>

<Note>
  **Fee currency follows side.** A BUY fill reports the fee estimate in `feeAmountContracts` (`feeAmountCollateral` absent); a SELL fill reports it in `feeAmountCollateral`. The same convention applies on `MINED`.
</Note>

<Note>
  **Makers are not charged a fee — only the taker pays.** On a maker's frame the fee estimate fields (`configuredFeeRateBps`, `effectiveFeeBps`, `feeAmountContracts` / `feeAmountCollateral`) mirror the maker order's configured rate and can be non-zero, but a maker is not charged a fee on a matched CLOB trade — the realized maker fee is `0`. Treat the taker-side estimate as a real pre-settlement charge to reconcile on `MINED`; treat the maker-side estimate as informational only.
</Note>

##### Terminal settlement (`type: "MINED" | "FAILED"`)

Emitted when a CLOB trade settles on-chain. Each participant receives a settlement event for their own order: one for the taker order and one for each matched maker order.

```json theme={null}
{
  "source": "SETTLEMENT",
  "type": "MINED",
  "eventId": "settlement:1b3a…:550e8400-e29b-41d4-a716-446655440000",
  "tradeEventId": "1b3a…",
  "orderId": "550e8400-e29b-41d4-a716-446655440000",
  "clientOrderId": "client-order-001",
  "takerOrderId": "e4c3…",
  "takerAccount": "0xAbC…123",
  "makerMatches": [
    {
      "account": "0xDeF…456",
      "orderId": "cb12…",
      "matchedSize": "25",
      "price": "0.53"
    }
  ],
  "marketSlug": "will-abc-happen-by-2026",
  "tokenId": "87893014956437093847...",
  "side": "BUY",
  "price": "0.53",
  "amountContracts": "25",
  "amountCollateral": "13.25",
  "configuredFeeRateBps": 0,
  "effectiveFeeBps": 0,
  "feeAmountContracts": "0",
  "txHash": "0xabc…",
  "timestamp": "2026-04-20T10:15:40.000Z"
}
```

| Field                  | Type                  | Description                                                                                                                                                                                                                                                               |
| ---------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`               | `'SETTLEMENT'`        | Discriminator for the settlement shape                                                                                                                                                                                                                                    |
| `type`                 | `'MINED' \| 'FAILED'` | Settlement outcome                                                                                                                                                                                                                                                        |
| `eventId`              | `string`              | Stable id in the form `settlement:<tradeEventId>:<orderId>`                                                                                                                                                                                                               |
| `tradeEventId`         | `string`              | Settlement trade id shared by all participant events for the same match                                                                                                                                                                                                   |
| `orderId`              | `string?`             | UUID of the recipient's own order for this event                                                                                                                                                                                                                          |
| `clientOrderId`        | `string?`             | Client-supplied id of the recipient's own order (`orderId`), when the order was placed with one. Field is omitted (not `null`) when the originating order had no client id. Counterparty (`takerOrderId`, `makerMatches[].orderId`) ids are never resolved to client ids. |
| `takerOrderId`         | `string?`             | UUID of the taker order in the trade                                                                                                                                                                                                                                      |
| `takerAccount`         | `string?`             | On-chain address of the taker (smart-wallet proxy or EOA)                                                                                                                                                                                                                 |
| `makerMatches`         | `array?`              | One entry per matched maker (account, orderId, matchedSize, price). A taker event can include multiple maker matches; each maker also receives a separate event for its own order.                                                                                        |
| `marketSlug`           | `string?`             | CLOB market slug                                                                                                                                                                                                                                                          |
| `tokenId`              | `string?`             | CTF token id for the recipient side                                                                                                                                                                                                                                       |
| `side`                 | `'BUY' \| 'SELL'?`    | Recipient order side                                                                                                                                                                                                                                                      |
| `price`                | `string?`             | Execution price as a decimal string                                                                                                                                                                                                                                       |
| `amountContracts`      | `string?`             | Filled contract amount for the recipient order                                                                                                                                                                                                                            |
| `amountCollateral`     | `string?`             | Collateral amount for the recipient order                                                                                                                                                                                                                                 |
| `configuredFeeRateBps` | `number?`             | Fee rate configured for the order                                                                                                                                                                                                                                         |
| `effectiveFeeBps`      | `number?`             | Effective fee rate applied to this trade                                                                                                                                                                                                                                  |
| `feeAmountContracts`   | `string?`             | Fee amount in contracts                                                                                                                                                                                                                                                   |
| `txHash`               | `string?`             | Settlement transaction hash, when known                                                                                                                                                                                                                                   |
| `timestamp`            | `string`              | ISO-8601 event timestamp                                                                                                                                                                                                                                                  |

<Note>
  **Reconciling WS events with `POST /orders`.** Submit an order with a `clientOrderId` and every `orderEvent` for that order — `PLACEMENT`, `UPDATE`, `CANCELLATION`, and the `MINED` / `FAILED` settlement frame — echoes the same `clientOrderId`. Match WS events to the originating request by `clientOrderId` rather than waiting for the `POST /orders` HTTP response, which only returns once settlement is `MINED`. If only one side supplied a `clientOrderId`, only that side's event includes it.
</Note>

<Note>
  **Maker fee on `MINED` is informational too.** Like the `MATCHED` estimate, a maker's `MINED` fee fields are computed from the maker order's configured rate, not a realized charge — makers are not charged, so the realized maker fee is `0`. Only the taker's `MINED` fee is a realized charge.
</Note>

* `type: "MINED"` — on-chain settlement confirmed.
* `type: "FAILED"` — settlement failed on-chain; the taker order did not execute and funds were not moved.
