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

# Event catalog

> Every lifecycle moment mapped across SSE, WebSocket, webhooks, and REST — plus the field and identity names that mean the same thing on different channels.

A single trade crosses four channels and changes names twice on the way. This page maps a trade's full lifecycle across every channel side by side, and lists the field aliases and noun changes you'd otherwise piece together from [How parlays work](/guides/lifecycle), [Real time & data channels](/guides/realtime-and-data), [WebSocket](/guides/websocket), [webhooks](/guides/webhooks), and the Quote Service reference pages.

## Naming conventions across channels

Each channel has its own event naming grammar. Knowing the pattern up front makes every table below scannable at a glance:

* **SSE** events are bare or underscore separated names — `best_quote`, `quote_request`, `quote_request_expired`.
* **WebSocket** events are `resource:verb`, colon namespaced — `quote:accepted`, `position:settled`.
* **Webhook** events are `resource.verb`, dot namespaced — `position.settled`, `parlay.status_changed`.

There's no deeper logic to the separator choice beyond which channel it's on. The MM SSE stream isn't even internally consistent: `quote_request` and `quote_request_expired` use underscores, while `quote_request:updated` uses a colon (see the [summary table](/api-reference/quote-service-mm/stream#sse-event-types) on that page).

## One trade, across every channel

Read this left to right for any given moment, or top to bottom to follow one trade start to finish. "—" means the moment has no representation on that channel.

<Note>
  `quote:*` WebSocket events (`quote:accepted`, `quote:confirmed`, `quote:executed`, `quote:expired`, `quote:rejected`, `quote:withdrawn`) deliver only to the **awarded market maker**, on their private `mm:quotes:{mm_id}` channel. `position:*` events deliver on `rfq:{rfq_id}`, the channel a user (or anyone tracking a specific trade) subscribes to. The two families are not interchangeable views of the same moment — several rows below have a WebSocket event for the MM and nothing for the user, or vice versa.
</Note>

| Lifecycle moment                                     | SSE — user stream ([`/v1/quote-requests/{id}/stream`](/api-reference/quote-service/stream))                                                                          | SSE — MM stream ([`/v1/mm/quote-requests/stream`](/api-reference/quote-service-mm/stream))                                                                                | WebSocket                                                                                                                                                                                                | Webhook                                                                                                                                                               | REST status                                                                                          |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Quote request created                                | — (no dedicated "created" event; the stream opens after creation and the first frame is `best_quote`, often `null`)                                                  | `quote_request`                                                                                                                                                           | not delivered on this channel — WebSocket starts at quote acceptance                                                                                                                                     | not delivered on this channel — webhooks are posttrade only                                                                                                           | quote request `status: "active"` — [`GET /v1/quote-requests/{id}`](/api-reference/quote-service/get) |
| Quote updated (price changes, or legs/amount edited) | `best_quote`                                                                                                                                                         | `quote_request:updated` — only fires when the **request itself** changes (`PATCH`); no MM stream event exists for an individual quote submission, yours or a competitor's | not delivered on this channel                                                                                                                                                                            | not delivered on this channel                                                                                                                                         | quote request `version`/`book_seq` increments; `status` stays `"active"`                             |
| Quote accepted / committed                           | `status` (`status: "committed"`) followed immediately by the terminal `committed` event, then the stream closes                                                      | `quote_request_expired` (`reason: "committed"`; `won: true` for the winning MM, `false` for every other MM)                                                               | `quote:accepted` + `mm_quote:accepted` — **MM only**. Nothing pushes to the user on WebSocket; they already have the outcome from the synchronous [commit](/api-reference/quote-service/commit) response | `parlay.status_changed` (`status: "accepted"`, `accepted_quote_id` set)                                                                                               | RFQ `status: "accepted"` — [`GET /v1/rfqs/{id}`](/api-reference/parlays/get)                         |
| Confirmed by maker                                   | not delivered on this channel — the stream already closed at commit                                                                                                  | not delivered on this channel                                                                                                                                             | `quote:confirmed` — **MM only**. No user facing WebSocket event marks this step specifically                                                                                                             | `parlay.status_changed` (`status: "confirmed"`)                                                                                                                       | RFQ `status: "confirmed"`                                                                            |
| Executed on chain                                    | not delivered on this channel                                                                                                                                        | not delivered on this channel                                                                                                                                             | `quote:executed` (MM channel) and `position:created` (`rfq:{rfq_id}` channel — collateral locked, `position_pda` set)                                                                                    | `parlay.status_changed` (`status: "executed"`)                                                                                                                        | RFQ `status: "executed"`                                                                             |
| Settled                                              | not delivered on this channel                                                                                                                                        | not delivered on this channel                                                                                                                                             | `position:settled` (`outcome`, `tx_signature`)                                                                                                                                                           | `position.settled` — the terminal outcome event; `parlay.status_changed`'s `status` values stop at `executed`/`cancelled` and never include `"settled"`               | RFQ `status: "settled"`                                                                              |
| Bought back early (cashout)                          | not on this stream — see the separate [cashout-request stream](/api-reference/quote-service/cashout-stream), whose own terminal `status` event reports `"committed"` | `cashout_request` announces only the **opening** of the buyback request to the backing MM; there's no separate SSE event for its completion                               | **not delivered on this channel** — see [the gap below](#the-websocket-buyback-gap)                                                                                                                      | `position.bought_back` (`amount`, `mm_pays_user`, `tx_signature`)                                                                                                     | RFQ `status: "bought_back"`, `cashout` object populated                                              |
| Cancelled                                            | `cancelled` — quote request abandoned precommit via [Cancel](/api-reference/quote-service/cancel)                                                                    | `quote_request_expired` (`reason: "cancelled"`)                                                                                                                           | `position:cancelled` — only for a **postcommit** cancellation (e.g. the maker missed the confirmation deadline); a precommit quote request cancellation never reaches a position, so nothing fires here  | not delivered precommit; postcommit fires **both** `parlay.status_changed` (`status: "cancelled"`) and `position.cancelled` together (dedupe on `X-Totalis-Event-Id`) | quote request `status: "cancelled"` precommit, or RFQ `status: "cancelled"` postcommit               |
| Expired                                              | `expired` — quote request's TTL lapsed with no commit                                                                                                                | `quote_request_expired` (`reason: "expired"`)                                                                                                                             | `quote:expired` — a specific MM's **accepted quote** lapsed before confirmation; there's no distinct WebSocket event for a whole RFQ expiring                                                            | **not delivered on this channel** — no webhook event exists for expiry, before or after commit                                                                        | quote request `status: "expired"` precommit, or RFQ `status: "expired"` postcommit                   |

## The WebSocket buyback gap

<Warning>
  **`position.bought_back` is a webhook only event.** There is no `position:bought_back` (or equivalent) WebSocket event today. A bot or live UI holding only a WebSocket connection — the setup [Real time & data channels](/guides/realtime-and-data) and [WebSocket](/guides/websocket) recommend for latency sensitive trading — gets **no real time signal** that a position was bought out early.

  If your integration needs that event live, you must also configure a [webhook endpoint](/guides/webhooks) to receive `position.bought_back`, or poll [`GET /v1/rfqs/{id}`](/api-reference/parlays/get) and watch for `status: "bought_back"`. A WebSocket only integration will miss this moment until it reconciles.
</Warning>

## Same value, different name

The same economic figures go by different names at the quote stage versus the settlement stage:

| Quote stage name                                                                                                                                            | Settlement stage name                                                                                                                                                                                                                               | Same value because                                                                                                      |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `user_cost` (Quote object — [quote-request stream](/api-reference/quote-service/stream), [`GET /v1/quote-requests/{id}`](/api-reference/quote-service/get)) | `user_stake` (Settlement object on [`GET /v1/rfqs/{id}`](/api-reference/parlays/get); also the name used from the start in [MM-stream](/api-reference/quote-service-mm/stream) and [cashout](/api-reference/quote-service/cashout-create) payloads) | Both are the user's net stake (`bet_amount` minus the taker fee). The API renames it once the trade moves past pricing. |
| `mm_cost` (Quote object, quote stage)                                                                                                                       | `mm_risk` (Settlement object; also used in MM stream `cashout_request` payloads)                                                                                                                                                                    | Both are the market maker's amount at risk (`total_payout`/`payout` minus the user's stake).                            |
| `total_payout` (Quote object, quote stage)                                                                                                                  | `payout` (Settlement object, settlement stage)                                                                                                                                                                                                      | Both are the full amount paid to the winner on a win (`user stake + mm risk`).                                          |

### Market maker identity across channels

`mm_id`, `market_maker_id`, and `target_mm_id` all identify the same thing — the market maker quoting or backing a trade. Which spelling you see depends on the channel:

| Field             | Where it appears                                                                                                                                                                                                                                                                                                                              |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mm_id`           | The MM SSE stream's [`connected`](/api-reference/quote-service-mm/stream#connected) event; the `mm:quotes:{mm_id}` WebSocket channel name itself                                                                                                                                                                                              |
| `market_maker_id` | Quote objects — `best_quote.market_maker_id` on both the [quote-request stream](/api-reference/quote-service/stream) and [cashout stream](/api-reference/quote-service/cashout-stream), the [`Get quote request`](/api-reference/quote-service/get) response, and the [`mm_quote:accepted`](/guides/websocket#quote-events) WebSocket payload |
| `target_mm_id`    | The [cashout request object](/api-reference/quote-service/cashout-create) — the single MM a given cashout request is offered to                                                                                                                                                                                                               |

### The noun stack

The same trade is called something different at each stage of its life. [How parlays work](/guides/lifecycle) introduces this progression; here it's gathered in one place:

| Stage                      | Name              | Notes                                                                                                                                                                                                                                                                                                                                                                                                           |
| -------------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Precommit, ephemeral       | **quote request** | Lives only in the Quote Service. Has its own `id` and `status` (`active` → `committed`/`cancelled`/`expired`). Ceases to exist once it commits or dies — it never becomes a queryable historical record.                                                                                                                                                                                                        |
| Postcommit, the API object | **RFQ**           | Created at commit, with its own `rfq_id` and `status` progression (`open` → `quoted` → `accepted` → `confirmed` → `executed` → `settled`/`bought_back`, or `cancelled`/`expired`). This is what [`GET /v1/rfqs/{id}`](/api-reference/parlays/get) returns.                                                                                                                                                      |
| Product facing name        | **parlay**        | The same object as the RFQ — "parlay" is the name you'd use in a UI or in conversation. The docs use "parlay (RFQ)" interchangeably for this reason.                                                                                                                                                                                                                                                            |
| Once funded on chain       | **position**      | The RFQ's on chain footprint once `status >= confirmed`. Carries `position_id` (the 16 byte on chain id, used specifically to open a [cashout request](/api-reference/quote-service/cashout-create)) and `position_pda` (the on chain account address, surfaced on WebSocket `position:*` events). Look a position up by `rfq_id`/`position_id` via the API — the PDA is an on chain address, not a lookup key. |
