Skip to main content
A user can leave a parlay before it settles. When they do, Totalis opens a short auction on that position and pushes it to every market maker on the stream you already consume. You reply with one number. The highest live bid wins.
Units. Every *_micro field is an integer of micro-USDC (1_000_000 = $1.00). The money fields beside them — user_stake, mm_risk, total_payout, and the amount on the settlement event — are decimal USDC. (payout_odds is a multiplier, not an amount.) Both conventions appear in the same payload, so scale before you compare.

How it works

1

Receive the auction

A cashout_request event arrives on GET /v1/mm/quote-requests/stream. It carries the position’s legs and economics. Auctions are broadcast, so you see exits on positions you have no relationship with.
2

Price the exit

Re-value the parlay at current odds, and read legs[].resolution carefully. void beats everything: any void leg cancels the whole position at settlement and refunds the stake, so such a position is worth about the stake even if a sibling leg already resolved lost. Absent a void leg, one lost leg makes the parlay worthless. Nothing stops an auction opening on a position whose legs are already decided, so resolution is your only defence.
3

Bid one all-in price

PUT your bid to /v1/mm/cashout-requests/{id}/quote before expires_at. price_micro is what the user receives, all-in. Highest live bid wins; ties go to the earliest bid.
4

Reconcile the outcome

If you win as the counterparty you receive position:bought_back. If you win as anyone else you acquire the position and, today, receive no event — see Knowing you won.

The auction

price_micro is a single all-in figure: no direction field, no separate fee term, no gross-vs-net. What you send is what the user sees on screen and what they walk away with. It can be below their stake — a losing parlay exits for less than it cost, and the user never pays more than their stake to leave. A bid may outlive the auction. Nothing tells you your bid lost, lapsed, or that the auction closed, so age bids out locally against expires_at. To pull a live bid before it lapses, DELETE /v1/mm/cashout-requests/{id}/quote: 204 when it was removed, 200 with {"status": "already_withdrawn"} if it had already gone (idempotent, not an error), 409 once the auction is no longer active.
Your bid being best does not guarantee a fill. The user is only ever filled at a price they explicitly accepted, so if the book moves down between their tap and their commit, the commit fails and nobody trades.

Knowing you won

There is no per-auction result event on the MM stream. A bought-back parlay reports a realized cash-out P&L rather than a win or loss — the exit is a real settlement, not a refund.

Errors

Commit-time rejections never reach you as an HTTP response — you learn of them only by not being filled. The ones worth knowing: amount_over_bound (the fee-aware ceiling, re-checked when the fee rate was unavailable at bid time), insufficient_buyer_balance / buyer_no_vault (acquisition, your funding), and already_transferred (the position had already moved). Treat 404 and the race-class 409s as ordinary lost auctions and log them quietly. Treat 400, 401 and 403 as your own bug: if every bid fails that way you are silently out of the market.

Checklist

  1. Handle cashout_request on the MM stream, and reconnect with last_event_id — with a 10 s lifetime, a reconnect gap means lost auctions.
  2. Price from legs, user_stake and total_payout, respecting legs[].resolution. These are decimal USDC; your bid is micro-USDC.
  3. Decide from your own book whether you back the position — that determines whether a win closes it or acquires it.
  4. Bid before expires_at; expire your own bids locally.
  5. Keep free balance ahead of outstanding bids.
  6. Alert on 400, 401 and 403. Log 404 and race-class 409s quietly.
  7. Reconcile wins from position:bought_back or, for an acquisition, your position reads.