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, not 50.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 paymentToken ties 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.


Request reference

ParameterRequiredDescription
amountThe amount to refund, as a negative value in USD (for example, -15.00).
merchantIdYour merchant account identifier.
tenderTypeSet to Card for card transactions.
paymentTokenRecommendedThe token from the original settled payment. Including it makes this a referenced refund.
originalIdRecommendedThe id of the original payment, for direct association.
cardAccountConditionalCard details or a vaulted card token. Required only for standalone refunds where no paymentToken/originalId is provided.
sourceOptionalThe 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: Approved with the correct negative amount.
  • A partial refund deducts correctly, and refunds exceeding the captured total are rejected.
  • A standalone refund (using cardAccount) works when no paymentToken is available.
  • Your webhook endpoint processes RefundCreated events 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:

PracticeDescription
Prefer referenced refundsLink refunds to the original payment with paymentToken or originalId to prevent over-refunding and automate reconciliation.
Void before settlementIf the payment hasn't settled, Void it instead; no interchange fees and no charge on the statement.
Set customer expectationsTell customers a refund can take several business days to appear, depending on their issuing bank.
Track cumulative partialsKeep a running total of partial refunds so you don't attempt a refund that exceeds the captured amount.
Restrict standalone refundsStandalone refunds bypass over-refund protection. Limit them to admin/manager roles and require approval.

Next steps

See also



Did this page help you?
.readme-logo { display: none !important; }