Mint

Quickstart: Crypto Deposits

Quickly start accepting USDC crypto payments on your site using our code examples.

USDC is a “stablecoin,” a cryptocurrency that provides a stable level of purchasing power. As such, it is a popular currency for online transactions, and your customers will want to use it as a payment medium. This guide will walk you through the basics of accepting USDC on your site. Here we use the Ethereum blockchain as an example, but the same steps apply to other currencies and chains as well.

Steps:

  1. Set up payment intent to pay with Crypto
  2. Acquire blockchain address customer will pay to
  3. Customer pays
  4. Receive payment

Once the customer reaches checkout and confirms they would like to pay with USDC on Ethereum, your system will send Circle a request to create a payment intent. Within this payment intent request you will specify the amount, currency, settlement currency, and chain.

Create a payment intent:

curl --location --request POST 'https://api-sandbox.circle.com/v1/paymentIntents' \
--header 'X-Requested-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data-raw '{
 "idempotencyKey": "17607606-e383-4874-87c3-7e46a5dc03dd",
 "amount": {
   "amount": "1.00",
   "currency": "USD"
 },
 "settlementCurrency": "USD",
 "paymentMethods": [
   {
     "type": "blockchain",
     "chain": "ETH"
   }
 ]
}'

Response

JSON
{
  "data": {
    "id": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "amount": {
      "amount": "1.00",
      "currency": "USD"
    },
    "amountPaid": {
      "amount": "0.00",
      "currency": "USD"
    },
    "amountRefunded": {
      "amount": "0.00",
      "currency": "USD"
    },
    "settlementCurrency": "USD",
    "paymentMethods": [
      {
        "type": "blockchain",
        "chain": "ETH"
      }
    ],
    "paymentIds": [],
    "timeline": [
      {
        "status": "created",
        "time": "2022-07-21T20:13:35.579331Z"
      }
    ],
    "createDate": "2022-07-21T20:13:35.578678Z",
    "updateDate": "2022-07-21T20:19:24.859052Z"
  }
}

Webhook notification

JSON
{
  "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
  "notificationType": "paymentIntents",
  "version": 1,
  "customAttributes": { "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522" },
  "paymentIntent": {
    "id": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "amount": { "amount": "1.00", "currency": "USD" },
    "amountPaid": { "amount": "0.00", "currency": "USD" },
    "amountRefunded": { "amount": "0.00", "currency": "USD" },
    "settlementCurrency": "USD",
    "paymentMethods": [{ "type": "blockchain", "chain": "ETH" }],
    "paymentIds": [],
    "refundIds": [],
    "timeline": [
      { "status": "created", "time": "2022-07-21T20:13:35.579331Z" }
    ],
    "createDate": "2022-07-21T20:13:35.578678Z",
    "updateDate": "2022-07-21T20:13:35.578678Z"
  }
}

For security reasons, we do not synchronously return the deposit blockchain address. To retrieve the blockchain deposit address, you have two options:

  1. Subscribe to webhook notifications
  2. Poll Circle APIs

To receive webhook notifications, follow the steps in the notifications quickstart. After you subscribe to notifications, you will receive updates for the payment intent whenever the resource is updated. In this case, when the paymentMethods.address is set, a notification is sent with a new timeline object with a status of pending.

Payment intent webhook notification

JSON
{
  "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
  "notificationType": "paymentIntents",
  "version": 1,
  "customAttributes": { "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522" },
  "paymentIntent": {
    "id": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "amount": { "amount": "1.00", "currency": "USD" },
    "amountPaid": { "amount": "0.00", "currency": "USD" },
    "amountRefunded": { "amount": "0.00", "currency": "USD" },
    "settlementCurrency": "USD",
    "paymentMethods": [
      {
        "type": "blockchain",
        "chain": "ETH",
        "address": "0x97de855690955e0da79ce5c1b6804847e7070c7f"
      }
    ],
    "fees": [
      { "type": "blockchainLeaseFee", "amount": "0.00", "currency": "USD" }
    ],
    "paymentIds": [],
    "refundIds": [],
    "timeline": [
      { "status": "pending", "time": "2022-07-21T20:13:38.188286Z" },
      { "status": "created", "time": "2022-07-21T20:13:35.579331Z" }
    ],
    "createDate": "2022-07-21T20:13:35.578678Z",
    "updateDate": "2022-07-21T20:13:38.186831Z",
    "expiresOn": "2022-07-21T21:13:38.087275Z"
  }
}

If you prefer to poll get a payment intent, you can send get request until you receivepaymentMethods.address.

Retrieve payment intent:

curl --location --request GET 'https://api-sandbox.circle.com/v1/paymentIntents/{id}' \
--header 'X-Requested-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'

Response

JSON
{
  "data": {
    "id": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "amount": {
      "amount": "1.00",
      "currency": "USD"
    },
    "amountPaid": {
      "amount": "0.00",
      "currency": "USD"
    },
    "amountRefunded": {
      "amount": "0.00",
      "currency": "USD"
    },
    "settlementCurrency": "USD",
    "paymentMethods": [
      {
        "type": "blockchain",
        "chain": "ETH",
        "address": "0x97de855690955e0da79ce5c1b6804847e7070c7f"
      }
    ],
    "fees": [
      { "type": "blockchainLeaseFee", "amount": "0.00", "currency": "USD" }
    ],
    "paymentIds": [],
    "refundIds": [],
    "timeline": [
      { "status": "pending", "time": "2022-07-21T20:13:38.188286Z" },
      { "status": "created", "time": "2022-07-21T20:13:35.579331Z" }
    ],
    "createDate": "2022-07-21T20:13:35.578678Z",
    "updateDate": "2022-07-21T20:13:38.186831Z",
    "expiresOn": "2022-07-21T21:13:38.087275Z"
  }
}

Once you receive the deposit address via paymentMethods.address, you’ll provide it to the customer along with the amount and currency to be paid. You can present the address two ways:

  1. as plain text the customer can cut and paste; or
  2. as a QR code the customer can scan via an app.

The customer then sends payment from their wallet (custodial or non-custodial).

Once Circle obtains payment on-chain, we create a Payment resource linked to the Payment Intent created earlier and update the status of that Payment Intent. Your firm will then receive payment via the method specified.

Payment intent webhook notification

JSON
{
  "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
  "notificationType": "paymentIntents",
  "version": 1,
  "customAttributes": { "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522" },
  "paymentIntent": {
    "id": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "amount": { "amount": "1.00", "currency": "USD" },
    "amountPaid": { "amount": "1.00", "currency": "USD" },
    "amountRefunded": { "amount": "0.00", "currency": "USD" },
    "settlementCurrency": "USD",
    "paymentMethods": [
      {
        "type": "blockchain",
        "chain": "ETH",
        "address": "0x97de855690955e0da79ce5c1b6804847e7070c7f"
      }
    ],
    "fees": [
      { "type": "blockchainLeaseFee", "amount": "0.00", "currency": "USD" },
      { "type": "totalPaymentFees", "amount": "0.01", "currency": "USD" }
    ],
    "paymentIds": ["66c56b6a-fc79-338b-8b94-aacc4f0f18de"],
    "refundIds": [],
    "timeline": [
      {
        "status": "complete",
        "context": "paid",
        "time": "2022-07-21T20:19:24.861094Z"
      },
      { "status": "pending", "time": "2022-07-21T20:13:38.188286Z" },
      { "status": "created", "time": "2022-07-21T20:13:35.579331Z" }
    ],
    "createDate": "2022-07-21T20:13:35.578678Z",
    "updateDate": "2022-07-21T20:19:24.859052Z",
    "expiresOn": "2022-07-21T21:13:38.087275Z"
  }
}

Payment webhook notification

JSON
{
  "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
  "notificationType": "payments",
  "version": 1,
  "customAttributes": { "clientId": "f1397191-56e6-42fd-be86-0a7b9bd91522" },
  "payment": {
    "id": "66c56b6a-fc79-338b-8b94-aacc4f0f18de",
    "type": "payment",
    "status": "paid",
    "amount": { "amount": "1.00", "currency": "USD" },
    "fees": { "amount": "0.01", "currency": "USD" },
    "createDate": "2022-07-21T20:16:35.092Z",
    "updateDate": "2022-07-21T20:19:24.719Z",
    "merchantId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
    "merchantWalletId": "1000999922",
    "paymentIntentId": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "settlementAmount": { "amount": "1.00", "currency": "USD" },
    "fromAddresses": {
      "chain": "ETH",
      "addresses": ["0x0d4344cff68f72a5b9abded37ca5862941a62050"]
    },
    "depositAddress": {
      "chain": "ETH",
      "address": "0x97de855690955e0da79ce5c1b6804847e7070c7f"
    },
    "transactionHash": "0x7351585460bd657f320b9afa02a52c26d89272d0d10cc29913eb8b28e64fd906"
  }
}

Retrieve a payment intent:

curl --location --request GET 'https://api-sandbox.circle.com/v1/paymentIntents/{id}' \
--header 'X-Requested-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'

Response

JSON
{
  "data": {
    "id": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "amount": {
      "amount": "1.00",
      "currency": "USD"
    },
    "amountPaid": {
      "amount": "1.00",
      "currency": "USD"
    },
    "amountRefunded": {
      "amount": "0.00",
      "currency": "USD"
    },
    "settlementCurrency": "USD",
    "paymentMethods": [
      {
        "type": "blockchain",
        "chain": "ETH",
        "address": "0x97de855690955e0da79ce5c1b6804847e7070c7f"
      }
    ],
    "fees": [
      {
        "type": "blockchainLeaseFee",
        "amount": "0.00",
        "currency": "USD"
      },
      {
        "type": "totalPaymentFees",
        "amount": "0.01",
        "currency": "USD"
      }
    ],
    "paymentIds": ["66c56b6a-fc79-338b-8b94-aacc4f0f18de"],
    "refundIds": [],
    "timeline": [
      {
        "status": "complete",
        "context": "paid",
        "time": "2022-07-21T20:19:24.861094Z"
      },
      {
        "status": "pending",
        "time": "2022-07-21T20:13:38.188286Z"
      },
      {
        "status": "created",
        "time": "2022-07-21T20:13:35.579331Z"
      }
    ],
    "createDate": "2022-07-21T20:13:35.578678Z",
    "updateDate": "2022-07-21T20:19:24.859052Z",
    "expiresOn": "2022-07-21T21:13:38.087275Z"
  }
}

Retrieve a payment:

curl --location --request GET 'https://api-sandbox.circle.com/v1/payments/{id}' \
--header 'X-Requested-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'

Response

JSON
{
  "data": {
    "id": "66c56b6a-fc79-338b-8b94-aacc4f0f18de",
    "type": "payment",
    "status": "paid",
    "amount": {
      "amount": "1.00",
      "currency": "USD"
    },
    "fees": {
      "amount": "0.01",
      "currency": "USD"
    },
    "createDate": "2022-07-21T20:16:35.092852Z",
    "updateDate": "2022-07-21T20:19:24.719313Z",
    "merchantId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
    "merchantWalletId": "1000999922",
    "paymentIntentId": "6e4d4047-db14-4c09-b238-1215aee50d03",
    "settlementAmount": {
      "amount": "1.00",
      "currency": "USD"
    },
    "fromAddresses": {
      "chain": "ETH",
      "addresses": ["0x0d4344cff68f72a5b9abded37ca5862941a62050"]
    },
    "depositAddress": {
      "chain": "ETH",
      "address": "0x97de855690955e0da79ce5c1b6804847e7070c7f"
    },
    "transactionHash": "0x7351585460bd657f320b9afa02a52c26d89272d0d10cc29913eb8b28e64fd906"
  }
}

Call the GET /payment/presign endpoint to fetch the typed message. The two required parameters are paymentIntentId , which can be retrieved from the GET /paymentIntent response or webhook notification; and endUserAddress which is the consumer wallet address.

Bash
curl --location 'https://api-sandbox.circle.com/v1/payments/presign?paymentIntentId=6e4d4047-db14-4c09-b238-1215aee50d03&endUserAddress=0x8381470ED67C3802402dbbFa0058E8871F017A6F' \
--header 'X-Requested-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'

Response

JSON
{
  "data": {
    "typedData": {
      "domain": {
        "name": "USD Coin",
        "verifyingContract": "0x07865c6e87b9f70255377e024ace6630c1eaa37f",
        "version": "2",
        "chainId": 5
      },
      "message": {
        "from": "0x8381470ED67C3802402dbbFa0058E8871F017A6F",
        "to": "0xdB055877e6c13b6A6B25aBcAA29B393777dD0a73",
        "value": "5003456",
        "validAfter": 1675317371,
        "validBefore": 1675107967,
        "nonce": "0x4f716a578b96592599c3ca7b2a46453df87511d4809f608cec982d6e83632604"
      },
      "totalAmount": {
        "amount": "3.14",
        "currency": "USD"
      },
      "feeChargeModel": "endUser",
      "networkFeeQuote": {
        "quoteId": "5d0bb4e7-bd83-44dd-b8f5-53ddd5f35a3a",
        "amount": {
          "amount": "3.14",
          "currency": "USD"
        },
        "expiresAt": "2023-02-02T06:01:21.152737680Z"
      },
      "types": {
        "EIP712Domain": [
          {
            "name": "name",
            "type": "string"
          },
          {
            "name": "version",
            "type": "string"
          },
          {
            "name": "chainId",
            "type": "uint256"
          },
          {
            "name": "verifyingContract",
            "type": "address"
          }
        ],
        "TransferWithAuthorization": [
          {
            "name": "from",
            "type": "address"
          },
          {
            "name": "to",
            "type": "address"
          },
          {
            "name": "validAfter",
            "type": "uint256"
          },
          {
            "name": "validBefore",
            "type": "uint256"
          },
          {
            "name": "nonce",
            "type": "byte32"
          }
        ]
      },
      "primaryType": "TransferWithAuthorization"
    }
  }
}

You will need to trigger the customer’s wallet using the response from /presign.

For example, if you use the signTypedData function from wagmi, you will need to fill out the domain, types and values fields.

Once the customer signs into the wallet, you will receive a string of raw signatures.

With a customer’s raw signature, Circle can create a crypto payment with the POST /payment/crypto endpoint.

Bash
curl --location 'https://api-sandbox.circle.com/v1/payments/crypto' \
--header 'X-Requested-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
    "idempotencyKey": "ba943ff1-ca16-49b2-ba55-1057e70ca5c7",
    "paymentIntentId": "4e9fa5b1-3964-4f02-a7ba-811cc5d94be1",
    "protocolMetadata": {
        "type": "TransferWithAuthorization",
        "metaTxNonce": "0xfdb476566b75311fdd14444e6a77630c36e653a3e255adcaa7c34f3babc1de76",
        "signatureValidAfter": "1675104393",
        "signatureValidBefore": "1675107967",
        "rawSignature": "0xcff7ef7a24b88d83fa3d6e81b41c9cef19cc0119c085a6ef98cb1b6bc9436a9f18dcb2d46b9cb4d31a7031466b450bbe1e6c0230c5503c7a68e04055b4be0cbc1b"
    },
    "amount": {
        "amount": "3.14",
        "currency": "USD"
    },
    "source": {
        "address": "0xdB055877e6c13b6A6B25aBcAA29B393777dD0a73",
        "type": "blockchain"
    },
    "destination": {
        "address": "0xda1ab716f7f7b3cb036a7fd74e5ca852126834c1",
        "chain": "ETH"
    },
    "quoteId": "c6ac001e-9812-4bc1-8dc3-1549b5adaa23"
}'

Response

JSON
{
  "data": {
    "id":"27827c45-6a3e-4012-8eaa-f6d712f70c2e",
    "type":"payment",
    "status":"pending",
    "amount":{
      "amount":"10.00",
      "currency":"USD"
    }
    "createDate":"2023-02-14T01:21:07.116369Z",
    "updateDate":"2023-02-14T01:21:07.116371Z",
    "merchantId":"a49f9b1d-75e0-44a9-b8d2-4293b3f11ebd",
    "merchantWalletId":"1000563095",
    "paymentIntentId":"dfcf96ab-dd3f-417e-b009-ef899ee4e8da",
    "fromAddresses":{
      "chain":"ETH",
      "addresses":[
        "0xbdE3d06b700A5f622767c85e79e42014C5376B6B"
      ]
    }
    "depositAddress":{
      "chain":"ETH",
      "address":"0x5f1090b5db3e00e13e94b93055b3d1c4254e1720"
    }
  }
}

Did this page help you?
© 2023-2025 Circle Technology Services, LLC. All rights reserved.