Circle APIs Documentation

Learn how to integrate with Circle APIs to accept traditional and stablecoin payments, embed digital wallets into your product or service, or power your internet marketplace.

✨ Wire Payments Quickstart

Get started with the Circle Payments API and accept your first wire payment that settles in USDC in just a few minutes!

1. Get an API key

The Circle Payments API uses API keys as the mechanism to authenticate client requests. The API key must be set in the Authorization header of the request sent from your backend server. The format of the header is Bearer secret-key-value.

Learn more about authenticating API calls here.

To obtain an API key for the sandbox environment, simply create an account and generate a new key in settings - it only takes a few seconds.


Get an API key

Once you have generated your API key, record it in a secure place.

2. Install the sample application

We have built a sample web application to demonstrate the use of Circle Payments API. You can clone the Github repository, configure the app and run it locally.

📘

NPM and Yarn

If you don't already, make sure you have npm and yarn installed.

# Clone the sample app Github repository
git clone https://github.com/circlefin/payments-sample-app.git

# Change into sample app folder
cd payments-sample-app

# Create a .env file and configure the base url for api calls
echo BASE_URL=https://api-sandbox.circle.com > .env

# Install the dependencies
yarn install

# Run the sample app locally
yarn dev
The sample application should now be running at: http://localhost:3011.

📘

Enter Your API Key

Take the API key you generated on step 1, and enter it on the settings tab on the top right corner of the sample application.

3. Create the Bank Account You Will Accept a Payment From

Now make an API call to create the bank account you intend to accept a payment from by using the create bank account for wire transfers endpoint.

You can do that by using the "Payments API" > "POST /wires" flow on the sample application menu. You can select one of three pre-existent test bank account details. Alternatively, you can use the command below to make an API call yourself.

# Replace ${YOUR_API_KEY} with the API key obtained on step 1
curl -H 'Accept: application/json' \
    -H 'Content-type: application/json' \
    -H "Authorization: Bearer ${YOUR_API_KEY}" \
    -X POST --url https://api-sandbox.circle.com/v1/banks/wires \
    --data '{"idempotencyKey":"6ae62bf2-bd71-49ce-a599-165ffcc33680","beneficiaryName":"John Smith", "accountNumber":"123456789", "routingNumber":"021000021", "billingDetails":{"name":"John Smith", "city":"Boston", "country":"US", "line1":"1 Main Street", "district":"MA", "postalCode":"02201"}, "bankAddress":{"country":"US"}}'

In either case, you should receive a response like below.

{
  "data":{
    "id":"ee781852-82c7-4989-9f61-a343c3cf5506",
    "description":"JPMORGAN CHASE BANK, NA ****6789",
    "trackingRef":"CIR2EQS5BM",
    "billingDetails":{
      "line1":"1 Main Street",
      "city":"Boston",
      "postalCode":"02201",
      "district":"MA",
      "country":"US"
    },
    "bankAddress":{
      "bankName":"JPMORGAN CHASE BANK, NA",
      "city":"NEW YORK",
      "district":"NEW YORK",
      "country":"US"
    },
    "createDate":"2020-07-27T07:17:16.799Z",
    "updateDate":"2020-07-27T07:17:16.799Z"
  }
}

📘

Bank Accounts for Wire Transfers in Different Countries

Note that the example above used option 1 of the set of fields required by the create bank account for wire transfers endpoint which is specific to U.S. domiciled bank accounts. For more details on other options (for bank accounts in other countries) see the guide on bank accounts for wire transfers in different countries.

4. Obtain the Bank Wire Transfer Details

Bank wire transfers are "push" payments, and so the end user making the payment has to initiate the transfer from their bank account (see our list of supported countries). For that reason it is important to be able to share bank wire transfer details with the end user.

You can obtain the details required for initiating the bank wire transfer by using the get wire transfer instructions endpoint. Do that by using the "Payments API" > "GET /wires/{id}/instructions" flow on the sample application menu. Alternatively, you can use the command below to make an API call yourself. Use the id of the bank account created in the previous step.

curl -H 'Accept: application/json' \
    -H "Authorization: Bearer ${YOUR_API_KEY}" \
    -X GET --url https://api-sandbox.circle.com/v1/banks/wires/${BANK_ACCOUNT_ID}/instructions

In either case, you should receive a response like below.

{
  "data":{
    "trackingRef":"CIR2JYD6WT",
    "beneficiary":{
      "name":"CIRCLE INTERNET",
      "address1":"1 MAIN STREET",
      "address2":"SUITE 1"
    },
    "beneficiaryBank":{
      "name":"CRYPTO BANK",
      "swiftCode":"CRYPTO99",
      "routingNumber":"999999999",
      "accountNumber":"1000000001",
      "address":"1 MONEY STREET",
      "city":"NEW YORK",
      "postalCode":"10001",
      "country":"US"
    }
  }
}

In the production environment, the transfer details above will represent Circle's bank account details for incoming transfers. That information should be shared with the end user initiating the bank wire transfer. Once the funds reach Circle's banking infrastructure, we will attempt to reconcile that payment and settle the funds on your account.

🚧

Bank Wire Transfer Instructions

It is very important that you build an experience on your product that ensures end users will utilize the correct bank wire transfer details when making a payment. Mistakes made on a bank wire transfer can cause payment delays and ultimately cause the payment to fail along the way.

🚧

Transfer Tracking Reference

Note that a bank account created via Circle APIs has a tracking reference (trackingRef attribute) that is unique to that bank account. For payments via bank wire transfer, it is imperative that the end user initiating the transfer include that value on the memo or instruction field when prompted for it by their bank. Failure to indicate the tracking reference makes it impossible for Circle to reconcile the payment - such transfers will be returned to the sender.

5. Accept a Payment Via Bank Wire Transfer

Now that you have obtained bank wire transfer details for the payment and shared those with the end user, you just need to wait for the transfer to be initiated by the end user, and eventually the payment to settle and be reconciled.

It is difficult to test flows involving push payments, so we have created an endpoint for creating a mock wire transfer. You can go to "Payments API" > "POST /mocks/payments/wire" on the sample application menu to utilize it. Alternatively, you can use the command below to make an API call yourself. Use the trackingRef obtained in the previous step.

curl -H 'Accept: application/json' \
    -H 'Content-type: application/json' \
    -H "Authorization: Bearer ${YOUR_API_KEY}" \
    -X POST --url https://api-sandbox.circle.com/v1/mocks/payments/wire \
    --data '{"trackingRef":"${TRACKING_REF}", "amount": { "amount": "1000.00", "currency": "USD"}}'

In either case, you should receive a response like below.

{
  "data":{
    "trackingRef":"CIR2JYD6WT",
    "amount":{
      "amount":"1000.00",
      "currency":"USD"
    },
    "status":"pending"
  }
}

6. Check for the Existence of Payment

Due to "push" nature of wire transfers, you will have to monitor payments into your account in order to detect the wire payment you are expecting. You can either poll for payments using the get payments endpoint at certain intervals, or use our notifications service to receive updates.

Eventually, you will observe a payment object that matches your expectation, such as the one below.

{
    "id": "c82a2f41-5ec5-4d86-9395-fcdf0d0da552",
    "type": "payment",
    "merchantId": "7cbdedb1-d526-46b4-af12-4162a002eb9c",
    "merchantWalletId": "1000005019",
    "source": {
        "id": "cc3ac8e5-4dd7-4061-b465-0d2e7947ce4c",
        "type": "wire"
    },
    "description": "Merchant push payment",
    "amount": {
        "amount": "1000.00",
        "currency": "USD"
    },
    "fees": {
        "amount": "0.00",
        "currency": "USD"
    },
    "status": "paid",
    "refunds": [
    ],
    "createDate": "2020-10-15T11:20:01.346Z",
    "updateDate": "2020-10-15T11:28:06.117Z"
}

You can detect a match by looking into the source.id attribute, as it should match the id of the bank account you created on step 3.

When the payment is settled, the status will be equals to paid.

If the status is equal to failed then it means we could not settle that payment. That typically happens:

  • due to a mismatch between the information provided during the creation of the bank account (step 3) and the information received from the sender bank;
  • due to funds originating from unsupported bank accounts (where sender information isn't available).

In cases when the wire payment has failed, the funds are automatically sent back to the sender.

❗️

Bank Account Verification

Due to regulatory obligations, our systems automatically compare the bank account (number and routing) and sender (first and last name) information provided at the time of bank account creation with the information received on the wire transfer details (what the sender bank transmits). When there are mismatches, we are obliged to fail the payment and return the funds.

To avoid returns, make sure you build a user experience that makes that clear for end users, so that they provide you with the correct bank account and account holder / beneficiary information.

❗️

Unsupported Bank Accounts

We currently cannot support wire payments originating from bank accounts that require For Further Credit (FFC) instructions. In a For Further Credit (FFC) payment, the money is sent to the final beneficiary via an intermediary bank which obfuscates the bank account sender information. Examples of these bank accounts are brokerage and investment accounts, accounts that leverage third party payment processors, accounts with money transfer services, and challenger banks without their own banking license.

🎉 You are all done!

7. Like what you see? Keep going!

By accepting a wire payment that settles in USDC, you have just touched the tip of the iceberg of Circle APIs.

Check how to subscribe to notifications on changes in payments status. Also make sure you check the rest of the documentation - a few starting points are suggested below.

8. Ready for the next step?

If you are in advanced stages of experimenting with our APIs and want to plan moving to production, please start by applying for a business account and subsequently reach out to sales. We'll be happy to walk you through to the next steps.

We can't wait to see what you are going to build!

Updated 10 days ago



✨ Wire Payments Quickstart


Get started with the Circle Payments API and accept your first wire payment that settles in USDC in just a few minutes!

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.