Use the Crypto Payouts API to send onchain USDC or EURC
stablecoin payouts from
Circle Mint to third-party blockchain addresses. You create a recipient, wait
until it is active, create a payout, then confirm completion using the API or
webhooks. The examples in this quickstart use Ethereum, but you can use any
supported blockchain.
Stablecoin payouts are for transferring funds to third-party recipients such as
vendors, contractors, remittances, or customers. If you want to transfer funds
to a wallet your business owns or controls, see the
Transfer to Your Own Wallet
quickstart.
Prerequisites
Before you begin this tutorial, ensure you’ve:
- Obtained a Circle Mint sandbox API key with access to
the Crypto Payouts API (stablecoin payouts).
- Obtained a source wallet ID (
source.id) with funds available for payouts.
- Installed cURL for API calls.
- (Optional) Configured
webhook notifications.
Step 1: Create an address book recipient
Add a recipient in your Mint address book before any payout. If delayed
withdrawals are on in the Circle Mint console, new recipients stay inactive
for 24 hours before they become active. If delayed withdrawals are off,
recipients become active within seconds.
Toggle delayed withdrawals under your Mint account settings in the Circle
Mint console.
1.1. Create a recipient
Call
Create address book recipient.
Expected result: a recipient id (status may be pending until active).
Example request:
curl --location --request POST 'https://api-sandbox.circle.com/v1/addressBook/recipients' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data-raw '{
"idempotencyKey": "9352ec9e-5ee6-441f-ab42-186bc71fbdde",
"chain": "ETH",
"address": "0x65BFCf1a6289a0b77b4D3F7d12005a05949FD8C3",
"metadata": {
"email": "satoshi@circle.com",
"bns": "testbns",
"nickname": "test nickname desc"
}
}'
Example response:
{
"data": {
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe",
"chain": "ETH",
"address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
"metadata": {
"nickname": "test nickname desc",
"email": "satoshi@circle.com",
"bns": "testbns"
},
"status": "pending",
"updateDate": "2022-09-22T14:16:34.985353Z",
"createDate": "2022-09-22T14:16:34.985353Z"
}
}
1.2. Confirm recipient status
The recipient must be active before you create a payout. Use webhooks or poll
Get address book recipient.
If delayed withdrawals are on, wait until status moves from inactive to
active.
Expected result: status is active.
After you
subscribe to notifications
for addressBookRecipients, Circle sends updates when a recipient is created or
its status changes.Example addressBookRecipients notification when the recipient becomes active:{
"clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802",
"notificationType": "addressBookRecipients",
"version": 1,
"customAttributes": {
"clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802"
},
"addressBookRecipient": {
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe",
"chain": "ETH",
"address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
"metadata": {
"nickname": "test nickname desc",
"email": "satoshi@circle.com",
"bns": "testbns"
},
"status": "active",
"updateDate": "2022-09-22T14:16:34.985353Z",
"createDate": "2022-09-22T14:16:34.985353Z"
}
}
Call the
Get address book recipient
endpoint on an interval until the recipient status is active.Example request: (use the id from the
create recipient response)curl --location --request GET 'https://api-sandbox.circle.com/v1/addressBook/recipients/dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'
Example response when the recipient is active:{
"data": {
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe",
"chain": "ETH",
"address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
"metadata": {
"nickname": "test nickname desc",
"email": "satoshi@circle.com",
"bns": "testbns"
},
"status": "active",
"updateDate": "2022-09-22T14:16:34.985353Z",
"createDate": "2022-09-22T14:16:34.985353Z"
}
}
Do not continue until the recipient status is active.
Step 2: Create a payout
Call Create payout with the
recipient id from Create a recipient, your source
wallet, and amounts. If toAmount.currency is omitted, amount.currency is
used as the receiving currency.
Expected result: a payout id with status pending.
source.identities is required for payouts of 3,000 USD or more. It describes
the sender (your organization) for FinCEN
Travel Rule compliance.
Example request:
curl --location --request POST 'https://api-sandbox.circle.com/v1/payouts' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data-raw '{
"idempotencyKey": "ba943ff1-ca16-49b2-ba55-1057e70ca5c7",
"source": {
"type": "wallet",
"id": "12345",
"identities": [
{
"type": "individual",
"name": "Satoshi Nakamoto",
"addresses": [
{
"line1": "100 Money Street",
"line2": "Suite 1",
"city": "Boston",
"district": "MA",
"postalCode": "01234",
"country": "US"
}
]
}
]
},
"destination": {
"type": "address_book",
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe"
},
"amount": {
"amount": "3000.14",
"currency": "USD"
},
"toAmount": {
"currency": "USD"
}
}'
Example response:
{
"data": {
"id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
"sourceWalletId": "12345",
"destination": {
"type": "address_book",
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe"
},
"amount": {
"amount": "3000.14",
"currency": "USD"
},
"toAmount": {
"amount": "3000.14",
"currency": "USD"
},
"status": "pending",
"updateDate": "2020-04-10T02:13:30.000Z",
"createDate": "2020-04-10T02:13:30.000Z"
}
}
If Get payout later returns
status failed, check the payload for an errorCode and related fields (for
example insufficient balance or an invalid recipient). Retry only after you fix
the underlying issue.
Step 3: Confirm payout completion
Confirm the payout using webhooks or by polling
Get payout.
Expected result: status is complete when funds are sent and delivered
onchain.
Subscribe to payout notifications to receive updates as status changes. Each
message includes the payout object with the latest status.Example payout notification when the status is complete:{
"clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802",
"notificationType": "payout",
"version": 1,
"customAttributes": {
"clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802"
},
"payout": {
"id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
"sourceWalletId": "12345",
"destination": {
"type": "address_book",
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe"
},
"amount": {
"amount": "3000.14",
"currency": "USD"
},
"toAmount": {
"amount": "3000.14",
"currency": "USD"
},
"fees": {
"amount": "0.00",
"currency": "USD"
},
"networkFees": {
"amount": "0.30",
"currency": "USD"
},
"status": "complete",
"createDate": "2020-04-10T02:13:30.000Z",
"updateDate": "2020-04-10T02:13:30.000Z"
}
}
Call the Get payout endpoint on
an interval until status is complete.Example request: (use the payout id from the
create payout response)curl --location --request GET 'https://api-sandbox.circle.com/v1/payouts/b8627ae8-732b-4d25-b947-1df8f4007a29' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'
Example response when the payout is complete:{
"data": {
"id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
"sourceWalletId": "12345",
"destination": {
"type": "address_book",
"id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe"
},
"amount": {
"amount": "3000.14",
"currency": "USD"
},
"toAmount": {
"amount": "3000.14",
"currency": "USD"
},
"fees": {
"amount": "0.00",
"currency": "USD"
},
"networkFees": {
"amount": "0.30",
"currency": "USD"
},
"status": "complete",
"createDate": "2020-04-10T02:13:30.000Z",
"updateDate": "2020-04-10T02:13:30.000Z"
}
}