ECASHPAYECASHPAYDocumentation
Back to site

Introduction

  • EcashPay API
  • Quickstart

Core concepts

  • Environments and API keys
  • Signing requests
  • Errors

Accept payments

  • Creating a payment
  • Payment methods
  • Confirming the outcome
  • Refunds, capture and cancel

Testing

  • Testing

API reference

  • API reference

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:

Full refund
POST /v1/payments/b0f9c6d2-…/refunds

{
  "reason": "REQUESTED_BY_CUSTOMER"
}
ReasonWhen
REQUESTED_BY_CUSTOMERThey changed their mind, returned the goods, cancelled the booking.
FRAUDULENTThe payment was not made by the account holder.
DUPLICATEThey were charged twice for one order.
CANCELLATIONYou cancelled the order — out of stock, cannot deliver.
OTHERSNothing 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:

Partial refund
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 at status.
  • 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.

A refund is not idempotent

Unlike creating a payment, a refund has no duplicate guard on your reference: two identical partial refunds will return the money twice. Decide before you retry — read the payment's refund list and check whether the first one landed.

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 an amount to capture part of what was authorized, or omit it for the full amount. The payment becomes SUCCEEDED.
  • POST /v1/payments/:paymentId/cancel — release the hold. No body. The payment becomes CANCELLED, 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.

PreviousConfirming the outcomeNextTesting

On this page

  • Refunding a payment
  • Partial refunds
  • When a refund is refused
  • Capture and cancel