Refund
Return funds to a customer after a payment has settled
A refund returns funds to a customer for a payment that has already settled. You can refund the full captured amount or a partial amount, and you can issue multiple partial refunds as long as their combined total doesn't exceed the original captured amount. For the full field list, jump to the Request reference.
You create a refund the same way you create a payment: a POST to /checkout/v3/payment with a negative amount. Linking the refund to the original payment with paymentToken or originalId (a referenced refund) is strongly recommended; it protects against over-refunding and keeps reconciliation clean. A refund with card details but no reference is a standalone refund.
If the payment hasn't settled yet, Void it instead of refunding, to avoid posting both a charge and a credit.
Common use cases
- Return the full amount for a returned online order
- Refund one item from a multi-item order (partial refund)
- Refund returns that arrive in stages (multiple partial refunds)
- Refund a purchase made on a legacy system (standalone refund)
Make your first refund
Submit a POST to /checkout/v3/payment with a negative amount and the original payment's paymentToken. A successful refund returns 201 Created with type: Return and status: Approved.
POST /checkout/v3/payment
{
"merchantId": 1000157980,
"tenderType": "Card",
"amount": -2.99,
"paymentToken": "PFBeGZaziZXBgCufaqPuVRLY6FlyJhGL",
"source": "API"
}{
"id": 4100000001181571,
"originalId": 4100000001181569,
"type": "Return",
"status": "Approved",
"amount": "-2.99",
"authCode": "PPS80a",
"reference": "613407782331",
"responseCode": 0
}Store the returned id; it's the unique identifier for the refund transaction. To view every transaction linked to a sale (the original payment, captures, and refunds), call GET /checkout/v3/paymentrelated?id={id} with the original payment's id.
Refund amounts are always negative (for example,
-50.00, not50.00). A positive amount creates a new charge, not a refund.
Scenarios
Every refund is a POST with a negative amount; the business context decides the amount and whether the refund is referenced or standalone.
Scenario 1: Full referenced refund
Business context. A customer returns a $200 product within the return window. The original sale settled five days ago. The merchant refunds the full amount, linking to the original payment with paymentToken so reconciliation stays clean and over-refunding is blocked.
POST /checkout/v3/payment
{
"merchantId": 1000157980,
"tenderType": "Card",
"amount": -200.00,
"paymentToken": "PFBeGZaziZXBgCufaqPuVRLY6FlyJhGL",
"source": "API"
}{
"id": 4100000001181571,
"originalId": 4100000001181569,
"type": "Return",
"status": "Approved",
"amount": "-200.00",
"responseCode": 0
}Because
paymentTokenties the refund to the original payment, PCE rejects any attempt to refund more than the captured amount.
Scenario 2: Partial refund
Business context. A customer ordered three items totaling $200; one item ($50) arrived damaged. The merchant refunds $50 for the damaged item only; the remaining $150 stays charged. Additional partial refunds are allowed until the cumulative total reaches the captured amount.
POST /checkout/v3/payment
{
"merchantId": 1000157980,
"tenderType": "Card",
"amount": -50.00,
"paymentToken": "PFBeGZaziZXBgCufaqPuVRLY6FlyJhGL",
"source": "API"
}{
"id": 4100000001181572,
"originalId": 4100000001181569,
"type": "Return",
"status": "Approved",
"amount": "-50.00",
"responseCode": 0
}Scenario 3: Standalone refund
Business context. A merchant migrated off a legacy gateway six months ago and needs to refund a purchase made on the old system. There's no paymentToken to reference, so the merchant issues a standalone refund with the customer's card details directly.
POST /checkout/v3/payment
{
"merchantId": 1000157980,
"tenderType": "Card",
"amount": -75.00,
"cardAccount": {
"number": "5555555555554444",
"expiryMonth": "10",
"expiryYear": "37",
"cvv": "798",
"avsZip": "10001"
},
"source": "API"
}{
"id": 4100000001181568,
"type": "Return",
"status": "Approved",
"amount": "-75.00",
"responseCode": 0
}Standalone refunds carry extra risk. Without a reference to an original sale, there's no automatic guard against refunding a card that never paid you. Restrict standalone refunds to admin or manager roles and require approval. Prefer referenced refunds wherever possible.
Track the payment
After issuing a refund, confirm its result with any of the following. The full status model is in Payment Lifecycle.
- GET /checkout/v3/payment/{id}: retrieve the refund transaction using the
idfrom the refund response. - GET /checkout/v3/paymentrelated?id={id}: view every transaction (sale, captures, refunds) linked to the original payment.
- Webhooks: subscribe to the
RefundCreatedevent for a push notification when a refund is created. See Payment Webhooks.
Request reference
| Parameter | Required | Description |
|---|---|---|
amount | ✓ | The amount to refund, as a negative value in USD (for example, -15.00). |
merchantId | ✓ | Your merchant account identifier. |
tenderType | ✓ | Set to Card for card transactions. |
paymentToken | Recommended | The token from the original settled payment. Including it makes this a referenced refund. |
originalId | Recommended | The id of the original payment, for direct association. |
cardAccount | Conditional | Card details or a vaulted card token. Required only for standalone refunds where no paymentToken/originalId is provided. |
source | Optional | The origin of the request (for example, API). |
A successful refund response includes type: Return, status, the negative amount, and responseCode.
Validation
PCE validates the refund synchronously before sending it to the card network. If validation fails, the request is rejected and nothing is refunded. Checks include:
- Required fields are present and correctly formatted.
- The referenced payment has settled and the cumulative refunds don't exceed the captured amount.
- Merchant configuration permits the refund.
Determine the outcome from the status (Approved or Declined) and responseCode fields. See Payment Response Codes and Handling Declines.
Statuses
An approved refund returns status: Approved and type: Return with a negative amount. Refunds apply only to settled payments; use Void before settlement. Accept Payments uses the shared Payment Lifecycle for every status.
Go live
The shared pre-production checklist (production credentials, webhooks, idempotency, sandbox testing) is in Getting Started. Specific to refunds, also confirm:
- A full referenced refund returns
status: Approvedwith the correct negative amount. - A partial refund deducts correctly, and refunds exceeding the captured total are rejected.
- A standalone refund (using
cardAccount) works when nopaymentTokenis available. - Your webhook endpoint processes
RefundCreatedevents idempotently. -
GET /checkout/v3/paymentrelated?id={id}shows the complete refund history for a sale.
Best practices
General practices (idempotency, webhooks, sandbox testing) are in Getting Started. Specific to refunds:
| Practice | Description |
|---|---|
| Prefer referenced refunds | Link refunds to the original payment with paymentToken or originalId to prevent over-refunding and automate reconciliation. |
| Void before settlement | If the payment hasn't settled, Void it instead; no interchange fees and no charge on the statement. |
| Set customer expectations | Tell customers a refund can take several business days to appear, depending on their issuing bank. |
| Track cumulative partials | Keep a running total of partial refunds so you don't attempt a refund that exceeds the captured amount. |
| Restrict standalone refunds | Standalone refunds bypass over-refund protection. Limit them to admin/manager roles and require approval. |
Next steps
See also
- Void a Payment: cancel before settlement
- Authorization and Capture: reserve funds and capture later
- Payment Lifecycle: statuses, tracking, and settlement
- Payment Webhooks: subscribe to
RefundCreated - Payment Response Codes: resolve a rejected refund
Updated about 11 hours ago