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

# Quote a payout

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

Lock a price against a real recipient.

Returns a snapshot with the locked rate and the amount the recipient
receives. **No money moves.** Your caps and screening run here too, so
an over-cap amount or a refused recipient fails before a quote is
spent (`422`).

Where an underfunded balance fails depends on the environment. The
sandbox checks it here (`400 BAD_REQUEST`, "Insufficient USD balance
… Top up with POST …/sandbox/fund"). Live, the balance is held when
you accept the quote, so `400 INSUFFICIENT_BALANCE` comes from
`POST /quotes/accept` or `POST /payouts`.

Quotes expire. Price and send close together.

## 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) — Same semantics as `Idempotency-Key` on the money routes (replay on the same body, `409` on a different one, released by a `4xx`), but optional here: without it the request simply runs once with no replay. Every `POST`, `PATCH` and `DELETE` honors it; send one whenever your client might retry.

## 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/offramp" \
  -H "x-api-key: $AVVIO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "content-type: application/json" \
  -d '{
        "amount": "200.00",
        "destinationAccountId": "<destinationAccountId>",
        "purposeOfPayment": "FAMILY_SUPPORT",
        "amountLeg": "source"
      }'
```

## Responses

- `200` — A locked quote snapshot
- `400` — Nothing was sent. - `VALIDATION_ERROR`: a field is malformed; `errors` names it. - `QUOTE_NOT_POSITIVE`: fees would leave the recipient with zero or less. Increase the amount and re-quote. - `EXACT_OUTPUT_UNSUPPORTED`: `amountLeg: destination` or `source_net` on a routing without `capabilities.exactOutput`. - `INDICATIVE_PRICING_UNAVAILABLE`: `amountLeg: source_net` on a routing that publishes no market rate. Send `amountLeg: destination` instead. - `BAD_REQUEST`: an unsupported corridor, an amount outside the corridor's minimum or maximum, or (sandbox only) an underfunded balance; `detail` says which. - `IDEMPOTENCY_KEY_INVALID`: a malformed `Idempotency-Key`.
- `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`.
- `404` — `DESTINATION_ACCOUNT_NOT_FOUND`: no payment method with this `destinationAccountId` belongs to your organization. Nothing was sent. Use a `destinationAccountId` from a recipient you created.
- `422` — A control refused it and **nothing was sent**. `PAYOUT_LIMIT_EXCEEDED`: over a single, daily, or per-end-user daily cap. The message names which; split it or ask us to raise the cap. `PAYOUT_REFUSED`: this payout cannot be sent to this recipient; do not retry, contact us with the `requestId`.
- `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`.

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