API reference / Checkouts
Create a checkout
/v1/checkouts One call, one link. Send your customer to checkout_url: they choose how to pay (QR Ph, e-wallets, cards or cash at a counter), give their name if you didn't, and pay. Paid once. Send items (Weav adds them up) or one amount, never both.
Each channel your customer starts is a payment with checkout_reference_id set (its PAYMENT_* webhooks still come). The first payment paid completes the checkout (CHECKOUT_COMPLETED). Never treat a redirect to success_url as proof of payment.
How it works
- Your customer chooses a channel. Weav starts a payment on it for the checkout’s total, the same as a payment you’d create yourself, with
checkout_reference_idset. You get itsPAYMENT_*webhooks as usual. - QR Ph also shows as each bank and e-wallet app that pays it (UnionBank, BDO Pay, GrabPay and more), because many customers know their app better than QR Ph. Choosing one makes a QR Ph payment with
qr_ph_appset: the page shows that app’s logo, colors and steps. Any QR Ph app can still pay it. - They can change their mind: choosing another channel cancels the payment in progress (you get
PAYMENT_CANCELLED) and starts a new one. - When you pay the fee, every channel shows the same total. When your customer pays it (fees on top), each channel shows its own total, fee included.
- The first payment paid completes the checkout:
statusbecomesCOMPLETED,paymentis that payment, and you getCHECKOUT_COMPLETED. - Rarely, a customer pays a QR code and then pays again another way. The second payment is real money: it’s credited like any payment, and Weav refunds it with you.
- A checkout that runs out unpaid becomes
EXPIRED(CHECKOUT_EXPIRED). A payment still in progress, such as a counter code good for 48 hours, keeps it open until that payment ends. If it’s paid, the checkout completes.
sequenceDiagram
autonumber
actor Customer as Your customer
participant Server as Your server
participant Weav
Server->>Weav: POST /v1/checkouts
Weav-->>Server: 201 OPEN, checkout_url
Server-->>Customer: Sends them to checkout_url
Customer->>Weav: Chooses a channel
Note over Weav: Starts a payment on it,<br/>with checkout_reference_id
opt They choose another channel
Weav->>Server: PAYMENT_CANCELLED webhook<br/>for the first payment
Note over Weav: Starts a new payment
end
Customer->>Weav: Pays
Weav->>Server: PAYMENT_COMPLETED and<br/>CHECKOUT_COMPLETED webhooksStatuses
flowchart LR
O[OPEN] --> C[COMPLETED]
O --> E[EXPIRED]
O --> X[CANCELLED]
E -. paid late .-> C
class O warn
class C ok
class E error
class X neutral| Status | Meaning |
|---|---|
OPEN |
Waiting for your customer to pay. |
COMPLETED |
Paid. Final. |
EXPIRED |
Ran out unpaid. A late payment still completes it. |
CANCELLED |
You canceled it. Final. |
Headers
AuthorizationstringRequiredBearerplus your API key. See Authentication.Idempotency-KeystringOptional. A unique value per new checkout, such as a UUID. Retrying with the same key and body returns the stored response; a different body returns 409. Without it, yourexternal_reference_idis the key (a checkout with neither is never matched to an earlier one).Up to 255 characters
Body
JSON, with Content-Type: application/json.
itemsarray of objects | nullAn order, up to 50 items. Each hasname(up to 255 characters),quantity(1 to 9,999) andunit_amount(pesos, a JSON number). Weav multiplies and adds them up; the total must be within your payment limits.Up to 50 items4 fields in
itemsnamestringRequiredUp to 255 charactersquantityintegerRequiredAt least 1At most 9999unit_amountnumberRequiredPesos, as a JSON number.amountnumberquantity×unit_amount.
amountnumber | nullPesos. Within your payment limits.currencystring | nullOne of:PHPdescriptionstring | nullWhat it's for, up to 255 characters. Your customer sees it.Up to 255 charactersexternal_reference_idstring | nullUnique across your checkouts in this mode when given.Up to 64 characterschannelsarray of strings | nullOnly these channels. Default every channel that's on.One of:QR_PHGCASHMAYACARDPAY_AND_GOPALAWANPAYBAYADqr_ph_appsarray of strings | nullQR Ph only as these bank or e-wallet apps, for example a UnionBank link. Needs QR Ph among the channels.One of:BDOCHINABANKGOTYMELANDBANKMETROBANKPNBRCBCROBINSONS_BANKSECURITY_BANKUNIONBANKGRABPAYSHOPEEPAYsave_payment_methodboolean | nullIf your customer pays by card, also saves the card for later charges (auto-debit). Sendcustomer.id. They agree to future charges on Weav's payment page, and their bank's check for this payment also confirms the card. Another way to pay saves nothing: sendchannels: [CARD]to take cards only. The payment'spayment_method_idis the saved card: you getPAYMENT_COMPLETED, thenPAYMENT_METHOD_SAVED. If that payment isn't paid, the card isn't kept (PAYMENT_METHOD_FAILED). Off until Weav turns on saving cards for your account (4224220401).customerobject | nullAll optional. With a name, your customer isn't asked for one; with an email, they get a receipt.4 fields in
customeridstringWithsave_payment_methodonly, and required then: your own ID for this customer. Their saved cards are listed by it (GET /v1/payment-methods?customer_id=).Up to 64 charactersPattern: ^[A-Za-z0-9._:@-]+$namestring | nullUp to 255 charactersemailstring (email) | nullmobile_nostring | null
success_urlstring (uri) | nullcancel_urlstring (uri) | nullHTTPS. Where your customer goes if they leave, or the checkout expires or is canceled.Up to 2048 characterswebhook_urlstring (uri) | nullexpires_in_minutesinteger | nullHow long it stays open, 5 to 10,080 (7 days). Default 1,440 (24 hours).At least 5At most 10080Default: 1440
Responses
201 Created
Checkout created (code 2010300).
What data holds
checkoutobject23 fields in
checkoutreference_idstringexternal_reference_idstring | nulltypestringOne of:ORDERAMOUNTstatusstringOne of:OPENCOMPLETEDEXPIREDCANCELLEDcurrencystringISO 4217. PHP today; more as they're enabled for your account.One of:PHPamountnumberThe total, in pesos.descriptionstring | nullitemsarray of objects4 fields in
itemsnamestringRequiredUp to 255 charactersquantityintegerRequiredAt least 1At most 9999unit_amountnumberRequiredPesos, as a JSON number.amountnumberquantity×unit_amount.
channelsarray of strings | nullOne of:QR_PHGCASHMAYACARDPAY_AND_GOPALAWANPAYBAYADqr_ph_appsarray of strings | nullcustomerobject4 fields in
customeridstring | nullYour ID for the customer, withsave_payment_method.namestring | nullemailstring | nullmobile_nostring | null
save_payment_methodbooleanA card payment also saves the card (the payment'spayment_method_id).checkout_urlstring (uri)success_urlstring | nullcancel_urlstring | nullwebhook_urlstring | nullpaymentanyThe payment that paid it.expires_atstring (date-time)completed_atstring (date-time) | nullexpired_atstring (date-time) | nullcancelled_atstring (date-time) | nullcreated_atstring (date-time)updated_atstring (date-time)
401 Unauthorized
Missing, malformed or unknown API key (code 4010000).
403 Forbidden
The key can't make this request (code 4030000): an address outside the key's IP allowlist, a live key before your live mode is on, or an account that isn't active. A live key sent from a browser is refused (code 4030001): keep live keys on your server.
409 Conflict
The request conflicts with the current state, e.g. an Idempotency-Key reused with a different body (4090001), a request still in progress (4090002), a payment that can't be canceled (4090101) or can't be canceled at the provider yet (4090102, retry shortly), or a webhook still being sent (4090201).
422 Unprocessable Content
One or more fields are invalid (code 4220000), or the channel is off (4220101) or doesn't take the currency (4220102).
429 Too Many Requests
Rate limited (code 4290000). Wait for Retry-After seconds.