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

# Live quote requests

> How Totalis parlay trading works: create quote requests, receive real-time pricing from market makers, and commit with stale-price protection.

Live quote requests are the core trading mechanism on Totalis. You create a parlay with 2-5 market legs, market makers compete to price it in real time, and you lock in the best offer when you're ready.

All endpoints use the `/v1/` prefix on the Quote Service base URL.

## How it works

<Steps>
  <Step title="Create a quote request">
    Call [`POST /v1/quote-requests`](/api-reference/quote-service/create) with your parlay legs and bet amount. You can update legs or bet amount with [`PATCH /v1/quote-requests/{id}`](/api-reference/quote-service/update) — each change bumps the `version` and invalidates stale quotes.
  </Step>

  <Step title="Stream live pricing">
    Open an SSE connection to [`GET /v1/quote-requests/{id}/stream`](/api-reference/quote-service/stream) to receive `best_quote` events as market makers submit and update their offers. Each event includes `book_seq` (monotonically increasing) and the current best payout multiplier.
  </Step>

  <Step title="Market makers price your request">
    Connected market makers receive your request via their [SSE stream](/api-reference/quote-service-mm/stream) and submit competing quotes via [`PUT /v1/mm/quote-requests/{id}/quote`](/api-reference/quote-service-mm/submit-quote). You always see the best available offer.
  </Step>

  <Step title="Commit the best quote">
    When you're satisfied with the price, call [`POST /v1/quote-requests/{id}/commit`](/api-reference/quote-service/commit). The commit includes protection fields that prove you saw the current price, preventing stale execution.
  </Step>

  <Step title="Trade confirmation">
    The winning market maker receives a `quote:accepted` event via [WebSocket](/guides/websocket) and confirms the trade. Vault settlement begins automatically.
  </Step>
</Steps>

## Commit protection

The commit endpoint requires these fields to ensure you're locking in the price you actually saw:

| Field                      | Type    | Description                                                                                                         |
| -------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `expected_version`         | integer | The quote request `version` you're committing against. Rejected if the request was modified since your last update. |
| `displayed_quote_id`       | string  | The `id` of the best quote you were shown.                                                                          |
| `displayed_quote_book_seq` | integer | The `book_seq` from the SSE event that delivered the quote. Proves your pricing was current.                        |
| `min_payout_odds_seen`     | number  | The minimum payout odds you saw. Only quotes at or above this threshold can be selected.                            |

```json theme={null}
{
  "expected_version": 3,
  "displayed_quote_id": "quote-uuid",
  "displayed_quote_book_seq": 5,
  "min_payout_odds_seen": 4.25
}
```

## Rejection codes

If a commit fails, `error.details.reason` tells you why:

| Reason                    | What happened                                                                                                                                |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `QUOTE_CHANGED`           | The request was updated since your last fetch. Re-fetch and try again.                                                                       |
| `MARKET_NOT_LIVE`         | One or more markets expired, halted, or were delisted. Remove the affected legs.                                                             |
| `QUOTE_EXPIRED`           | All quotes expired. Wait for a fresh quote and retry.                                                                                        |
| `COMMIT_FAILED`           | The commit couldn't be completed — for example, no eligible market maker had sufficient collateral. Not retryable; the trade did not happen. |
| `COMMIT_FAILED_RETRYABLE` | Temporary error. Retry after a short delay.                                                                                                  |

## For market makers

### Receiving quote requests

Connect to the [MM SSE stream](/api-reference/quote-service-mm/stream) to receive quote requests in real time. On initial connection you receive a snapshot of all active requests, then incremental updates as new requests arrive.

### Submitting quotes

Call [`PUT /v1/mm/quote-requests/{id}/quote`](/api-reference/quote-service-mm/submit-quote) with the `request_version` and `request_hash` from the SSE event. One active quote per request version — submitting again replaces your previous quote. Send only the fields below; the server derives `user_cost`, `total_payout`, and `mm_cost` from `payout_odds` and the request's `bet_amount`.

```json theme={null}
{
  "request_version": 3,
  "request_hash": "sha256...",
  "payout_odds": 4.25,
  "expires_in_ms": 15000
}
```

Keep quotes short-lived (default 15s). When the request changes to a new version, your prior-version quote is invalidated automatically — just re-price and `PUT` a new quote with the new `version` and `request_hash`. You don't need to withdraw the old one.

### Withdrawing quotes

Call [`DELETE /v1/mm/quote-requests/{id}/quote`](/api-reference/quote-service-mm/withdraw-quote) to retract a quote on the **current** version before the user commits it — for example, if your price moved and you want to stand down. This is not part of the version-change flow: a new `version` already invalidates your prior quote, so you don't withdraw to re-quote.

## SSE event format

Events on the user stream (`/v1/quote-requests/{id}/stream`):

```json theme={null}
{
  "book_seq": 5,
  "version": 3,
  "best_quote": {
    "id": "quote-uuid",
    "payout_odds": 4.25,
    "user_cost": 25,
    "total_payout": 106.25,
    "mm_cost": 81.25,
    "valid_until": "2026-06-01T18:45:45.000Z"
  }
}
```

When no quotes are active, `best_quote` is `null`. Store `book_seq` and `best_quote.id` from the latest event — you'll need them for the commit request.

## Quote request object

```json theme={null}
{
  "id": "1a6d1f06-9d4f-47cb-994b-3bdfbbef7e40",
  "version": 3,
  "request_hash": "sha256...",
  "book_seq": 5,
  "status": "active",
  "bet_amount": 25,
  "expires_at": "2026-06-01T18:45:30.000Z",
  "legs": [
    {
      "id": "8ccf2c5d-...",
      "market_ticker": "KXBTC-26JUN05-T73500",
      "side": "yes",
      "venue": "kalshi"
    }
  ],
  "input_legs": [
    { "market_ticker": "KXBTC-26JUN05-T73500", "side": "yes", "venue": "kalshi" }
  ]
}
```
