This tutorial shows how to send a stablecoin payout from Circle Mint using the
Crypto Payouts API. The examples 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, ensure that you’ve:
- Obtained a Circle Mint sandbox API key with access to the Stablecoin Payouts
- Obtained a Circle Mint sandbox API key with access to the Crypto Payouts API.
- 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
Create a recipient in your Mint address book before any payout. New recipients
can be active immediately or inactive for 24 hours, depending on your Mint
settings.
You can turn on delayed withdrawals in the Circle Mint console. When it is on,
new address book entries are inactive for the first 24 hours and you cannot send
a payout to them during that window. When it is off, new addresses are available
for payouts immediately after they are active.
1.1. Create a recipient
Call the
Create address book recipient
endpoint:
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
Before you create a payout, the recipient must be active. You cannot pay out
to an inactive recipient. Use webhook notifications or continuous polling to
confirm status. If delayed withdrawals are on, wait until status moves from
inactive to 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 the Create payout
endpoint with the recipient id (from when you
created the recipient), your source wallet, and
amounts. If toAmount.currency is omitted, amount.currency is used as the
receiving currency.
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 to create a payout:
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"
}
}
Step 3: Confirm payout completion
The payout is complete when the funds are sent and delivered onchain. Confirm
the payout status using webhook notifications or continuous polling.
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"
}
}