curl -X POST https://api.totalis.trade/v1/cashout-requests/c3d4e5f6-7890-abcd-ef12-34567890abcd/commit \
-H "X-API-Key: $TOTALIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"min_price_micro": 66250000}'
{
"data": {
"cashout_request_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd",
"status": "committed",
"chain_sig": "5Nx7...buybackSig"
}
}
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Cashout is being processed; please check back",
"details": { "reason": "COMMIT_UNREACHABLE", "indeterminate": true }
}
}
Quote service
Commit cashout
Accept the winning bid on an early cashout auction and drive it on-chain.
POST
/
v1
/
cashout-requests
/
{id}
/
commit
curl -X POST https://api.totalis.trade/v1/cashout-requests/c3d4e5f6-7890-abcd-ef12-34567890abcd/commit \
-H "X-API-Key: $TOTALIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"min_price_micro": 66250000}'
{
"data": {
"cashout_request_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd",
"status": "committed",
"chain_sig": "5Nx7...buybackSig"
}
}
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Cashout is being processed; please check back",
"details": { "reason": "COMMIT_UNREACHABLE", "indeterminate": true }
}
}
Accept the winning bid on your early cashout auction and exit on-chain. The bid is the price, and the market maker does not confirm it. You echo back the price you accepted, and the exit fills only at or above it. Totalis obtains signatures server-side via Privy at execution.
You receive
The commit is idempotent per (request, user). A committed result is cached for 5 minutes and replayed verbatim with
A Privy JWT (
The body is strict. An unknown field is a
A
min_price_micro or better either way. Who won decides what happens to the position:
| Winning bid from | Position | RFQ status |
|---|---|---|
| The position’s own counterparty | Closes. Your stake is released. | Becomes bought_back |
| Any other market maker | Transfers to the winner and stays open under new ownership. You are out of it. | Does not become bought_back |
200 OK. A retry with a different min_price_micro still gets the first result, and the new floor is not re-evaluated. Retry with the value you first sent.
Indeterminate commits never double-spend. If the on-chain outcome is unknown (timeout or transient RPC failure), the request stays
committing and returns 503 with details.indeterminate: true. Totalis resolves it against on-chain state, so do not treat that 503 as a failure. Reopen the stream and wait for the terminal status. See the 503 cases below.Authentication
Send your API key in theX-API-Key header. The key needs the trading:write scope.
X-API-Key: <your-api-key>
Authorization: Bearer <jwt>) is also accepted. See Authentication.
Path parameters
string
required
The cashout request ID (UUID).
Request body
integer
required
The price you accepted on screen, in microUSDC. Echo back the
price_micro from the best_quote frame you were shown. Without it the commit is a 400, because nothing ever fills at a price the user did not see.The fill uses the best live bid at commit time, floored at this value. A better bid fills at the better price. If the book has moved below it, the commit fails with 409 price_below_accepted (carrying best_price_micro) and the auction stays open to re-tap.400.
Response
Returns201 Created on a fresh commit, or 200 OK when replaying a cached idempotent result.
object
Errors
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Missing or invalid min_price_micro (must be an integer >= 1), or an unknown field. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 403 | FORBIDDEN | You do not own this cashout request (details.reason: not_owner). |
| 404 | NOT_FOUND | Cashout request not found. |
| 409 | CONFLICT | Determinate failure: nothing landed. See details.reason below. |
| 410 | GONE | The auction expired before commit. Open a fresh one. |
| 429 | RATE_LIMITED | Too many requests. Honor Retry-After. |
| 503 | SERVICE_UNAVAILABLE | Branch on details.indeterminate, never on the message. See below. |
409 means nothing landed. Most reasons are retryable against a live book. already_transferred is terminal: stop, and re-read the position instead of reopening an auction.
409 reason | Meaning |
|---|---|
price_below_accepted | The best live bid is below min_price_micro. Carries best_price_micro. |
quote_expired | No live bid left. |
not_active | The cashout request is not active. |
locked | A commit for this auction is already in flight. |
missing_wallet | The position has no seller wallet on record, so the exit cannot be built. |
amount_over_bound | The winning counterparty bid failed the collateral re-check at commit. |
already_transferred | Terminal. The position has already moved. |
insufficient_buyer_balance, buyer_no_vault, buyer_is_seller, buyer_is_counterparty | Buyer-side rejections when the winner is acquiring the position. |
details.indeterminate | Meaning | Your move |
|---|---|---|
true | The exit may have landed. details.reason is the execution-layer code, typically COMMIT_UNREACHABLE (the lane was not reached), BAD_RESPONSE (it answered unusably), or the lane’s own error code. It is not a stable taxonomy, so treat every value the same. | Do not retry. Reopen the stream and wait for the terminal status. |
false | Only ever fee_unavailable: the profit-fee rate could not be read. Nothing landed, and the auction is still open. | Retry immediately. It is safe. |
curl -X POST https://api.totalis.trade/v1/cashout-requests/c3d4e5f6-7890-abcd-ef12-34567890abcd/commit \
-H "X-API-Key: $TOTALIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"min_price_micro": 66250000}'
{
"data": {
"cashout_request_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd",
"status": "committed",
"chain_sig": "5Nx7...buybackSig"
}
}
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Cashout is being processed; please check back",
"details": { "reason": "COMMIT_UNREACHABLE", "indeterminate": true }
}
}
Was this page helpful?

