Skip to main content
GET
Open a Server-Sent Events (SSE) stream of all active quote requests. This is the primary integration path for market makers; use it instead of polling. You receive new requests, version updates, closes, and early cashout auctions.

Authentication

API key required. Pass your API key in the X-API-Key header.

SSE event types

The stream sends seven event names. Match them exactly: quote_request and quote_request_expired use underscores, but quote_request:updated uses a colon.

connected

Sent once on connection. Confirms your identity. mm_id is your Privy DID. It is the same value as the user_id returned by auth:success on the WebSocket, and the key of your mm:quotes:{mm_id} channel there.

snapshot_begin

Sent at the start of the initial snapshot, on a new connection or a reconnect. Every active quote request follows before snapshot_complete.

quote_request

Sent when a new quote request is created, and once for each active request replayed during the snapshot. This is the event you price.

quote_request:updated

Sent when a request you already saw moves to a new version because the user edited the legs or the bet amount. The payload matches quote_request, with the incremented version and a new request_hash. Your quote on the prior version is invalidated automatically. It leaves the book immediately and never blocks a new submission, so you do not need to withdraw it. Re-price and submit a new quote with the new version and request_hash.
A listener registered only for quote_request misses every version bump. Register one for quote_request:updated too, or branch on the event: field in a raw SSE parser.

snapshot_complete

Sent when the initial snapshot finishes. The stream then sends incremental updates only.

quote_request_expired

Sent when a quote request you saw is no longer active. Remove it from your local state. reason says why it closed: won separates a lost auction from an abandoned or timed-out one: The winning maker’s identity and odds are never disclosed.

cashout_request

Sent when a user opens an early cashout auction on a position, and once for each active auction replayed during the snapshot. It is broadcast to every market maker, including on positions you do not back. The auction lives about 10 seconds. Bid with PUT /v1/mm/cashout-requests/{id}/quote. To pass, submit nothing; there is no decline endpoint.
This event differs from quote_request in name and payload. It carries cashout_request_id (not id) and the on-chain position_id. Branch on the SSE event: field, or register a dedicated cashout_request listener.
Every field below is always present.
string
required
The auction id. Pass it as {id} when you bid. This payload has no id field, unlike quote_request.
string
required
The on-chain position id (32 hex chars, no 0x). Look it up in your own book to see whether you are its counterparty, which determines your economics.
array
required
The position’s legs. Each carries id, event_ticker, market_ticker, side (yes / no), venue, and resolution.resolution is one of unresolved, won, lost, void. It is your only protection against pricing an already-decided parlay. void overrides the others: any void leg cancels the whole position at settlement and refunds the stake, so the position is worth roughly user_stake even when a sibling leg reads lost. With no void leg, one lost leg makes the parlay worthless.
number
required
Decimal USDC. The net stake the counterparty underwrites, the same quantity as on quote_request. It is the reference point for the exit price: a bid above it means the user leaves in profit, below it at a loss.
number
required
Decimal USDC. The counterparty’s locked risk on the position, for pricing context only. Do not compute the counterparty bid ceiling from it. The server derives that ceiling from total_payout - user_stake; the two are stored separately and can disagree in the last decimal.
number
required
Decimal USDC. What the position pays if every leg wins, and the hard ceiling on any bid: price_micro <= round(total_payout * 1e6), or the bid is rejected price_above_max_payout.
number
required
The accepted quote’s payout multiplier. Pricing context, not an amount, and never a bid term. On positions created before this field was carried, it is reconstructed from total_payout / user_stake and can be off in the 5th or 6th decimal. Do not reconcile against it exactly.
integer
required
The auction’s version, 1 today. A cashout auction is never re-versioned mid-flight the way a forward quote request can be, so there is no cashout_request:updated event to handle.
string
required
ISO 8601 close time of the auction, about 10 s out. Bid before it. It is not the position’s market-end horizon, which this payload omits, so you cannot pre-filter for the near-close cutoff. A bid on a position close to its market end is rejected MARKET_NEAR_CLOSE. Treat that as an ordinary lost auction.

Leg fields

Legs use the same field names on every event and both venues. The values are venue specific. The examples above are Kalshi. Legs can carry extra display fields beyond these. The set is additive and differs by event, so parse leniently and ignore keys you do not use.

Reconnection

Every SSE event includes an id: field. Persist it. On reconnect, pass it as the last_event_id query parameter to ask for the events you missed instead of a fresh snapshot. You get a replay only while that id is still retained on the server; otherwise the full snapshot is sent again, starting with snapshot_begin. On production in September 2026, reconnects received the full snapshot even with an id seconds old, so treat every snapshot as authoritative and do not depend on replay. The stream also sends a : keepalive comment about every 3 seconds. If nothing arrives for much longer, reconnect.
The taker-fee rate is read once per connection. On a long-lived stream, user_stake reflects the rate in effect when you connected. Reconnect after a fee rate change to get user_stake at the new rate.

Notes

  • Price payout_odds and size collateral against user_stake, the stake net of the taker fee, never the gross bet_amount: user_stake = bet_amount - taker_fee, where taker_fee = floor(bet_amount_micro * taker_fee_bps / 10000) in microUSDC. When the fee is off (taker_fee_bps is 0), user_stake == bet_amount.
  • The stream excludes quote requests created by your own user account.

Errors