Skip to main content
A Refund returns part or all of a SUCCEEDED payment to the customer’s card. Refunds always use the currency of the original payment.

Create a refund

  • amount is always required, in minor units. For a full refund, send the payment’s current amount_refundable.
  • merchant_reference is optional, belongs to this refund, and must be an integer with exactly 10 digits (from 1000000000 to 9999999999).
  • reason is required free text for your support and audit trail.
  • A payment can be refunded multiple times until the accumulated refunded amount reaches the original amount. A refund that would exceed amount_refundable is rejected with 422 and error.code: "amount_exceeds_refundable".
The response is 201 Created with a Refund object:

Refund lifecycle

Refunds are processed asynchronously. 201 means accepted, not completed. Track refund status by re-retrieving the parent payment — every payment carries its refunds in the refunds array (oldest first), with amount_refunded and amount_refundable kept up to date. Webhooks also emit refund.succeeded and refund.failed when terminal refund status changes are available.

Idempotent refunds

Refund creation is idempotent on (Idempotency-Key, request body):
  • Retrying with the same key and the same body returns the original refund — it is safe to retry on timeouts.
  • Reusing a key with any field changed (a different amount, reason, or merchant_reference) is rejected with 409 and error.code: "idempotency_key_reused".
  • Retrying while the original request is still processing returns 409 with error.code: "idempotency_key_in_use"; wait briefly and retry the same body.
Pick a deterministic key tied to the business operation — for example refund-{orderId}-{sequence} — so retries collapse correctly even across processes. More in Idempotency.

Operational notes

  • Refunds can take several business days to appear on the customer’s statement, even after SUCCEEDED.
  • If a refund FAILED (for example the card account was closed), resolve it with the customer through another channel; creating the same refund again will typically fail for the same reason.