---
updatedAt: 2026-10-16T08:11:00.482Z
---

Fetch the complete documentation index at: https://docs.avvio.xyz/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Accept a quote

`POST https://api.avvio.xyz/business/api/v1/payments/organizations/{orgId}/quotes/accept`

Send the money.

**This is the step that moves money.** It debits your balance and
returns the payout. A balance-funded payout needs nothing else. A
payout you fund yourself comes back with `requiresFunding: true`: read
`GET /payouts/{payoutId}/funding`, send the money, and confirm it with
`POST /payouts/{payoutId}/funding/confirm`.

If this times out, the outcome is unknown: the payout may have been
accepted. **Retry with the same `Idempotency-Key`.** A replay returns
the original payout; re-quoting sends a second payment. A
`500 PAYOUT_OUTCOME_UNKNOWN` means the same thing: do not re-quote or
mint a new key; look for the payout with
`GET /orders?reference=<your reference>` first.

## Parameters

- `orgId` (path, required) — The opaque organization id issued to you, normally CUID-shaped (for example `cmsx…`). It is not an `org_`-prefixed alias. Pass it unchanged in every organization-scoped path.
- `Idempotency-Key` (header, required) — A unique value per logical operation, 1-255 chars of `A-Z a-z 0-9 _ . : -`. Reuse it to retry. Same key with the same body replays the stored response; same key with a *different* body is a `409`, because answering with the first call's result would hand you a receipt for a payout you did not request. A `4xx` releases the key, so you can fix the body and reuse it. **Reuse it; do not generate one per attempt.** A key minted per attempt defeats replay entirely: every retry looks like a new request, so every retry pays. We also watch for an identical body arriving under a *different* key within 15 minutes and refuse it with `DUPLICATE_REQUEST_DETECTED`. Records are kept for 7 days. That is a retention window only: there is no path where an expired key is re-executed.
- `X-Allow-Duplicate` (header) — Set to `true` to send a request that is byte-identical to one you sent within the last 15 minutes under a different key. `true` is the only accepted value. It switches off the guard that catches a retry arriving under a fresh key, so send it only when you mean to pay twice.

## Example

```bash
IDEMPOTENCY_KEY=$(uuidgen)  # new key per call; reuse it only to retry this exact request
curl -s -X POST "$AVVIO_BASE_URL/payments/organizations/$AVVIO_ORG_ID/quotes/accept" \
  -H "x-api-key: $AVVIO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "content-type: application/json" \
  -d '{
        "snapshotId": "<snapshotId>",
        "type": "OFFRAMP",
        "endUser": {
          "id": "customer_42"
        },
        "paymentReason": "FAMILY_SUPPORT"
      }'
```

## Responses

- `200` — The payout. A replayed idempotent request returns the original and sets the `Idempotency-Replayed` response header.
- `400` — Nothing was sent. - `BAD_REQUEST`: the quote expired or is not one we issued (price again), or a field this route does not take (`provider`, `billId`, `fundingId`); `detail` says which. - `INSUFFICIENT_BALANCE`: your balance does not cover the payout. Top up and quote again. - `VALIDATION_ERROR`: a field is malformed; `errors` names it. - `IDEMPOTENCY_KEY_REQUIRED` or `IDEMPOTENCY_KEY_INVALID`: the header is missing or malformed.
- `401` — The key was refused. Nothing ran. - `UNAUTHORIZED`: missing, invalid or revoked, or a key on a route that does not accept one. - `KEY_EXPIRED`: the key passed the expiry it was issued with. Issue a new one; an expired key cannot be rotated. - `KEY_IP_NOT_ALLOWED`: the key is pinned to source addresses and this request came from another.
- `403` — `USE_POST_PAYOUTS`: this organization has an approval threshold or a velocity cap, and only `POST /payouts` enforces them. Nothing was sent; send the payout through `POST /payouts`, which may answer `202 pending_approval`. Also the refusals every write can answer: `FORBIDDEN` (a key for a different organization), `ACCOUNT_BLOCKED`, `LIVE_KEY_ORG_NOT_APPROVED` and `INSUFFICIENT_SCOPE`.
- `409` — On a route that moves money: - `IDEMPOTENCY_KEY_CONFLICT`: the key was reused with a different body. Use a new key for a new request. - `IDEMPOTENCY_KEY_REQUEST_IN_PROGRESS`: the first request with this key is still running. Back off and retry the same key. - `PAYOUT_OUTCOME_UNKNOWN`: a replay of a key whose first call answered `500 PAYOUT_OUTCOME_UNKNOWN`. Money may have moved. Do not send a new key; look the outcome up first. `originalRequestId` names the first call. - `DUPLICATE_REQUEST_DETECTED`: an identical body under a *different* key within 15 minutes. Nothing was executed. Retry with `originalIdempotencyKey`, or send `X-Allow-Duplicate: true` if you mean to pay twice.
- `429` — Too many requests. The default ceiling is **100 requests per minute per API credential** on a 60-second window. High-volume payout and reconciliation routes declare a 600/minute override, and batch submission a 30/minute ceiling. A separate 2,000/minute per-source-IP abuse ceiling always applies. Obey `Retry-After`; it is in seconds and is authoritative. A 429 means the request was refused before the handler ran. Retry reads normally; retry an idempotent mutation with its same `Idempotency-Key`.
- `500` — `PAYOUT_OUTCOME_UNKNOWN`: the call failed after the money may have moved, and we cannot yet say whether it did. **Do not retry with a new `Idempotency-Key`**; that is how a payment goes out twice. Look the outcome up first (the operation says where), or replay the same key, which answers `409 PAYOUT_OUTCOME_UNKNOWN` until we resolve it. Send support the `requestId`. Every other `500` is `INTERNAL`: nothing was recorded under the key, and retrying with the same key is safe.

Machine contract: [partner-payouts.openapi.yaml](/partner-payouts.openapi.yaml), operation `sendPayout`.
