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

Payment methods

The four ways a customer can pay, how each one behaves, and what happens when one is switched off.

The four methods

There are four, and method takes exactly one of them. You choose how the customer pays; you never choose who clears it.

Credit card

CARD_CREDIT

The customer enters card details on a secure page and comes back when it is done. Decided in seconds.

POST /v1/payments — Credit card
{
  "referenceId": "order-1001",
  "method": "CARD_CREDIT",
  "amount": 1500,
  "currency": "PHP",
  "customerEmail": "payer@example.com",
  "description": "Order #1001"
}
What comes back
{
  "status": "PENDING",
  "method": "CARD_CREDIT",
  "qrString": null,
  "paymentLinkUrl": "https://checkout.ecashpay.example/9f2b41c7"
}

Debit card

CARD_DEBIT

The same journey as a credit card. It is a separate method because the two can settle differently and can be priced differently.

POST /v1/payments — Debit card
{
  "referenceId": "order-1002",
  "method": "CARD_DEBIT",
  "amount": 1500,
  "currency": "PHP",
  "customerEmail": "payer@example.com",
  "description": "Order #1002"
}
What comes back
{
  "status": "PENDING",
  "method": "CARD_DEBIT",
  "qrString": null,
  "paymentLinkUrl": "https://checkout.ecashpay.example/1c4d7e90"
}

QR

QR

The customer scans a code with whichever bank or wallet app they already have. The payment is completed by scanning, so this is the one method that keeps the customer on your page.

POST /v1/payments — QR
{
  "referenceId": "order-1003",
  "method": "QR",
  "amount": 1500,
  "currency": "PHP",
  "customerEmail": "payer@example.com",
  "description": "Order #1003"
}
What comes back
{
  "status": "PENDING",
  "method": "QR",
  "qrString": "00020101021228670011ph.ppmi.p2m…6304ABCD",
  "paymentLinkUrl": null
}

E-wallet

EWALLET

The customer approves the payment in their wallet app or its web flow. Usually decided before they close the tab.

POST /v1/payments — E-wallet
{
  "referenceId": "order-1004",
  "method": "EWALLET",
  "amount": 1500,
  "currency": "PHP",
  "customerEmail": "payer@example.com",
  "description": "Order #1004"
}
What comes back
{
  "status": "PENDING",
  "method": "EWALLET",
  "qrString": null,
  "paymentLinkUrl": "https://checkout.ecashpay.example/3d7c9a10"
}

Read those four side by side and the contract is the whole story: the bodies are identical but for one word, and only QR answers differently. Nothing names a rail, a service or a flow, because none of those are yours to choose.

How each one behaves

Three of the four end with the customer somewhere else and coming back. The response carries paymentLinkUrl; you send them there, and then your server asks the API for the outcome — EcashPay does not call your server when a payment finishes, so there is no webhook to wait for.

QR is the exception, and it is the one difference worth building for. A QR payment is completed by scanning, so the response carries the payload itself in qrString and paymentLinkUrl is null. Render the payload as a QR code on your own page — the customer never leaves it.

Never both

qrString and paymentLinkUrl are never both set. Branch on whichever is present rather than on the method, and a method that changes shape later cannot break your client.

The payload is a string to render, not an address to fetch. Never request it, and never put a URL inside a QR code you drew from it.

When a method is unavailable

A method can be switched off — EcashPay routes each method onto a payment rail per environment, and an operator can turn one off or leave it unrouted. It is a platform-wide setting, not something enabled per merchant account. That is answered with 503 PAYMENT_METHOD_UNAVAILABLE, naming the method.

The status is deliberate: 503 says the request was fine and the capability was not there. There is no retryAfter on it and no retry window: a method that is switched off comes back when someone switches it on, not on a timer, so fall back to another method rather than looping. A misspelled method is a different thing and answers 400 INVALID_PAYMENT_METHOD, which retrying will never fix.

A method that is currently switched off
HTTP/1.1 503 Service Unavailable

{
  "success": false,
  "error": {
    "code": "PAYMENT_METHOD_UNAVAILABLE",
    "message": "QR code is currently unavailable."
  }
}

Never silently rerouted

An unavailable method is refused, not quietly moved to another one. The methods differ in what they can refund and how they settle, so a silent substitution would change what your payment is — and you would find out from a reconciliation, not from the response.

Choosing a method

If you offer a picker, offer the four. If you offer one method, offer EWALLET — it is the dominant consumer rail in the Philippines and the fastest to settle.

The create-payment body is the same whichever method you send, so there is one shape to write against. Reading a payment, the ledger and the payer directory do not vary by method at all. Refunding and capture are the exception: the request and response shapes are identical, but whether a payment can be refunded or captured through the API depends on how it was charged, so read the answer back rather than assuming it is accepted.

The payment you get back reports the method it was charged as, in method. It is recorded at the moment of the charge, so a payment made today keeps its method in your reports even if we route that method somewhere else tomorrow.

PreviousCreating a paymentNextConfirming the outcome

On this page

  • The four methods
  • How each one behaves
  • When a method is unavailable
  • Choosing a method