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

# How-to: Send a stablecoin payout

> Send USDC or EURC onchain to a third-party recipient with the Stablecoin Payouts API. Covers the Circle LLC (US) flow and the Circle Singapore (CIRCLE_SG) flow.

Use the Stablecoin Payouts API to send USDC or EURC onchain to a third-party
recipient, such as vendors, contractors, or customers. The flow differs by
Circle entity: Circle LLC (US) applies Travel Rule data at a \$3,000
USD-equivalent threshold, while Circle Singapore (CIRCLE\_SG) requires
beneficiary identity, wallet ownership, and a payment reason code on every
payout. This page documents both. For the underlying model, see
[How stablecoin payins and payouts work](/circle-mint/concepts/stablecoin-payins-and-payouts).

<Tip>
  Stablecoin Payouts are for third-party recipients (wallets your business does
  not own or control). To move funds between wallets your business owns, see
  [Transfer Onchain](/circle-mint/howtos/transfer-on-chain).
</Tip>

## Prerequisites

Before you begin:

* Stablecoin Payouts is enabled on your Circle Mint account. The product is
  available through Circle LLC (US) and Circle Singapore (CIRCLE\_SG). To request
  activation, [contact Circle Mint](https://www.circle.com/mint-contact).
* A Circle Mint sandbox API key. See
  [Get started with Circle Mint](/circle-mint/quickstarts/getting-started).
* A source wallet ID (`source.id`) with funds available for payouts.
* For CIRCLE\_SG only: the Virtual Asset Service Provider (VASP) that holds the
  recipient's wallet, when the wallet is hosted.
* The destination address is on a blockchain supported by the Stablecoin Payouts
  API. See
  [Supported chains and currencies](/circle-mint/references/supported-chains-and-currencies).

<Note>
  For XRP destinations (`chain: "XRP"`), the Stablecoin Payouts API supports only
  the classic-address format (for example, `rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY`).
  The x-address format is not supported. Use the `addressTag` field to specify the
  destination tag.
</Note>

## Steps

<Tabs>
  <Tab title="Circle LLC (US)">
    ### Step 1. Register the recipient

    Add the recipient to your address book with `POST /v1/addressBook/recipients`.
    Provide `idempotencyKey`, `chain`, and `address`. The `metadata` fields
    (`nickname`, `email`, `bns`) are optional.

    ```bash theme={null}
    curl -X POST https://api-sandbox.circle.com/v1/addressBook/recipients \
      -H "Authorization: Bearer $API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "idempotencyKey": "9352ec9e-5ee6-441f-ab42-186bc71fbdde",
        "chain": "BASE",
        "address": "0x65BFCf1a6289a0b77b4D3F7d12005a05949FD8C3",
        "metadata": {
          "nickname": "Acme Corp payout address",
          "email": "ap@acme.example",
          "bns": "acme.base.eth"
        }
      }'
    ```

    ```json theme={null}
    {
      "data": {
        "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1",
        "chain": "BASE",
        "address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
        "metadata": {
          "nickname": "Acme Corp payout address",
          "email": "ap@acme.example",
          "bns": "acme.base.eth"
        },
        "status": "pending",
        "createDate": "2026-05-01T14:16:34.985353Z",
        "updateDate": "2026-05-01T14:16:34.985353Z"
      }
    }
    ```

    The recipient transitions out of `pending` according to your Mint Console
    **Delayed withdrawals** setting. When delayed withdrawals are on, new recipients
    stay `inactive` for 24 hours before becoming `active`. When delayed withdrawals
    are off, recipients become `active` in seconds.

    #### Step 1.1. Wait for active status

    The recipient must be `active` before you submit a payout.

    <Tabs>
      <Tab title="Webhook">
        Subscribe to `addressBookRecipients` notifications. Circle sends an event when
        the recipient is created and when its status changes.

        ```json theme={null}
        {
          "clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802",
          "notificationType": "addressBookRecipients",
          "version": 1,
          "addressBookRecipient": {
            "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1",
            "chain": "BASE",
            "address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
            "status": "active",
            "createDate": "2026-05-01T14:16:34.985353Z",
            "updateDate": "2026-05-01T14:18:02.123456Z"
          }
        }
        ```
      </Tab>

      <Tab title="Polling">
        Call `GET /v1/addressBook/recipients/{id}` on an interval until `status` is
        `active`.

        ```bash theme={null}
        curl https://api-sandbox.circle.com/v1/addressBook/recipients/dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1 \
          -H "Authorization: Bearer $API_KEY"
        ```

        ```json theme={null}
        {
          "data": {
            "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1",
            "chain": "BASE",
            "address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
            "status": "active",
            "createDate": "2026-05-01T14:16:34.985353Z",
            "updateDate": "2026-05-01T14:18:02.123456Z"
          }
        }
        ```
      </Tab>
    </Tabs>

    ### Step 2. Send the payout

    Call `POST /v1/payouts` with the source wallet, the recipient `id` as the
    destination, and the amounts.

    <Warning>
      Travel Rule applies to payouts of \$3,000 USD-equivalent or more. Include
      `source.identities[]` to describe the originator (your organization or your end
      customer). See
      [Travel Rule compliance](/circle-mint/references/travel-rule-compliance) for the
      schema and failure modes.
    </Warning>

    <Tabs>
      <Tab title="Below threshold">
        ```bash theme={null}
        curl -X POST https://api-sandbox.circle.com/v1/payouts \
          -H "Authorization: Bearer $API_KEY" \
          -H "Content-Type: application/json" \
          -d '{
            "idempotencyKey": "ba943ff1-ca16-49b2-ba55-1057e70ca5c7",
            "source": {
              "type": "wallet",
              "id": "12345"
            },
            "destination": {
              "type": "address_book",
              "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1"
            },
            "amount": {
              "amount": "500.00",
              "currency": "USD"
            },
            "toAmount": {
              "currency": "USD"
            }
          }'
        ```
      </Tab>

      <Tab title="At or above threshold">
        ```bash theme={null}
        curl -X POST https://api-sandbox.circle.com/v1/payouts \
          -H "Authorization: Bearer $API_KEY" \
          -H "Content-Type: application/json" \
          -d @body.json
        ```

        ```json theme={null}
        {
          "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-a5be9c7ecbe1"
          },
          "amount": {
            "amount": "3000.14",
            "currency": "USD"
          },
          "toAmount": {
            "currency": "USD"
          }
        }
        ```
      </Tab>
    </Tabs>

    ```json theme={null}
    {
      "data": {
        "id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
        "sourceWalletId": "12345",
        "destination": {
          "type": "address_book",
          "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1"
        },
        "amount": {
          "amount": "3000.14",
          "currency": "USD"
        },
        "toAmount": {
          "amount": "3000.14",
          "currency": "USD"
        },
        "status": "pending",
        "createDate": "2026-05-01T14:20:30.000Z",
        "updateDate": "2026-05-01T14:20:30.000Z"
      }
    }
    ```

    ### Step 3. Confirm completion

    Wait for the payout to reach `status: complete`.

    <Tabs>
      <Tab title="Webhook">
        Subscribe to `payouts` notifications. The payload includes the payout under the
        `payout` key.

        ```json theme={null}
        {
          "clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802",
          "notificationType": "payouts",
          "version": 1,
          "payout": {
            "id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
            "sourceWalletId": "12345",
            "destination": {
              "type": "address_book",
              "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1"
            },
            "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": "2026-05-01T14:20:30.000Z",
            "updateDate": "2026-05-01T14:21:12.000Z"
          }
        }
        ```
      </Tab>

      <Tab title="Polling">
        Call `GET /v1/payouts/{id}` on an interval until `status` is `complete`.

        ```bash theme={null}
        curl https://api-sandbox.circle.com/v1/payouts/b8627ae8-732b-4d25-b947-1df8f4007a29 \
          -H "Authorization: Bearer $API_KEY"
        ```

        ```json theme={null}
        {
          "data": {
            "id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
            "sourceWalletId": "12345",
            "destination": {
              "type": "address_book",
              "id": "dff5fcb3-2e52-5c13-8a66-a5be9c7ecbe1"
            },
            "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": "2026-05-01T14:20:30.000Z",
            "updateDate": "2026-05-01T14:21:12.000Z"
          }
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Circle Singapore">
    The CIRCLE\_SG flow has additional requirements: beneficiary `identity` and
    `ownership` on the recipient, `purposeOfTransfer` on the payout, and Travel Rule
    applies to payouts of all amounts.

    ### Step 1. Look up the recipient's VASP

    For hosted-wallet recipients, you need the `vaspId` of the Virtual Asset Service
    Provider (VASP) that holds the wallet. Call `GET /v1/addressBook/vasps` to list
    the VASP records active in your jurisdiction. This endpoint is available only to
    CIRCLE\_SG customers.

    ```bash theme={null}
    curl https://api-sandbox.circle.com/v1/addressBook/vasps \
      -H "Authorization: Bearer $API_KEY"
    ```

    ```json theme={null}
    {
      "data": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "name": "Anchorage Digital"
        },
        {
          "id": "661f9511-f30c-52e5-b660-709766551111",
          "name": "Coinhako"
        },
        {
          "id": "772a0622-041d-63f6-c771-810877662222",
          "name": "Paxos"
        }
      ]
    }
    ```

    If the recipient self-custodies, self-hosted wallets are not yet supported on
    the CIRCLE\_SG flow. The recipient must hold the destination wallet at a listed
    VASP.

    ### Step 2. Register the recipient with identity and ownership

    Call `POST /v1/addressBook/recipients` with `chain`, `address`, `identity`, and
    `ownership`. Use the request body that matches the recipient type.

    <Tabs>
      <Tab title="Individual recipient">
        ```bash theme={null}
        curl -X POST https://api-sandbox.circle.com/v1/addressBook/recipients \
          -H "Authorization: Bearer $API_KEY" \
          -H "Content-Type: application/json" \
          -d @body.json
        ```

        ```json theme={null}
        {
          "idempotencyKey": "9352ec9e-5ee6-441f-ab42-186bc71fbdde",
          "chain": "BASE",
          "address": "0x65BFCf1a6289a0b77b4D3F7d12005a05949FD8C3",
          "metadata": {
            "nickname": "Ada Lovelace"
          },
          "identity": {
            "type": "individual",
            "firstName": "Ada",
            "lastName": "Lovelace"
          },
          "ownership": {
            "type": "third_party",
            "custody": {
              "type": "hosted",
              "vaspId": "550e8400-e29b-41d4-a716-446655440000"
            }
          }
        }
        ```
      </Tab>

      <Tab title="Business recipient">
        ```bash theme={null}
        curl -X POST https://api-sandbox.circle.com/v1/addressBook/recipients \
          -H "Authorization: Bearer $API_KEY" \
          -H "Content-Type: application/json" \
          -d @body.json
        ```

        ```json theme={null}
        {
          "idempotencyKey": "9352ec9e-5ee6-441f-ab42-186bc71fbdde",
          "chain": "BASE",
          "address": "0x65BFCf1a6289a0b77b4D3F7d12005a05949FD8C3",
          "metadata": {
            "nickname": "Acme Corp payout address"
          },
          "identity": {
            "type": "business",
            "businessName": "Acme Corp"
          },
          "ownership": {
            "type": "third_party",
            "custody": {
              "type": "hosted",
              "vaspId": "550e8400-e29b-41d4-a716-446655440000"
            }
          }
        }
        ```
      </Tab>
    </Tabs>

    ```json theme={null}
    {
      "data": {
        "id": "8755d0ea-14f9-4259-b092-de23c14b6568",
        "chain": "BASE",
        "address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
        "metadata": {
          "nickname": "Ada Lovelace"
        },
        "status": "pending",
        "identity": {
          "type": "individual",
          "firstName": "Ada",
          "lastName": "Lovelace"
        },
        "ownership": {
          "type": "third_party",
          "custody": {
            "type": "hosted",
            "vaspId": "550e8400-e29b-41d4-a716-446655440000"
          }
        },
        "createDate": "2026-05-01T14:16:34.985353Z",
        "updateDate": "2026-05-01T14:16:34.985353Z"
      }
    }
    ```

    The recipient transitions from `pending` to `active` after risk review.

    <Note>
      You cannot modify `identity` (error `2036`) or `ownership` (error `2037`) on an
      existing recipient through PATCH. To change either, register a new recipient.
    </Note>

    #### Step 2.1. Wait for active status

    Wait for the recipient `status` to become `active`.

    <Tabs>
      <Tab title="Webhook">
        Subscribe to `addressBookRecipients` notifications. Circle sends an event when
        the recipient is created and when its status changes.

        ```json theme={null}
        {
          "clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802",
          "notificationType": "addressBookRecipients",
          "version": 1,
          "addressBookRecipient": {
            "id": "8755d0ea-14f9-4259-b092-de23c14b6568",
            "chain": "BASE",
            "address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
            "status": "active",
            "identity": {
              "type": "individual",
              "firstName": "Ada",
              "lastName": "Lovelace"
            },
            "ownership": {
              "type": "third_party",
              "custody": {
                "type": "hosted",
                "vaspId": "550e8400-e29b-41d4-a716-446655440000"
              }
            },
            "createDate": "2026-05-01T14:16:34.985353Z",
            "updateDate": "2026-05-01T14:18:02.123456Z"
          }
        }
        ```
      </Tab>

      <Tab title="Polling">
        Call `GET /v1/addressBook/recipients/{id}` on an interval until `status` is
        `active`.

        ```bash theme={null}
        curl https://api-sandbox.circle.com/v1/addressBook/recipients/8755d0ea-14f9-4259-b092-de23c14b6568 \
          -H "Authorization: Bearer $API_KEY"
        ```

        ```json theme={null}
        {
          "data": {
            "id": "8755d0ea-14f9-4259-b092-de23c14b6568",
            "chain": "BASE",
            "address": "0x65bfcf1a6289a0b77b4d3f7d12005a05949fd8c3",
            "status": "active",
            "identity": {
              "type": "individual",
              "firstName": "Ada",
              "lastName": "Lovelace"
            },
            "ownership": {
              "type": "third_party",
              "custody": {
                "type": "hosted",
                "vaspId": "550e8400-e29b-41d4-a716-446655440000"
              }
            },
            "createDate": "2026-05-01T14:16:34.985353Z",
            "updateDate": "2026-05-01T14:18:02.123456Z"
          }
        }
        ```
      </Tab>
    </Tabs>

    ### Step 3. Send the payout

    Call `POST /v1/payouts` with the originator `identities`, the destination, the
    amounts, and `purposeOfTransfer`. Travel Rule applies on every CIRCLE\_SG payout
    regardless of amount, so `source.identities[]` is always required.
    `purposeOfTransfer` is one of `PMT000` to `PMT030` except `PMT006`. See
    [payment reason codes](/circle-mint/references/travel-rule-compliance#payment-reason-codes).

    ```bash theme={null}
    curl -X POST https://api-sandbox.circle.com/v1/payouts \
      -H "Authorization: Bearer $API_KEY" \
      -H "Content-Type: application/json" \
      -d @body.json
    ```

    ```json theme={null}
    {
      "idempotencyKey": "ba943ff1-ca16-49b2-ba55-1057e70ca5c7",
      "source": {
        "type": "wallet",
        "id": "12345",
        "identities": [
          {
            "type": "business",
            "name": "Example Pte. Ltd.",
            "addresses": [
              {
                "line1": "1 Raffles Place",
                "line2": "#20-01",
                "city": "Singapore",
                "district": "Singapore",
                "postalCode": "048616",
                "country": "SG"
              }
            ]
          }
        ]
      },
      "destination": {
        "type": "address_book",
        "id": "8755d0ea-14f9-4259-b092-de23c14b6568"
      },
      "amount": {
        "amount": "500.00",
        "currency": "USD"
      },
      "toAmount": {
        "currency": "USD"
      },
      "purposeOfTransfer": "PMT001"
    }
    ```

    ```json theme={null}
    {
      "data": {
        "id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
        "sourceWalletId": "12345",
        "destination": {
          "type": "address_book",
          "id": "8755d0ea-14f9-4259-b092-de23c14b6568"
        },
        "amount": {
          "amount": "500.00",
          "currency": "USD"
        },
        "toAmount": {
          "amount": "500.00",
          "currency": "USD"
        },
        "purposeOfTransfer": "PMT001",
        "status": "pending",
        "createDate": "2026-05-01T14:20:30.000Z",
        "updateDate": "2026-05-01T14:20:30.000Z"
      }
    }
    ```

    ### Step 4. Confirm completion

    Wait for the payout to reach `status: complete`.

    <Tabs>
      <Tab title="Webhook">
        Subscribe to `payouts` notifications. The payload includes the payout under the
        `payout` key.

        ```json theme={null}
        {
          "clientId": "a03a47ff-b0eb-4070-b3df-dc66752cc802",
          "notificationType": "payouts",
          "version": 1,
          "payout": {
            "id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
            "sourceWalletId": "12345",
            "destination": {
              "type": "address_book",
              "id": "8755d0ea-14f9-4259-b092-de23c14b6568"
            },
            "amount": {
              "amount": "500.00",
              "currency": "USD"
            },
            "toAmount": {
              "amount": "500.00",
              "currency": "USD"
            },
            "fees": {
              "amount": "0.00",
              "currency": "USD"
            },
            "networkFees": {
              "amount": "0.30",
              "currency": "USD"
            },
            "purposeOfTransfer": "PMT001",
            "status": "complete",
            "createDate": "2026-05-01T14:20:30.000Z",
            "updateDate": "2026-05-01T14:21:12.000Z"
          }
        }
        ```
      </Tab>

      <Tab title="Polling">
        Call `GET /v1/payouts/{id}` on an interval until `status` is `complete`.

        ```bash theme={null}
        curl https://api-sandbox.circle.com/v1/payouts/b8627ae8-732b-4d25-b947-1df8f4007a29 \
          -H "Authorization: Bearer $API_KEY"
        ```

        ```json theme={null}
        {
          "data": {
            "id": "b8627ae8-732b-4d25-b947-1df8f4007a29",
            "sourceWalletId": "12345",
            "destination": {
              "type": "address_book",
              "id": "8755d0ea-14f9-4259-b092-de23c14b6568"
            },
            "amount": {
              "amount": "500.00",
              "currency": "USD"
            },
            "toAmount": {
              "amount": "500.00",
              "currency": "USD"
            },
            "fees": {
              "amount": "0.00",
              "currency": "USD"
            },
            "networkFees": {
              "amount": "0.30",
              "currency": "USD"
            },
            "purposeOfTransfer": "PMT001",
            "status": "complete",
            "createDate": "2026-05-01T14:20:30.000Z",
            "updateDate": "2026-05-01T14:21:12.000Z"
          }
        }
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

## Failure modes

Failures fall into two categories. Synchronous validation errors return HTTP
4xx, so you fix the request body and retry. Asynchronous risk evaluation accepts
the request with HTTP 201, then transitions the payout to `status: failed`.
Resubmit with a new `idempotencyKey` after correcting the underlying data.

| Code                 | Type                   | Cause                                                                                                                                                                     | Resolution                                                                                                                                                                                  |
| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transaction_denied` | Asynchronous           | Travel Rule data is missing or invalid. The response carries `riskEvaluation.decision: denied` and `riskEvaluation.reason: 3220`.                                         | Review `source.identities`, the recipient's `identity` and `ownership` (CIRCLE\_SG), the `vaspId` (CIRCLE\_SG), and `purposeOfTransfer` (CIRCLE\_SG). Resubmit with a new `idempotencyKey`. |
| `insufficient_funds` | Asynchronous           | The source wallet does not have enough balance for `amount` plus fees.                                                                                                    | Fund the source wallet, then resubmit with a new `idempotencyKey`.                                                                                                                          |
| `5020`               | Synchronous (HTTP 400) | `purposeOfTransfer` is missing or invalid on a CIRCLE\_SG payout.                                                                                                         | Provide a valid `PMT` code other than `PMT006`.                                                                                                                                             |
| `2024` to `2037`     | Synchronous (HTTP 400) | Address Book validation failures on CIRCLE\_SG: missing `identity`, missing `ownership`, missing or disallowed `vaspId`, or PATCH attempted on `identity` or `ownership`. | Add the missing or corrected field on the initial create call. For `2036` and `2037` PATCH errors, register a new recipient instead.                                                        |

See [Travel Rule compliance](/circle-mint/references/travel-rule-compliance) for
schema details and [API errors](/circle-mint/references/error-codes) for the
full error code reference.

## See also

* [How stablecoin payins and payouts work](/circle-mint/concepts/stablecoin-payins-and-payouts):
  conceptual overview of the payin and payout flows.
* [Travel Rule compliance](/circle-mint/references/travel-rule-compliance):
  identity, ownership, VASP, and payment-reason-code schemas.
* [Supported chains and currencies](/circle-mint/references/supported-chains-and-currencies):
  blockchains and currencies available through Stablecoin Payouts.
* [Transfer Onchain](/circle-mint/howtos/transfer-on-chain): first-party
  transfers between wallets your business owns through the Core API.
