Skip to main content
Use the Crypto Deposits API to refund USDC or EURC after a completed payin, which is a stablecoin deposit from an external wallet into your Circle Mint account. The examples use a continuous payment intent (open-ended checkout), but the same steps apply to transient intents (single checkout with a fixed amount). Complete Receive a Stablecoin Payin first if you have not accepted a payin yet.

Prerequisites

Before you begin this tutorial, ensure you’ve:

Step 1: Start a refund on the payment intent

Call the Refund a payment intent endpoint.
  • Partial refund: set toAmount to the amount you return to the customer. You can send multiple partial refunds up to what was settled.
  • Full refund: use the request fields for refunding the remaining balance as described in the API reference.
Expected result: a refund object with status pending and a refund id. Example request:
cURL
curl --location --request POST 'https://api-sandbox.circle.com/v1/paymentIntents/e2e90ba3-9d1f-490d-9460-24ac6eb55a1b/refund' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data-raw '{
  "idempotencyKey": "9aed1aab-292a-427f-aae1-e0e358fef1c9",
  "destination": {
    "chain": "ETH",
    "address": "0xcd7475eaed9ee9678cf219cec748e25aba068a69"
  },
  "amount": {
    "currency": "USD"
  },
  "toAmount": {
    "amount": "0.50",
    "currency": "USD"
  }
}'
Example response:
JSON
{
  "data": {
    "id": "3389f4ba-aafd-4eef-aaa2-3292df8f62e6",
    "type": "refund",
    "status": "pending",
    "amount": {
      "currency": "USD"
    },
    "createDate": "2023-01-22T15:29:58.000000Z",
    "updateDate": "2023-01-22T15:29:58.000000Z",
    "merchantId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
    "merchantWalletId": "1000999922",
    "paymentIntentId": "e2e90ba3-9d1f-490d-9460-24ac6eb55a1b",
    "settlementAmount": {
      "amount": "0.50",
      "currency": "USD"
    },
    "depositAddress": {
      "chain": "ETH",
      "address": "0xcd7475eaed9ee9678cf219cec748e25aba068a69"
    }
  }
}

Step 2: Inspect the payment intent

Call Get a payment intent to confirm the refund is reflected on the intent. Expected result: the response includes these fields:
  • amountRefunded: cumulative amount refunded on this intent so far.
  • refundIds: refund IDs associated with this intent.
  • paymentIds: IDs of payin payments on this intent.
  • timeline: includes a refunded entry after the refund is recorded (alongside earlier statuses such as paid).
Example request:
cURL
curl --location --request GET 'https://api-sandbox.circle.com/v1/paymentIntents/e2e90ba3-9d1f-490d-9460-24ac6eb55a1b' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'
Example response:
JSON
{
  "data": {
    "id": "e2e90ba3-9d1f-490d-9460-24ac6eb55a1b",
    "currency": "USD",
    "settlementCurrency": "USD",
    "amountPaid": {
      "amount": "1.00",
      "currency": "USD"
    },
    "amountRefunded": {
      "amount": "0.50",
      "currency": "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": ["3389f4ba-aafd-4eef-aaa2-3292df8f62e6"],
    "timeline": [
      {
        "status": "refunded",
        "time": "2023-01-22T15:30:00.000000Z"
      },
      {
        "status": "complete",
        "context": "paid",
        "time": "2023-01-21T20:19:24.861094Z"
      },
      {
        "status": "pending",
        "time": "2023-01-21T20:13:38.188286Z"
      },
      {
        "status": "created",
        "time": "2023-01-21T20:13:35.579331Z"
      }
    ],
    "type": "continuous",
    "createDate": "2023-01-21T20:13:35.578678Z",
    "updateDate": "2023-01-22T15:30:00.000000Z"
  }
}

Step 3: Confirm refund completion

Call Get a payment with the original payin payment id or with the refund id from Step 1. Expected result: the response has type refund and status paid when the refund has settled onchain. If status is still pending, the refund has not finished. Poll Get a payment on an interval, or subscribe to payments notifications (see the notifications quickstart) to learn when the status changes. Example request: (replace the ID with the payment or refund id)
cURL
curl --location --request GET 'https://api-sandbox.circle.com/v1/payments/3389f4ba-aafd-4eef-aaa2-3292df8f62e6' \
--header 'Accept: application/json' \
--header 'X-Request-Id: ${GUID}' \
--header 'Authorization: Bearer ${YOUR_API_KEY}'
Example response:
JSON
{
  "data": {
    "id": "3389f4ba-aafd-4eef-aaa2-3292df8f62e6",
    "type": "refund",
    "status": "paid",
    "amount": {
      "currency": "USD"
    },
    "fees": {
      "amount": "0.01",
      "currency": "USD"
    },
    "createDate": "2023-01-22T15:29:58.000000Z",
    "updateDate": "2023-01-22T15:35:12.000000Z",
    "merchantId": "f1397191-56e6-42fd-be86-0a7b9bd91522",
    "merchantWalletId": "1000999922",
    "paymentIntentId": "e2e90ba3-9d1f-490d-9460-24ac6eb55a1b",
    "settlementAmount": {
      "amount": "0.50",
      "currency": "USD"
    },
    "fromAddresses": {
      "chain": "ETH",
      "addresses": ["0x0d4344cff68f72a5b9abded37ca5862941a62050"]
    },
    "depositAddress": {
      "chain": "ETH",
      "address": "0xcd7475eaed9ee9678cf219cec748e25aba068a69"
    },
    "transactionHash": "0xa1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678"
  }
}