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

# Bid on a cashout auction

> Bid one all-in price on a user's early cashout auction.

Submit or replace your bid on an early cashout auction. Auctions arrive as a
[`cashout_request`](/solana/api-reference/quote-service-mm/stream#cashout_request) event on the
[MM stream](/solana/api-reference/quote-service-mm/stream) you already subscribe to. They are broadcast to
every market maker, including on positions you do not back. An auction lives about 10 seconds.

Bid one all-in `price_micro`: the microUSDC the user receives. There is no direction field and no
fee term. The highest live bid wins, and ties go to the earliest bid. To pass, submit nothing;
there is no decline endpoint.

Re-submitting replaces your bid atomically and also re-times it. Re-sending the same price puts you
behind any bid that has since matched it. Do not re-`PUT` an unchanged price just to refresh the
TTL: you would hand away a tie you were winning.

| If you | A win |
| - | - |
| Back the position | Closes it. A closing exit carries the profit fee on your side. |
| Do not back it | Acquires it. No fee applies. |

For the payload and auction mechanics, see [Cashout auctions](/solana/guides/cashout-auctions).

## Authentication

API key required, with the `mm:quote` scope. Pass it in the `X-API-Key` header.

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

## Path parameters

<ParamField path="id" type="string" required>
  The cashout request ID (UUID). Called `cashout_request_id` on the push.
</ParamField>

## Request body

<ParamField body="price_micro" type="integer" required>
  The all-in amount the user receives, in microUSDC (`1_000_000` = \$1.00). Integer, minimum `1`.
  May be below the user's stake: a losing parlay exits for less than it cost.

  Two ceilings apply, both in microUSDC. `user_stake` and `total_payout` arrive as decimal USDC on
  the push, so scale them by `1e6` first.

  Every bid must satisfy `price_micro <= round(total_payout * 1e6)` (`price_above_max_payout`). If
  you are the position's current counterparty, a tighter fee-aware ceiling binds
  (`price_above_buyback_bound`). It is derived from `total_payout - user_stake`, not from the
  `mm_risk` field, because the two drift by up to `0.0001` USDC:

  ```
  S = round(user_stake * 1e6)
  M = round((total_payout - user_stake) * 1e6)
  price_micro <= S + M - floor(M * fee_bps / 10_000)
  ```
</ParamField>

<ParamField body="expires_in_ms" type="integer" default="15000">
  How long your bid stays live, in milliseconds. Range 5000-60000. A bid may outlive the auction.
  One that lapses mid-auction stops being the best bid, and nothing tells you when, so age bids out
  locally.
</ParamField>

The body is strict: an unknown field is a `400`.

## Withdrawing a bid

`DELETE /v1/mm/cashout-requests/{id}/quote` pulls your live bid. It is idempotent.

| Response | Meaning |
| - | - |
| `204 No Content` | Your bid was removed. |
| `200 OK` with `{"status": "already_withdrawn"}` | Your bid had already lapsed. Not an error. |
| `409` | The auction is no longer active. |
| `404` | The auction is unknown. |

There is no partial withdraw. Re-`PUT` to change a price.

## Response

Returns `201 Created` for your first bid on an auction, or `200 OK` when replacing your own.

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="quote" type="object">
      The submitted bid.

      <Expandable title="quote">
        <ResponseField name="id" type="string">Bid UUID.</ResponseField>
        <ResponseField name="cashout_request_id" type="string">The auction this bid is for.</ResponseField>
        <ResponseField name="market_maker_id" type="string">Your market maker ID.</ResponseField>
        <ResponseField name="price_micro" type="integer">The all-in microUSDC you bid.</ResponseField>
        <ResponseField name="valid_until" type="string">ISO 8601 timestamp when this bid expires.</ResponseField>
        <ResponseField name="status" type="string">`"active"`</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="book_seq" type="integer">The auction's new book sequence number.</ResponseField>
    <ResponseField name="replaced" type="boolean">`true` if this replaced your previous bid.</ResponseField>
  </Expandable>
</ResponseField>

## Errors

| Status | `details.reason` | Description |
| - | - | - |
| 400 | validation | Non-integer or non-positive `price_micro`, `expires_in_ms` out of range, unknown field, or malformed JSON. |
| 400 | `price_above_max_payout` | Bid exceeds the position's `total_payout`. Response carries `max_price_micro`. |
| 400 | `price_above_buyback_bound` | You back this position and the bid exceeds what your locked collateral covers after the profit fee. Skipped when the fee rate is briefly unavailable; the commit then re-checks it and rejects with `amount_over_bound`. |
| 401 | none | Missing or invalid API key (`error.code: UNAUTHORIZED`). |
| 403 | `insufficient_scope` | Key lacks `mm:quote`. Response carries `required_scope`. |
| 404 | none | Auction unknown, or already evicted at its TTL. The ordinary "too slow" outcome, not a fault. |
| 409 | `self_quote` | You opened this auction (you are the seller). Bidding on a position you back is allowed; that is the closing case. |
| 409 | `not_active` | The auction was committed or cancelled before your bid landed. |
| 409 | `expired` | The auction expired as your bid landed. |
| 409 | `MARKET_NEAR_CLOSE` | The underlying market is too close to close to exit. |
| 409 | `buyback_wallet_missing` | You back this position but no wallet is on record, so a closing exit cannot be built. Only your bids fail; other market makers can still win the same auction by acquiring the position. |
| 429 | none | Too many requests (`error.code: RATE_LIMITED`). Honor `Retry-After`. |

<Warning>
  Winning is not the same as being paid. The user is only filled at a price they explicitly accepted,
  so a fill can fail if the book moves down between their tap and their commit. If you win by
  acquiring a position, your funding and eligibility are checked at that commit, not when you bid. An
  underfunded or ineligible winning bid fails there with `insufficient_buyer_balance`,
  `buyer_no_vault`, or `buyer_is_counterparty`.
</Warning>

<RequestExample>
  ```bash curl theme={null}
  curl -X PUT https://api.totalis.trade/v1/mm/cashout-requests/$CASHOUT_REQUEST_ID/quote \
    -H "X-API-Key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"price_micro": 1990000, "expires_in_ms": 15000}'
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch(
    `https://api.totalis.trade/v1/mm/cashout-requests/${cashoutRequestId}/quote`,
    {
      method: 'PUT',
      headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
      // price_micro is what the USER receives, all-in, in micro-USDC
      body: JSON.stringify({ price_micro: 1_990_000, expires_in_ms: 15_000 }),
    },
  );
  ```

  ```python Python theme={null}
  import requests

  requests.put(
      f'https://api.totalis.trade/v1/mm/cashout-requests/{cashout_request_id}/quote',
      headers={'X-API-Key': API_KEY},
      # price_micro is what the USER receives, all-in, in micro-USDC
      json={'price_micro': 1_990_000, 'expires_in_ms': 15_000},
  )
  ```
</RequestExample>


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