Refunds, capture and cancel
Give money back, settle an authorization, or void one before it settles.
Refunding a payment
To return the whole amount, post a refund with a reason and no amount. The reason is required — it is what makes your refund reporting mean anything later:
POST /v1/payments/b0f9c6d2-…/refunds
{
"reason": "REQUESTED_BY_CUSTOMER"
}| Reason | When |
|---|---|
REQUESTED_BY_CUSTOMER | They changed their mind, returned the goods, cancelled the booking. |
FRAUDULENT | The payment was not made by the account holder. |
DUPLICATE | They were charged twice for one order. |
CANCELLATION | You cancelled the order — out of stock, cannot deliver. |
OTHERS | Nothing above fits. Use it sparingly; it is the row nobody can report on. |
A successful full refund leaves the payment REFUNDED. The refund itself is a record of its own, with an id and a status — a refund can be PENDING for a while on rails that do not return money instantly.
Partial refunds
Add amount to return part of it, and add your own referenceId for the refund so you can recognise it in your books:
POST /v1/payments/b0f9c6d2-…/refunds
{
"reason": "REQUESTED_BY_CUSTOMER",
"amount": 500,
"referenceId": "refund-1001-a"
}You can refund partially more than once, up to the original amount. The payment sits at PARTIALLY_REFUNDED until the refunds add up to the whole, at which point it becomes REFUNDED. Amounts are in the major unit, exactly as on the payment — 500 is ₱500.00.
When a refund is refused
Three refusals, and each is telling you something different:
STATUS_NOT_REFUNDABLE— the payment is not in a refundable state. It never succeeded, or it is already fully refunded. Read it back and look atstatus.NOTHING_LEFT_TO_REFUND— earlier refunds already returned the full amount. Usually a duplicate request, which is worth investigating on your side.AMOUNT_EXCEEDS_REMAINING— you asked for more than is left. Read the payment's refunds and subtract before asking again.
Capture and cancel
These two only apply to a payment sitting at AUTHORIZED — funds held, not yet taken. A payment that went straight to SUCCEEDED was captured as it was made, and neither endpoint applies to it.
POST /v1/payments/:paymentId/capture— take the money. Send anamountto capture part of what was authorized, or omit it for the full amount. The payment becomesSUCCEEDED.POST /v1/payments/:paymentId/cancel— release the hold. No body. The payment becomesCANCELLED, and the customer's funds are freed without a refund ever appearing on their statement.
Prefer cancel over refund whenever the payment has not been captured: it is faster for the customer, and it leaves a cleaner record for both of you.

