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

> ## Agent Instructions
> Before reading these docs, install the relevant Circle Skill to get pre-loaded context — skills are LLM-optimized and cover architecture decisions, correct flows, and common pitfalls. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills. Available skills: use-usdc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md (balances, transfers, approvals on EVM and Solana); EURC has no skill — see https://developers.circle.com/stablecoins/what-is-eurc.md; bridge-stablecoin https://github.com/circlefin/skills/blob/master/plugins/circle/skills/bridge-stablecoin/SKILL.md (crosschain transfers via CCTP, USDC, EURC, and third-party assets); use-arc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md (Arc chain config, contract deployment, USDC bridging — Arc docs: https://docs.arc.io/llms.txt); use-circle-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md (choose wallet type); use-developer-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md (custodial wallets for payouts and treasury); use-user-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md (embedded wallets with Web2 login); use-modular-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md (smart contract wallets with passkeys and ERC-4337); use-gateway https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md (unified USDC balance, nanopayments); use-smart-contract-platform https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md (deploy, interact, monitor contracts). Pair any skill with the Circle MCP server for live SDK signatures, contract addresses, and chain IDs: {"mcpServers":{"circle":{"url":"https://api.circle.com/v1/codegen/mcp"}}}.
> Read the product overview first. Each product has an overview explaining when and why to use it. Read it before quickstarts.
> Pick the right wallet type. Developer-controlled (you hold keys), user-controlled (end user holds keys via PIN/social login), or modular (smart contract wallets with passkeys). See https://developers.circle.com/wallets.md.
> Use CCTP V2 for crosschain transfers. CCTP natively transfers USDC and EURC via burn-and-mint, and supports permissionless wrapping of third-party assets via lock-and-mint. V1 is legacy; always use V2 unless V1 is specified or the chain requires it (Noble, Sui, and Aptos still require V1). Migration guide: https://developers.circle.com/cctp/migration-from-v1-to-v2.md.
> Use Bridge Kit for frontend bridging. Wraps CCTP with a simpler SDK for user-facing apps. Use CCTP directly for backend transfers.
> Gas Station vs Paymaster. Gas Station sponsors gas for Circle Wallet transactions. Paymaster lets users pay gas in USDC. Different use cases — read both overviews.
> Gateway Nanopayments for sub-cent payments. Gasless USDC micropayments down to $0.000001 via x402 and batched settlement. For pay-per-request APIs, AI agent payments, streaming.
> Look up USDC addresses per chain. Never hardcode — use https://developers.circle.com/stablecoins/usdc-contract-addresses.md.
> Prefer SDKs over raw API calls. Node.js and Python SDKs handle auth, retries, and errors.
> API key required. Bearer token in Authorization header. Testnet and mainnet use separate keys and may use different base URLs depending on the product.
> Set up webhooks when available. Most operations are async. Webhooks deliver transaction confirmations and state changes.
> When calling list endpoints, paginate using pageSize and pageAfter until no nextPageAfter cursor is returned—stopping at the first page silently misses records.
> Building an AI agent? Start with the Agent Stack—Circle CLI, agent wallets, and nanopayments built for autonomous use cases: https://developers.circle.com/agent-stack.md.

# Quickstart: Send fiat payouts

> Discover a supported payout corridor, register a fiat beneficiary, request a quote, and initiate a local-currency payout.

Send local currency to a recipient's bank account, funded by the USDC in your
Managed Payments account. Circle acts as the Originating Financial Institution
(OFI) on the Circle Payments Network (CPN), which routes the payout to a
Beneficiary Financial Institution (BFI) that delivers the local fiat.

This quickstart pays an individual in Mexico over SPEI, Mexico's interbank
payment system. The same steps apply to every corridor.

## Prerequisites

Before you begin, ensure that you've:

* Completed Managed Payments onboarding with fiat payout permissions enabled on
  your account.
* Funded your Managed Payments account with enough USDC to cover the payout
  amount and fees.
* Created an API key with Managed Payments access from the
  [Circle hub](https://hub.circle.com).
* (Optional) Set up a webhook endpoint to receive beneficiary and payout events.
  See
  [Set up a webhook endpoint](https://developers.circle.com/api-reference/webhook-endpoints.md#v2-notifications).

## Step 1: Discover a corridor (optional)

Call
[`GET /v1/beneficiaries/corridors`](https://developers.circle.com/api-reference/cpn/managed-payments/fiat-payouts/list-beneficiary-corridors)
to list the corridors available on your account. Each one is a combination of
destination country, currency, payment method, and customer type. If you already
know which corridor you need, skip to step 2.

```bash theme={null}
curl -X GET "https://api-sandbox.circle.com/v1/beneficiaries/corridors" \
  --header "Authorization: Bearer $API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "destinationCountry": "MX",
      "destinationCurrency": "MXN",
      "paymentMethod": "SPEI",
      "customerTypes": ["INDIVIDUAL", "BUSINESS"]
    }
  ]
}
```

The response has one entry for each corridor. This example shows only the one
the rest of this quickstart uses: `MX` / `MXN` / `SPEI` / `INDIVIDUAL`.

## Step 2: Get field requirements

Each corridor needs a different set of fields to register a beneficiary. Call
[`GET /v1/beneficiaries/requirements`](https://developers.circle.com/api-reference/cpn/managed-payments/fiat-payouts/get-beneficiary-requirements)
with the corridor parameters.

```bash theme={null}
curl -X GET "https://api-sandbox.circle.com/v1/beneficiaries/requirements?destinationCountry=MX&destinationCurrency=MXN&paymentMethod=SPEI&customerType=INDIVIDUAL" \
  --header "Authorization: Bearer $API_KEY"
```

```json expandable theme={null}
{
  "data": {
    "fields": [
      {
        "name": "CLABE",
        "type": "TEXT",
        "required": true,
        "pattern": "^[0-9]{18}$",
        "validationDetails": "18 digits."
      },
      {
        "name": "BENEFICIARY_NAME",
        "type": "TEXT",
        "required": true,
        "pattern": "^.{1,140}$"
      },
      {
        "name": "BENEFICIARY_ADDRESS",
        "type": "ADDRESS",
        "required": true,
        "fields": [
          { "name": "STREET", "type": "TEXT", "required": true },
          { "name": "CITY", "type": "TEXT", "required": true },
          { "name": "STATE_PROVINCE", "type": "TEXT", "required": false },
          { "name": "POSTAL_CODE", "type": "TEXT", "required": true },
          { "name": "COUNTRY", "type": "TEXT", "required": true }
        ]
      }
    ]
  }
}
```

In the next step, you send these fields in two objects, split by field name:

* `bankAccount`: fields that don't start with `BENEFICIARY_`, such as `CLABE`.
* `travelRule`: fields that start with `BENEFICIARY_`, such as
  `BENEFICIARY_NAME` and `BENEFICIARY_ADDRESS`.

## Step 3: Register a beneficiary

Send the collected fields to
[`POST /v1/beneficiaries`](https://developers.circle.com/api-reference/cpn/managed-payments/fiat-payouts/create-beneficiary).
Use a stable `idempotencyKey` so retries don't create duplicate records.

```bash expandable theme={null}
curl -X POST "https://api-sandbox.circle.com/v1/beneficiaries" \
  --header "Authorization: Bearer $API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "idempotencyKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "customerType": "INDIVIDUAL",
    "destinationCountry": "MX",
    "destinationCurrency": "MXN",
    "paymentMethod": "SPEI",
    "bankAccount": {
      "CLABE": "012345678901234567"
    },
    "travelRule": {
      "BENEFICIARY_NAME": "Alice Garcia",
      "BENEFICIARY_ADDRESS": {
        "STREET": "Av. Reforma 100",
        "CITY": "Ciudad de Mexico",
        "STATE_PROVINCE": "CDMX",
        "POSTAL_CODE": "06600",
        "COUNTRY": "MX"
      }
    }
  }'
```

```json theme={null}
{
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "INACTIVE",
    "customerType": "INDIVIDUAL",
    "destinationCountry": "MX",
    "destinationCurrency": "MXN",
    "paymentMethod": "SPEI"
  }
}
```

Save the beneficiary `id`. You use it as the `destination.id` in step 6. To
list, delete, or recover beneficiaries, see
[Manage fiat beneficiaries](https://developers.circle.com/cpn/managed-payments/howtos/manage-fiat-beneficiaries.md).

## Step 4: Wait for the beneficiary to become active

The beneficiary starts as `INACTIVE` while Circle screens it, and you can't send
a payout until it's `ACTIVE`. Use a webhook to get notified when screening
finishes, or poll if you can't receive webhooks, such as when testing without a
public endpoint.

> [tab] Webhook
>
> Subscribe to the
> [`payouts.beneficiary.updated`](https://developers.circle.com/api-reference/cpn/managed-payments/webhooks/payouts-beneficiary-updated)
> webhook event. When screening finishes, you receive a notification with `status`
> set to `ACTIVE` or `DENIED`:
>
> ```json expandable theme={null}
> {
>   "subscriptionId": "00000000-0000-4000-8000-000000000002",
>   "notificationId": "11111111-1111-4111-8111-111111111131",
>   "notificationType": "payouts.beneficiary.updated",
>   "notification": {
>     "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
>     "idempotencyKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
>     "customerType": "INDIVIDUAL",
>     "destinationCountry": "MX",
>     "destinationCurrency": "MXN",
>     "paymentMethod": "SPEI",
>     "status": "ACTIVE",
>     "riskDecision": "ACTIVE",
>     "riskScreenedDate": "2026-08-25T19:31:20.000Z",
>     "fieldManifest": "[\"BENEFICIARY_ADDRESS\",\"BENEFICIARY_NAME\",\"CLABE\"]",
>     "createDate": "2026-08-25T19:30:45.123Z",
>     "updateDate": "2026-08-25T19:31:20.000Z"
>   },
>   "timestamp": "2026-08-25T19:31:21.000000000Z",
>   "version": 2
> }
> ```
>
> The beneficiary is in `notification`. Use `updateDate` to keep the latest
> status.

> [tab] Polling
>
> Poll
> [`GET /v1/beneficiaries/{id}`](https://developers.circle.com/api-reference/cpn/managed-payments/fiat-payouts/get-beneficiary)
> until `status` changes.
>
> ```bash theme={null}
> curl -X GET "https://api-sandbox.circle.com/v1/beneficiaries/{id}" \
>   --header "Authorization: Bearer $API_KEY"
> ```
>
> ```json theme={null}
> {
>   "data": {
>     "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
>     "status": "ACTIVE",
>     "customerType": "INDIVIDUAL",
>     "destinationCountry": "MX",
>     "destinationCurrency": "MXN",
>     "paymentMethod": "SPEI"
>   }
> }
> ```

If the status is `DENIED`, screening rejected the beneficiary. Delete it and
register a new one.

## Step 5: Get a payout quote

A quote locks the exchange rate and fees for a payout. Call
[`POST /v1/payouts/quotes`](https://developers.circle.com/api-reference/cpn/managed-payments/fiat-payouts/create-payout-quote)
before you send the payout.

This example is an exact-in quote. You set the USDC amount in `from.amount`, and
the response shows the MXN amount your recipient receives after fees. For an
exact-out quote, set `to.amount` in MXN instead, and the response shows the USDC
amount debited.

The `useCase` field describes who is sending and who is receiving. `B2C` is a
business sending to an individual. The other values are `B2B`, `C2B`, and `C2C`.

```bash theme={null}
curl -X POST "https://api-sandbox.circle.com/v1/payouts/quotes" \
  --header "Authorization: Bearer $API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "useCase": "B2C",
    "from": {
      "currency": "USDC",
      "amount": "100.00"
    },
    "to": {
      "currency": "MXN",
      "country": "MX",
      "rail": "SPEI"
    }
  }'
```

```json expandable theme={null}
{
  "data": [
    {
      "id": "q1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "from": {
        "currency": "USDC",
        "amount": "100.00"
      },
      "to": {
        "currency": "MXN",
        "amount": "1975.50",
        "country": "MX",
        "rail": "SPEI"
      },
      "fees": [
        {
          "type": "FIAT_PAYOUT_FEE",
          "amount": "1.50",
          "currency": "USDC"
        }
      ],
      "expiresAt": "2026-09-10T16:05:00.000Z"
    }
  ]
}
```

> [!NOTE]
>
> Quotes expire at `expiresAt`. If a quote expires, request a new one.

Save the quote `id`. You use it as the `quoteId` in step 6.

## Step 6: Send the payout

Create the payout with
[`POST /v1/payouts`](https://developers.circle.com/api-reference/cpn/managed-payments/payouts/create-payout).
Set `destination.type` to `fiat_address_book`, `destination.id` to the
beneficiary `id` from step 3, and `quoteId` to the quote `id` from step 5. Set
`amount` to the quote's `from.amount`, `reasonForPayment` to a code from the
[payment reason codes](https://developers.circle.com/cpn/references/payments/payment-reason-codes.md), and
`customerRefId` to your own reference for the payout.

```bash theme={null}
curl -X POST "https://api-sandbox.circle.com/v1/payouts" \
  --header "Authorization: Bearer $API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "idempotencyKey": "p1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "destination": {
      "type": "fiat_address_book",
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    },
    "amount": {
      "amount": "100.00",
      "currency": "USDC"
    },
    "quoteId": "q1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "useCase": "B2C",
    "reasonForPayment": "PMT001",
    "customerRefId": "order-9876"
  }'
```

```json theme={null}
{
  "data": {
    "id": "p9b8c7d6-e5f4-3210-abcd-ef1234567890",
    "status": "pending",
    "amount": {
      "amount": "100.00",
      "currency": "USDC"
    }
  }
}
```

The payout starts as `pending`.

## Step 7: Confirm the payout completed

Track the payout with the
[`mint.payout`](https://developers.circle.com/api-reference/cpn/managed-payments/webhooks/mint-payout)
webhook event or by polling `GET /v1/payouts/{id}`. While the payout is in
progress, Circle sends `mint.payout` events with `status` still `pending`. The
final event has a `status` of `complete` or `failed`.

This example is the final event for a completed payout. When `status` is
`complete`, `toAmount` shows the fiat amount sent to the recipient.

```json expandable theme={null}
{
  "subscriptionId": "00000000-0000-4000-8000-000000000002",
  "notificationId": "11111111-1111-4111-8111-111111111111",
  "notificationType": "mint.payout",
  "notification": {
    "id": "p9b8c7d6-e5f4-3210-abcd-ef1234567890",
    "status": "complete",
    "destination": {
      "type": "fiat_address_book",
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    },
    "amount": {
      "amount": "100.00",
      "currency": "USDC"
    },
    "toAmount": {
      "amount": "1975.50",
      "currency": "MXN"
    },
    "createDate": "2026-09-10T16:01:00.000Z",
    "updateDate": "2026-09-10T16:02:30.000Z"
  },
  "timestamp": "2026-09-10T16:02:30.500000000Z",
  "version": 2
}
```
