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.
- (Optional) Set up a webhook endpoint to receive beneficiary and payout events. See Set up a webhook endpoint.
Step 1: Discover a corridor (optional)
CallGET /v1/beneficiaries/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.
MX / MXN / SPEI / INDIVIDUAL.
Step 2: Get field requirements
Each corridor needs a different set of fields to register a beneficiary. CallGET /v1/beneficiaries/requirements
with the corridor parameters.
bankAccount: fields that don’t start withBENEFICIARY_, such asCLABE.travelRule: fields that start withBENEFICIARY_, such asBENEFICIARY_NAMEandBENEFICIARY_ADDRESS.
Step 3: Register a beneficiary
Send the collected fields toPOST /v1/beneficiaries.
Use a stable idempotencyKey so retries don’t create duplicate records.
id. You use it as the destination.id in step 6. To
list, delete, or recover beneficiaries, see
Manage fiat beneficiaries.
Step 4: Wait for the beneficiary to become active
The beneficiary starts asINACTIVE 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.
- Webhook
- Polling
Subscribe to the
The beneficiary is in
payouts.beneficiary.updated
webhook event. When screening finishes, you receive a notification with status
set to ACTIVE or DENIED:notification. Use updateDate to keep the latest
status.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. CallPOST /v1/payouts/quotes
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.
Quotes expire at
expiresAt. If a quote expires, request a new one.id. You use it as the quoteId in step 6.
Step 6: Send the payout
Create the payout withPOST /v1/payouts.
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, and
customerRefId to your own reference for the payout.
pending.
Step 7: Confirm the payout completed
Track the payout with themint.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.