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

# Channels and events

> Catalog of Pusher channels and realtime events for markets, order books, and account updates.

This is the complete catalog of realtime channels and the events published on each. Terminology: **event** = a question; **market** = an outcome.

For client setup, see [Overview](/api-reference/websocket/overview). Private channels require [Authorization](/api-reference/websocket/authorization).

## Channels

| Channel                  | Type    | Auth                                            | Purpose                                                |
| ------------------------ | ------- | ----------------------------------------------- | ------------------------------------------------------ |
| `event`                  | public  | none                                            | Global feed of event and market activity               |
| `event-{event_id}`       | public  | none                                            | Per-event BBO, order-book, and status updates          |
| `private-user-{user_id}` | private | `POST https://api.futuur.com/v2.0/pusher/auth/` | Per-user balance, deposit, order, and position updates |
| `test-channel`           | public  | none                                            | Connectivity testing (`test-event` only)               |

## Events at a glance

| Event                  | Channel                     | Emitted when                                             |
| ---------------------- | --------------------------- | -------------------------------------------------------- |
| `best-prices-change`   | `event`, `event-{event_id}` | A wagerable market's best bid/ask changes                |
| `price-change`         | `event`                     | An event's price or volume state changes                 |
| `new-market`           | `event`                     | A new market is added to an event                        |
| `live-data-update`     | `event`                     | Live data, status, or resolution changes                 |
| `market-status-change` | `event`, `event-{event_id}` | Tradability fields change (status, bet window, disabled) |
| `market-comment`       | `event`                     | A user posts a comment on an event                       |
| `order-book-update`    | `event-{event_id}`          | Absolute top-N bid/ask levels for a changed market       |
| `balance-changed`      | `private-user-{user_id}`    | The user's balance changes                               |
| `deposit-success`      | `private-user-{user_id}`    | A deposit completes                                      |
| `order-update`         | `private-user-{user_id}`    | An order is created or its status changes                |
| `position-update`      | `private-user-{user_id}`    | The user's wager shares change                           |

<Note>
  Full-depth `order-book-snapshot` pushes are **not** emitted (Pusher message size limits). `order-book-update` carries top-N levels per market. For depth beyond top-N, call the REST [order book](/api-reference/markets/order-book) API.
</Note>

## Event channel (public)

Global public feed on channel `event`. Subscribe with `pusher.subscribe("event")`; no authentication required.

### best-prices-change

Emitted when the best bid/ask of a **wagerable** market changes. Non-wagerable markets are skipped to stay within Pusher limits.

Also published on `event-{event_id}` with the same payload, so quoting bots can avoid the global `event` fanout:

```javascript theme={null}
pusher.subscribe("event-" + eventId).bind("best-prices-change", ...);
```

<ResponseField name="market_id" type="integer">Market (outcome) ID.</ResponseField>
<ResponseField name="event_id" type="integer">Event ID.</ResponseField>
<ResponseField name="currency_mode" type="string">`play_money` or `real_money`.</ResponseField>
<ResponseField name="best_ask" type="number | null">Best ask price.</ResponseField>
<ResponseField name="best_bid" type="number | null">Best bid price.</ResponseField>
<ResponseField name="spread" type="number | null">`best_ask - best_bid`.</ResponseField>

### price-change

Emitted when an event's price or volume state changes. `currency_mode` controls the ordering of `markets` in the payload.

| Field                     | Type    | Description                      |
| ------------------------- | ------- | -------------------------------- |
| `id`                      | number  | Event ID                         |
| `title`                   | string  | Event title                      |
| `status`                  | string  | Event status code                |
| `currency_mode`           | string  | `play_money` or `real_money`     |
| `is_wagerable`            | boolean | Whether the event accepts wagers |
| `wagers_count_play_money` | number  | Play-money wager count           |
| `wagers_count_real_money` | number  | Real-money wager count           |
| `wagers_count_total`      | number  | Sum of play and real counts      |
| `volume_play_money`       | number  | null                             |
| `volume_real_money`       | number  | null                             |
| `markets`                 | array   | Visible markets (see below)      |

Each element of `markets`:

| Field         | Type   | Description                                                |
| ------------- | ------ | ---------------------------------------------------------- |
| `id`          | number | Market ID                                                  |
| `title`       | string | Market title                                               |
| `status`      | string | Market status                                              |
| `price`       | object | Long mid-price per currency: `{ "OOM": ..., "USDC": ... }` |
| `long_label`  | string | Long side label (e.g. `"Yes"`)                             |
| `short_label` | string | Short side label (e.g. `"No"`)                             |
| `resolution`  | string | `long`, `short`, or null                                   |

### new-market

Emitted when a new market is added to an event.

| Field                        | Type   | Description                       |
| ---------------------------- | ------ | --------------------------------- |
| `id`                         | number | Market ID                         |
| `title`                      | string | Market title                      |
| `title_verbose`              | string | Verbose title                     |
| `event`                      | object | `{ id, title, status, category }` |
| `status`                     | string | Market status                     |
| `suggested_price_play_money` | number | null                              |
| `suggested_price_real_money` | number | null                              |
| `bet_start_date`             | string | null                              |
| `bet_end_date`               | string | null                              |

### live-data-update

Emitted when an event's live data changes.

| Field              | Type    | Description                         |
| ------------------ | ------- | ----------------------------------- |
| `id`               | number  | Event ID                            |
| `status`           | string  | Event status                        |
| `resolution`       | string  | null                                |
| `resolve_date`     | string  | null                                |
| `event_start_date` | string  | null                                |
| `event_end_date`   | string  | null                                |
| `event_extra_data` | object  | null                                |
| `is_live`          | boolean | Whether the event is currently live |

### market-status-change

Emitted on `event` and `event-{event_id}` when tradability fields change (`status`, bet window, or market `disabled`). Use this to start or stop quoting — do not rely on BBO alone.

### market-comment

Emitted when a user posts a comment. Sent with a \~5s delay so replicas can catch up before clients refetch.

| Field        | Type   | Description                                                          |
| ------------ | ------ | -------------------------------------------------------------------- |
| `id`         | number | Comment ID                                                           |
| `content`    | string | Comment text                                                         |
| `created_on` | string | ISO 8601 timestamp                                                   |
| `user`       | object | `{ id, username, picture, win_rate, wagers_count, net_earnings }`    |
| `question`   | object | `{ id, title, slug, status, resolve_date, bet_end_date, is_binary }` |

## Per-event channel (public)

Channel name pattern: `event-{event_id}` (e.g. `event-1234`). Subscribe with `pusher.subscribe("event-" + eventId)`; no authentication required.

Events on this channel: `order-book-update`, `best-prices-change`, and `market-status-change`.

### order-book-update

Absolute top-N (default 5) bid/ask levels for the affected market — one message per market. The legacy refetch ping (`{ endpoint, question, currency }`) and the separate `order-book-delta` event are removed; use this payload only.

For depth beyond top-N, call [GET /markets/{id}/book/](/api-reference/markets/order-book).

| Field           | Type   | Description                                         |
| --------------- | ------ | --------------------------------------------------- |
| `market_id`     | number | Market (outcome) ID                                 |
| `event_id`      | number | Event ID                                            |
| `currency`      | string | Currency code (e.g. `USDC`)                         |
| `currency_mode` | string | `play_money` or `real_money`                        |
| `top_n`         | number | Number of levels (default `5`)                      |
| `ask`           | array  | Ask levels: `{ price, total_shares, total_amount }` |
| `bid`           | array  | Bid levels: `{ price, total_shares, total_amount }` |
| `timestamp`     | string | Emission timestamp                                  |

```html theme={null}
<script>
    var pusher = new Pusher("9011f7eac38e825792d5", { cluster: "us2" });
    var channel = pusher.subscribe("event-" + eventId);
    channel.bind("order-book-update", function (data) {
        applyTopOfBook(data.market_id, data.bid, data.ask);
    });
</script>
```

## Private user channel

Channel name pattern: `private-user-{user_id}`. Requires authorization via `POST https://api.futuur.com/v2.0/pusher/auth/`. Subscribe with `pusher.subscribe("private-user-" + userId)`.

### balance-changed

Emitted when the user's balance changes. Carries no amount — refetch [GET /me/balances/](/api-reference/me/balances).

| Field       | Type   | Description                     |
| ----------- | ------ | ------------------------------- |
| `timestamp` | number | Unix epoch seconds when emitted |

### deposit-success

Emitted when a deposit completes.

| Field      | Type   | Description      |
| ---------- | ------ | ---------------- |
| `amount`   | number | Deposited amount |
| `currency` | string | Currency code    |

### order-update

Real-time order lifecycle updates: create / open acks (`pending`, `open`, including PROCESSING → OPEN) plus fill, partial fill, cancel, and expire. Useful for syncing resting orders without relying only on the REST response.

| Field                 | Type    | Description                                                                            |
| --------------------- | ------- | -------------------------------------------------------------------------------------- |
| `order_id`            | number  | Order ID                                                                               |
| `market_id`           | number  | Market ID                                                                              |
| `event_id`            | number  | Event ID                                                                               |
| `status`              | string  | New status (e.g. `pending`, `open`, `filled`, `partial_filled`, `canceled`, `expired`) |
| `previous_status`     | string  | null                                                                                   |
| `side`                | string  | `bid`                                                                                  |
| `position`            | string  | `l` (long)                                                                             |
| `price`               | number  | null                                                                                   |
| `shares_requested`    | number  | Requested quantity                                                                     |
| `shares_filled`       | number  | Total filled so far                                                                    |
| `shares_filled_delta` | number  | Optional — filled in this update                                                       |
| `avg_fill_price`      | number  | null                                                                                   |
| `currency`            | string  | Currency code                                                                          |
| `timestamp`           | string  | ISO 8601 with milliseconds                                                             |
| `cancel_reason`       | string  | Optional — e.g. `user_requested`                                                       |
| `expired_at`          | string  | Optional — ISO 8601                                                                    |
| `is_system_initiated` | boolean | Optional                                                                               |

```html theme={null}
<script>
    var pusher = new Pusher("9011f7eac38e825792d5", { cluster: "us2" });
    var privateChannel = pusher.subscribe("private-user-" + userId);
    privateChannel.bind("order-update", function (data) {
        if (data.status === "pending" || data.status === "open") {
            // create / open ack — sync resting order
        }
        if (data.status === "filled" || data.status === "partial_filled") {
            // handle fill
        }
        if (data.status === "canceled" || data.status === "expired") {
            // remove from local open-orders model
        }
    });
</script>
```

### position-update

Emitted when a user's wager shares change. Use for inventory sync.

| Field              | Type   | Description               |
| ------------------ | ------ | ------------------------- |
| `market_id`        | number | Market (outcome) ID       |
| `event_id`         | number | Event ID                  |
| `position`         | string | Position side             |
| `currency`         | string | Currency code             |
| `shares`           | number | Current share quantity    |
| `purchases_amount` | number | Amount spent on purchases |
| `avg_price`        | number | Average purchase price    |

## Related

* [Overview](/api-reference/websocket/overview) — Pusher client setup
* [Authorization](/api-reference/websocket/authorization) — private channel HMAC auth
* [Order book](/api-reference/markets/order-book) — REST endpoint for full depth beyond top-N
* [Reading the order book](/guides/reading-the-order-book) — interpret bid/ask depth
