> ## 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.

# WebSocket

> Real-time trade confirmations and position updates via WebSocket.

The Totalis WebSocket pushes **post-trade events** in real time — quote acceptances and confirmations, and position settlements. Connect, authenticate, subscribe to the channels you need, and handle events as they arrive.

For **pre-trade** live pricing, use the SSE streams instead: the [maker stream](/api-reference/quote-service-mm/stream) for incoming quote requests, and the [quote-request stream](/api-reference/quote-service/stream) for the best current quote. The WebSocket covers everything from quote acceptance onward.

<Note>
  WebSocket events reach you only while you're connected — missed events are not redelivered. For durable, at-least-once delivery to a server (signed, retried, replayable), use [webhooks](/guides/webhooks); they carry most of the same lifecycle moments. An early cash-out that **closes** a position is on both channels (`position:bought_back` here, `position.bought_back` by webhook); the one exit outcome neither channel pushes to the buyer is a bid that **acquires** a position — see the [event catalog](/guides/event-catalog#the-transfer-notification-gap). See [Real time & data channels](/guides/realtime-and-data) for the full channel map.
</Note>

## Connecting

```
wss://api.totalis.trade/ws
```

## Authentication

Send an auth message with your API key immediately after connecting:

```json theme={null}
{ "type": "auth", "api_key": "<your-api-key>" }
```

Success:

```json theme={null}
{ "type": "auth:success", "user_id": "did:privy:abc123", "user_type": "user" }
```

Error:

```json theme={null}
{ "type": "auth:error", "message": "Invalid API key" }
```

## Subscribing to channels

After authenticating, subscribe to channels to receive events:

```json theme={null}
{ "type": "subscribe", "channel": "mm:quotes:<your-mm-id>" }
```

| Channel             | Description                                                                              |
| ------------------- | ---------------------------------------------------------------------------------------- |
| `mm:quotes:{mm_id}` | Your quote lifecycle updates (accepted, accepted details, confirmed, expired, withdrawn) |
| `rfq:{rfq_id}`      | Position and status updates for a specific trade                                         |

## Events

### Quote events

| Event               | Description                                                                                                                                                                                                                    | Data                                                                                      |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| `quote:accepted`    | A user committed your quote. You must confirm it before the deadline.                                                                                                                                                          | `{ quote_id, rfq_id, confirmation_deadline }`                                             |
| `mm_quote:accepted` | MM-only accepted quote details for the selected market maker. Use this to reserve local exposure or record analytics immediately. Its `quote_id` is valid for confirmation; do not depend on ordering versus `quote:accepted`. | `{ rfq_id, quote_id, user_id, quote, exposure_legs, confirmation_deadline, accepted_at }` |
| `quote:confirmed`   | You confirmed the quote. Vault settlement begins.                                                                                                                                                                              | `{ quote_id, rfq_id, execution_id }`                                                      |
| `quote:executed`    | On-chain vault position created.                                                                                                                                                                                               | `{ quote_id, rfq_id }`                                                                    |
| `quote:expired`     | Quote expired before confirmation.                                                                                                                                                                                             | `{ quote_id, rfq_id }`                                                                    |
| `quote:rejected`    | Another quote was accepted instead.                                                                                                                                                                                            | `{ quote_id, rfq_id, reason }`                                                            |
| `quote:withdrawn`   | You withdrew the quote.                                                                                                                                                                                                        | `{ quote_id, rfq_id }`                                                                    |

`mm_quote:accepted` payload:

```json theme={null}
{
  "rfq_id": "550e8400-e29b-41d4-a716-446655440000",
  "quote_id": "7d3a2f1e-4b8c-4d6e-9f0a-1b2c3d4e5f60",
  "market_maker_id": "did:privy:mm",
  "user_id": "did:privy:user",
  "source": "quote_request_commit",
  "quote_request_id": "1a6d1f06-9d4f-47cb-994b-3bdfbbef7e40",
  "draft_quote_id": "b2c3d4e5-6789-0abc-def1-234567890abc",
  "request_version": 3,
  "request_hash": "sha256:...",
  "confirmation_deadline": "2026-06-05T12:00:05.000Z",
  "accepted_at": "2026-06-05T12:00:00.000Z",
  "quote": {
    "payout_odds": 7.08,
    "user_cost": 50,
    "total_payout": 354,
    "mm_cost": 304,
    "valid_until": "2026-06-05T12:00:10.000Z"
  },
  "exposure_legs": [
    {
      "venue": "kalshi",
      "event_ticker": "KXCAR",
      "market_ticker": "KXCAR-YES",
      "side": "yes"
    }
  ]
}
```

<Note>
  **`draft_quote_id` is undocumented.** It appears nowhere else in the API contract, and its relationship to the accepted `quote_id` above isn't specified — treat it as informational only, and use `quote_id` (the value valid for confirmation) rather than `draft_quote_id` for any action. If your integration needs to know what this field represents, raise it with Totalis support rather than assuming a meaning.
</Note>

### Position events

`position_pda` is the on-chain account address for the position, not a lookup key. To fetch or reference a position through the API, use `rfq_id` (or `position_id`, once it's [set on the RFQ](/api-reference/parlays/get)) instead.

| Event                  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Data                                                                                |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `position:created`     | Vault position created, collateral locked.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `{ rfq_id, position_pda, timestamp }`                                               |
| `position:settled`     | Position settled with outcome.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `{ rfq_id, position_pda, outcome, tx_signature, timestamp }`                        |
| `position:cancelled`   | Position cancelled, collateral unlocked.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | `{ rfq_id, position_pda, reason, timestamp }`                                       |
| `position:error`       | Position execution error.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `{ rfq_id, error, timestamp }`                                                      |
| `position:bought_back` | A position was closed early by a winning cash-out bid. Delivered on this `rfq:{rfq_id}` channel, on the `mm:quotes:{mm_id}` channel of the market maker whose exposure closed, and directly to any connection authenticated as the seller or as that maker — so subscribe here and dedupe on `tx_signature`. `amount` is decimal USDC; `quote_id` is the position's original accepted quote, not the winning bid. Nothing is emitted when a bid *acquires* the position instead, and the RFQ does not become `bought_back` in that case — see [the transfer gap](/guides/event-catalog#the-transfer-notification-gap). | `{ rfq_id, position_pda, amount, mm_pays_user, tx_signature, quote_id, timestamp }` |

## Keep-alive

Send periodic pings to keep the connection open:

```json theme={null}
{ "type": "ping" }
```

Response:

```json theme={null}
{ "type": "pong", "timestamp": "2026-06-01T12:00:00.000Z" }
```

## Example

```javascript theme={null}
const ws = new WebSocket('wss://api.totalis.trade/ws');

ws.onopen = () => {
  ws.send(JSON.stringify({ type: 'auth', api_key: '<your-api-key>' }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === 'auth:success') {
    ws.send(JSON.stringify({
      type: 'subscribe',
      channel: `mm:quotes:${msg.user_id}`
    }));
  }

  if (msg.type === 'quote:accepted') {
    console.log('Quote accepted! Confirm before:', msg.data.confirmation_deadline);
    // POST https://api.totalis.trade/v1/mm/quotes/{quoteId}/confirm
  }

  if (msg.type === 'mm_quote:accepted') {
    console.log('Accepted quote details:', msg.data.exposure_legs);
  }

  if (msg.type === 'position:settled') {
    console.log('Position settled:', msg.data.outcome);
  }
};

setInterval(() => {
  ws.send(JSON.stringify({ type: 'ping' }));
}, 30_000);
```
