API reference / Payments
Create a payment
/v1/payments Creates a payment on one channel and returns what the customer does next (next_action): scan a QR code, go to a checkout page, or pay at a counter with a payment code.
With a test key, the checkout page is Weav's test checkout, where you pay, decline or expire the payment. Live payments run through the providers.
Never treat a redirect to your success_url as proof of payment. Wait for the PAYMENT_COMPLETED webhook, or read the payment with GET.
What your customer does next
Payment link (the default)
By default every payment comes back as a payment link: send your customer to next_action.checkout_url, Weav’s payment page. Weav sets the payment up with the provider when your customer opens it, so expires_at starts as the link’s lifetime (24 hours) and becomes the provider’s window (for example 15 minutes for a QR Ph code) from that moment. For QR Ph the page shows the code and how-to-pay steps for their bank or e-wallet app (set qr_ph_app to start with one). The QR Ph and Pay & Go examples ask for the raw QR string or payment code instead, with "next_action_format": "DIRECT".
Your customer’s name. Weav needs it on every payment, for anti-money-laundering and fraud checks. Send it in customer.name if you have it. If you don’t, leave customer out: Weav’s payment page asks your customer before anything is set up. With DIRECT there’s no Weav page, so customer.name is required.
Webhooks for this payment. They go to your webhook URL. To send one payment’s webhooks somewhere else, set webhook_url on it.
QR Ph, shown by you
With the raw string, render qr_string as a QR code and show the steps in next_action.instructions. Any QR Ph bank or e-wallet app can scan it. A QR Ph code expires 15 or 60 minutes after it’s made, depending on your account’s QR Ph provider; expires_at has the exact time.
Lay it out the QR Ph way, with the QR Ph symbol in the center: bank and e-wallet apps expect it, so a code that’s off may not scan. See Showing a QR Ph code for the exact layout and a sample.
Redirect: GCash, Maya and cards
Send your customer to next_action.checkout_url. After they pay or cancel there, they come back through Weav first: Weav checks the result with the provider right away, then sends them to your success_url (paid) or cancel_url (failed, expired or canceled). Both are optional: without them, your customer stays on Weav’s result page. If the provider is still confirming, they see a Weav page that updates by itself. Always rely on the webhook or GET /v1/payments/{reference_id} for the final status, not on which URL they land on.
A GCash payment expires 10 minutes after it’s created, Pay with Maya after 15 minutes and a card payment after 60.
Mobile apps. The GCash page has an “Open in GCash” button that uses a gcash:// link. If you load checkout_url in a WebView, hand gcash:// links to the operating system. On Android, use shouldOverrideUrlLoading. On iOS, use decidePolicyForNavigationAction. Otherwise the customer sees an unknown-scheme error.
Over the counter
Give the customer the payment_code. At a Pay & Go kiosk they choose Eplayment on the screen, enter the code and pay in cash. With PALAWANPAY and BAYAD they go to a Palawan or Bayad counter, pay to Eplayment and show the code. Counter payments expire after 48 hours.
Headers
AuthorizationstringRequiredBearerplus your API key. See Authentication.Idempotency-KeystringOptional. A unique value per new payment, 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.Up to 255 characters
Body
JSON, with Content-Type: application/json.
channelstringRequired, unless you sendpayment_method_id. One ofQR_PH,GCASH,MAYA,CARD,PAY_AND_GO,PALAWANPAY,BAYAD. The channel must be on for your account, or the response is 422 (4220101).One of:QR_PHGCASHMAYACARDPAY_AND_GOPALAWANPAYBAYADpayment_method_idstring | nullCharge a saved payment method instead (auto-debit), with no payer present. Leave outchannelandcustomer. Only anACTIVEone, or 4224220103. A card is usually paid at once (COMPLETED); if the bank asks your customer to confirm again, it'sPENDINGwithnext_action.typeREDIRECT.save_payment_methodboolean | nullCARDonly. Also saves your customer's card for later charges (auto-debit), so you don't needPOST /v1/payment-methodsfirst. Sendcustomer.id. On Weav's payment page, your customer agrees to future charges and pays; their bank's check (3DS) for this payment also confirms the card. The response'spayment_method_idis the new method,PENDINGuntil the payment is paid. You getPAYMENT_COMPLETED, thenPAYMENT_METHOD_SAVED. If the payment isn't paid, the card isn't kept (PAYMENT_METHOD_FAILED). Off until Weav turns on saving cards for your account (4224220401).currencystringRequiredISO 4217. PHP today; more as they're enabled for your account.One of:PHPamountnumberRequiredMajor unit, up to the currency's decimals (2 for PHP). Must be within your payment limits (GET /v1/channels; by default ₱0.01 to ₱50,000.00), or the response is 422.More than 0external_reference_idstringRequiredYour order or invoice reference. Unique across your payments in this mode (test and live are separate); reusing one returns 422.Up to 64 charactersdescriptionstring | nullUp to 255 characters. Your customer sees it on their emailed receipt (sent when you give their email).Up to 255 charactersnext_action_formatstring | nullHOSTED(default, every channel) returnsnext_action.checkout_url, Weav's payment page; the payment is set up with the provider when the customer opens it.DIRECTsets it up right away and returns the rawqr_string(with instructions), the provider'scheckout_urlor thepayment_code.One of:HOSTEDDIRECTqr_ph_appstring | nullQR Ph only. Tailors the how-to-pay steps to one bank or e-wallet app; any QR Ph app can still pay.One of:BDOCHINABANKGOTYMELANDBANKMETROBANKPNBRCBCROBINSONS_BANKSECURITY_BANKUNIONBANKGRABPAYSHOPEEPAYcustomerobject | nullThe person paying. Stored encrypted; with an email, Weav emails them a receipt once the payment is paid. Weav needs the name for every payment (anti-money-laundering and fraud checks). Leave it out withHOSTEDand Weav's payment page asks your customer before they pay; withDIRECTthere's no Weav page, sonameis required.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._:@-]+$namestringOne field; not split into first and last name.Up to 255 charactersemailstring (email) | nullUp to 255 charactersmobile_nostring | nullA Philippine mobile number.Up to 20 characters
webhook_urlstring | nullOptional. All of this payment's webhooks go here instead of your webhook URL, whatever its events list says. Public HTTPS only, signed with your signing key.Up to 2048 characterssuccess_urlstring (uri) | nullOptional, HTTPS. Where your customer goes once the payment is paid. Without it, they stay on Weav's result page. Never treat this redirect as proof of payment.Up to 2048 characterscancel_urlstring (uri) | nullOptional, HTTPS. Where your customer goes if they leave without paying (the payment failed, expired or was canceled). Without it, they stay on Weav's result page.Up to 2048 characters
Responses
201 Created
Payment created (code 2010100).
What data holds
paymentobject32 fields in
paymentreference_idstringexternal_reference_idstring | nullYours. For a checkout's payment, the checkout's (null when it has none).checkout_reference_idstring | nullThe checkout this payment was started from, if any.payment_method_idstring | nullThe saved payment method it was charged to, or the one it saves the card to (save_payment_method), if any.provider_reference_idstring | nullThe provider's transaction ID, once the provider has one.channel_reference_idstring | nullA reference from the channel that is unique to this payment, once the payment completes. Null for channels whose numbers can repeat; those are in references.referencesobjectThe provider's other numbers for this payment, keyed by type:invoice_number(the 6-digit QR Ph invoice number),receipt_number(Maya) ortransaction_id(GCash). Saved once the provider confirms the payment; {} until then. They can repeat across payments: search with them, never identify a payment by one alone.3 fields in
referencesinvoice_numberstringreceipt_numberstringtransaction_idstring
channelstringOne ofQR_PH,GCASH,MAYA,CARD,PAY_AND_GO,PALAWANPAY,BAYAD.One of:QR_PHGCASHMAYACARDPAY_AND_GOPALAWANPAYBAYADcustomerobjectThe person paying, as you sent it. The email and mobile number turn null once Weav's retention period ends.3 fields in
customernamestring | nullemailstring | nullmobile_nostring | null
currencystringISO 4217. PHP today; more as they're enabled for your account.One of:PHPamountnumberfeenumber | nullNull until a rate applies.totalnumber | nullamountplusfee, calculated by Weav. Null whilefeeis null.fee_bearerstringMERCHANT, the fee comes out ofamount(default).PAYER(fees on top), the customer is chargedamount+feeand you receive the fullamount.One of:MERCHANTPAYERamount_chargednumberWhat the customer is charged.amount, ortotalwhenfee_bearerisPAYER.amount_refundednumberThe total refunded so far. The payment turnsREFUNDEDonce it equalsamount.refundsarray of objectsRefunds Weav recorded for this payment, oldest first. Refunds are made by Weav support on request.4 fields in
refundsreference_idstringamountnumberprovider_reference_idstring | nullrefunded_atstring (date-time)
statusstringOne of:PENDINGCOMPLETEDFAILEDCANCELLEDREVERSEDREFUNDEDdescriptionstring | nullAs you sent it.success_urlstring (uri) | nullcancel_urlstring (uri) | nullwebhook_urlstring | nullWhere this payment's webhooks go, when not your webhook URL.next_actionobjectWhat your customer does next.typeisDISPLAY_QR,REDIRECT,PAY_AT_COUNTER, or null once the payment is final.qr_string,checkout_urlandpayment_codeare each null unless they apply. WithHOSTED(the default),typeisREDIRECTandcheckout_urlis Weav's payment page (the test checkout with a test key), for every channel. For QR Ph,qr_ph_appis the app you chose, andinstructionslists the how-to-pay steps (title,description) when you asked forDIRECT.6 fields in
next_actiontypestring | nullOne of:DISPLAY_QRREDIRECTPAY_AT_COUNTERqr_stringstring | nullQR Ph payload to render as a QR code: error correction Q (M at minimum), a white quiet zone of at least 4 modules, and the full-color QR Ph symbol on a white box 23.81% of the code width (quiet zone excluded) in the exact center.checkout_urlstring (uri) | nullpayment_codestring | nullFor over-the-counter channels.qr_ph_appstring | nullQR Ph only. The bank or e-wallet app the steps are tailored to.instructionsarray of objects | nullQR Ph withnext_action_formatDIRECTonly. How-to-pay steps to show the customer.2 fields in
instructionstitlestringdescriptionstring
test_checkout_urlstring (uri) | nullTest mode only: the test checkout page, where you pay, decline or let this payment expire, for every channel (a counter payment withDIRECThas no other way to finish). Anyone with the link can open it. Null in live mode.failureobject | nullcodeandmessagewhen the payment failed. Codes:EXPIRED,DECLINED,PROVIDER_ERROR.2 fields in
failurecodestringOne of:EXPIREDDECLINEDPROVIDER_ERRORmessagestring
expires_atstring (date-time)When an unpaid payment fails (failure.codeEXPIRED).completed_atstring (date-time) | nullWhen the customer paid, as the provider reports it.failed_atstring (date-time) | nullWhen the payment failed.cancelled_atstring (date-time) | nullWhen the payment was canceled.reversed_atstring (date-time) | nullWhen the payment was reversed.created_atstring (date-time)When Weav created the payment.updated_atstring (date-time)When the payment last changed.
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.
501 Not Implemented
This channel isn't live for your account yet (code 5010100); use a test key.