> ## Documentation Index
> Fetch the complete documentation index at: https://docs.noxpay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Accept Conversion

> POST /v2/rfq/accept — accept an existing quote, choosing the settlement day and destination.

Accepts a quote created via [Create Conversion](/api-reference/conversions/create), locking in the rate and scheduling delivery. The balance in `from_currency` must be available at the moment of accept — it is not reserved when the quote is created.

## Request body

| Field            | Type   | Required    | Description                                  |
| ---------------- | ------ | ----------- | -------------------------------------------- |
| `rfq_id`         | string | Yes         | ID returned by Create Conversion             |
| `settlement_day` | string | Yes         | `"d0"` or `"d1"`                             |
| `wallet_id`      | string | Conditional | Destination crypto wallet ID (crypto payout) |
| `pix_key`        | string | Conditional | Destination Pix key (BRL payout)             |

## Response `200 OK` (accepted)

| Field            | Type   | Description                                                                                                              |
| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------ |
| `rfq_id`         | string | ID of the conversion                                                                                                     |
| `state`          | string | `DONE` once accepted                                                                                                     |
| `amount_from`    | float  | Confirmed amount sent                                                                                                    |
| `amount_to`      | float  | Confirmed amount to be received                                                                                          |
| `rate`           | float  | Confirmed rate                                                                                                           |
| `quote_pair`     | string | Quote pair, as `<from display name>/<to display name>` — display names, not currency codes (e.g. `USDT (TRX)/BRL (PIX)`) |
| `settlement_eta` | string | Confirmed settlement time (RFC 3339)                                                                                     |
| `wallet_id`      | string | Destination wallet, echoed back when the payout is crypto                                                                |
| `pix_key`        | string | Destination Pix key, echoed back when the payout is BRL                                                                  |
| `reason`         | string | Empty on `200`; carries the explanation on a refusal or failure                                                          |

This is the one endpoint in the API that returns `state`, because `state` is what carries the outcome of the accept. Everywhere else, read `status` / `substatus` instead.

A `200` here means the trade is locked and delivery is scheduled — it does not mean funds have already landed. Delivery completes at `settlement_eta`; see [Get Conversion](/api-reference/conversions/get) or the `webhook` to track it.

## Outcomes

`POST /v2/rfq/accept` is the only committing operation in the conversion flow, so it has the widest set of outcomes. Every one of them is listed here.

| HTTP                        | State                | Meaning                                                                                                                  | Retry?                |
| --------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------- |
| `200 OK`                    | `DONE`               | Accepted. `amount_from`, `amount_to`, `rate`, `settlement_eta` are populated                                             | Done                  |
| `202 Accepted`              | —                    | **Still being evaluated — this is not an acceptance.** `reason` is deliberately empty: it is a wait, not a refusal       | Yes, by re-reading    |
| `400 Bad Request`           | —                    | Invalid JSON, unknown field, empty `rfq_id`, or `settlement_day` outside `d0` / `d1`                                     | No                    |
| `401 Unauthorized`          | —                    | Missing or invalid `api-key`                                                                                             | No                    |
| `404 Not Found`             | —                    | The conversion does not exist, or belongs to another account. The two cases are deliberately indistinguishable           | No                    |
| `409 Conflict`              | `EXPIRED`            | The rate expired and the quote was renewed — re-read the conversion and resubmit with the new rate                       | Yes, after re-reading |
| `410 Gone`                  | `DEPRECATED`         | The renewal window closed — create a new conversion                                                                      | No                    |
| `422 Unprocessable Entity`  | `REFUSED` or `ERROR` | Refused. `reason` carries the cause: insufficient balance, D0 unavailable, or a limit ceiling                            | No                    |
| `503 Service Unavailable`   | —                    | The rate provider is unavailable. **Nothing was decided** — the conversion is still in `QUOTE` and can be accepted again | Yes                   |
| `500 Internal Server Error` | —                    | Failed to re-read the conversion or its attributes                                                                       | Sometimes             |

<Warning>
  **A `202` is not a success.** It means the accept is still being evaluated and no decision has been recorded. Do not treat it as confirmation and do not resubmit the accept — re-read [Get Conversion](/api-reference/conversions/get) or wait for the webhook until you reach a terminal outcome.
</Warning>

When a `422` is caused by a limit ceiling rather than balance, `GET /v2/rfq/{id}` exposes `limit_block_source` to tell you which gate blocked it — `operational` for the desk ceiling, `compliance` for the KYB tier. The field is absent when the refusal was for insufficient balance.

`503` and `202` are safe to retry. `409` needs a re-read first. `410` and `422` are final for that `rfq_id`.

**Status codes:** `200`, `202`, `400`, `401`, `404`, `409`, `410`, `422`, `500`, `503`

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://checkout.noxpay.io/v2/rfq/accept \
    -H "api-key: <key>" \
    -H "Content-Type: application/json" \
    -d '{
      "rfq_id": "NOXabc123...",
      "settlement_day": "d0",
      "wallet_id": "..."
    }'
  ```

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

  response = requests.post(
      "https://checkout.noxpay.io/v2/rfq/accept",
      headers={
          "api-key": "<key>",
          "Content-Type": "application/json",
      },
      json={
          "rfq_id": "NOXabc123...",
          "settlement_day": "d0",
          "wallet_id": "...",
      },
  )
  print(response.json())
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://checkout.noxpay.io/v2/rfq/accept", {
    method: "POST",
    headers: {
      "api-key": "<key>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      rfq_id: "NOXabc123...",
      settlement_day: "d0",
      wallet_id: "...",
    }),
  });
  const data = await response.json();
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "rfq_id":         "NOXabc123...",
    "state":          "DONE",
    "amount_from":    1000.0,
    "amount_to":      5050.0,
    "rate":           5.050,
    "quote_pair":     "USDT (TRX)/BRL (PIX)",
    "settlement_eta": "2026-07-01T19:00:00Z"
  }
  ```

  ```json 409 theme={null}
  { "state": "EXPIRED", "reason": "Rate expired and was renewed — fetch the latest quote before retrying" }
  ```

  ```json 410 theme={null}
  { "state": "DEPRECATED", "reason": "Renewal window closed — create a new conversion" }
  ```

  ```json 422 theme={null}
  { "state": "REFUSED", "reason": "Insufficient balance" }
  ```

  ```json 503 theme={null}
  { "state": "QUOTE", "reason": "forex rate unavailable" }
  ```
</ResponseExample>
