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

# Commit cashout

> Accept the winning bid on an early cashout auction and drive it on-chain.

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 `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` |

The commit is idempotent per (request, user). A committed result is cached for 5 minutes and replayed verbatim with `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.

<Note>
  **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](/solana/api-reference/quote-service/cashout-stream) and wait for the terminal `status`. See the [`503` cases](#errors) below.
</Note>

## Authentication

Send your API key in the `X-API-Key` header. The key needs the `trading:write` scope.

```
X-API-Key: <your-api-key>
```

A Privy JWT (`Authorization: Bearer <jwt>`) is also accepted. See [Authentication](/solana/authentication).

## Path parameters

<ParamField path="id" type="string" required>
  The cashout request ID (UUID).
</ParamField>

## Request body

<ParamField body="min_price_micro" type="integer" required>
  The price you accepted on screen, in [microUSDC](/solana/glossary#units). 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.
</ParamField>

The body is strict. An unknown field is a `400`.

## Response

Returns `201 Created` on a fresh commit, or `200 OK` when replaying a cached idempotent result.

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="cashout_request_id" type="string">The cashout request UUID.</ResponseField>
    <ResponseField name="status" type="string">`"committed"`</ResponseField>
    <ResponseField name="chain_sig" type="string">The on-chain transaction signature: `buy_back_position` when the position closed, `transfer_position` when it transferred.</ResponseField>
  </Expandable>
</ResponseField>

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

A `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](/solana/api-reference/quote-service/cashout-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. |

<RequestExample>
  ```bash theme={null}
  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}'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "data": {
      "cashout_request_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd",
      "status": "committed",
      "chain_sig": "5Nx7...buybackSig"
    }
  }
  ```

  ```json 503 theme={null}
  {
    "error": {
      "code": "SERVICE_UNAVAILABLE",
      "message": "Cashout is being processed; please check back",
      "details": { "reason": "COMMIT_UNREACHABLE", "indeterminate": true }
    }
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.