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.
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
- Handle
cashout_requeston the MM stream, and reconnect withlast_event_id— with a 10 s lifetime, a reconnect gap means lost auctions. - Price from
legs,user_stakeandtotal_payout, respectinglegs[].resolution. These are decimal USDC; your bid is micro-USDC. - Decide from your own book whether you back the position — that determines whether a win closes it or acquires it.
- Bid before
expires_at; expire your own bids locally. - Keep free balance ahead of outstanding bids.
- Alert on 400, 401 and 403. Log 404 and race-class 409s quietly.
- Reconcile wins from
position:bought_backor, for an acquisition, your position reads.
