A redirect only means the user’s browser came back to your site. It is never proof of payment. The authoritative source of a payment result is the Webhook notification, with the Order Inquiry API as the reconciliation fallback.
The user was redirected back to my site — is the payment successful?
Not necessarily.successRedirectUrl is UI navigation only. Confirm the
result through either of these, in order of preference:
- Webhook — Waffo posts the payment result to your
notifyUrlwhen the payment completes or fails. - Order Inquiry — call
/api/v1/order/inquiryto actively query the order when you need to reconcile.
The user closed the browser before being redirected — did the payment fail?
No. The payment may still complete on the payment method’s side. The webhook fires regardless of what the user’s browser does. If in doubt, call Order Inquiry.What is the difference between webUrl and successRedirectUrl?
They travel in opposite directions:
failedRedirectUrl and cancelRedirectUrl cover the failure and
user-cancellation returns in the same way.
What does each orderStatus value mean?
Only
PAY_SUCCESS and ORDER_CLOSE are final states.
The order timed out — TIMEOUT_CLOSE vs TIMEOUT_CHANNEL_CLOSE?
Both are failure codes on orders closed by timeout. They tell you where
the user dropped off:
Use the split to analyse your conversion funnel:
TIMEOUT_CLOSE means
drop-off before authorization started, TIMEOUT_CHANNEL_CLOSE means the
flow stalled after it started. When Waffo cannot determine whether a request
was initiated, the order falls back to TIMEOUT_CLOSE. The distinction
applies to all payment methods; older orders keep their original code.
Bank transfer / over-the-counter payments: why two notifications?
Payment methods where the user pays outside the checkout session — bank transfer / virtual account (VA) and over-the-counter (OTC) — report in two stages:- Acceptance — after order creation you receive an acceptance result. This is not a final payment status: the user has not paid yet.
- Payment result — the final notification arrives only after the user completes the payment at their bank, ATM, or the counter.
PAY_SUCCESS / ORDER_CLOSE as final,
exactly as for synchronous methods.
I did not receive a webhook. What should I check?
notifyUrlmust be HTTPS (TLS 1.2+) and reachable from the public internet.- Verify the
X-SIGNATUREheader with the Waffo public key — and make sure your endpoint isn’t rejecting valid requests. - Respond with
{"message": "success"}after processing. If Waffo receivesfailedorunknown, Waffo retries the notification on a back-off schedule spread over the following day — see Webhook retry for the schedule. - While investigating, use Order Inquiry to fetch the order state so your business flow is not blocked.
When should I call Order Inquiry instead of waiting?
- As a reconciliation fallback when no webhook has arrived within your expected window.
- When you receive an
Exxxxxunknown error on a request — retry the inquiry until you get a finalPAY_SUCCESSorORDER_CLOSE. - In batch reconciliation jobs.
The order creation failed. Will I still get a notification?
Yes.PAYMENT_NOTIFICATION is sent when a payment completes or fails — a
failed order is notified exactly like a successful one, so do not build your
flow on the synchronous create response alone.
The notification is also richer than that response:
So the failure reason for a rejected order is available in the notification
and through Order Inquiry, not in the create response. Match the notification
to your own record with
paymentRequestId or merchantOrderId; both are
echoed back. Acknowledge it the same way as any other webhook — see
event type list.
How long can the customer still pay after I create the order?
orderExpiredAt is optional. If you omit it, the default expiry time from
your merchant contract applies. What it controls is narrower than it looks:
- It governs the window in which the customer can submit the order on the checkout page (must be UTC+0).
- Once the order has been submitted to the payment method, the expiry is governed by that payment method, not by your value. A small number of payment methods accept a channel-side expiry time from the merchant — the Payin page in the Merchant Portal shows the expiry behavior per payment method.
- Passing a time that has already elapsed is rejected at creation with
A0034(“the order expiry time provided by the merchant has expired”).
An offline or bank-transfer order has been pending for hours. Should I cancel it?
No. For over-the-counter (OTC) and virtual-account / bank-transfer payments the customer pays outside the checkout session, so a long pending period is normal rather than a symptom of failure — and the automatic close time differs per payment method. Do not infer failure from elapsed time, and do not release or void the purchase on your side while the order is still open: wait for the final notification, or poll Order Inquiry. OnlyPAY_SUCCESS and ORDER_CLOSE
are final.
I sent the same request twice at the same time and got an error. Did either go through?
A concurrency rejection is protection, not a business failure. Creating the same order from two requests in parallel returnsA0040 (“the order cannot
be created concurrently”) instead of creating two orders.
Handle it like this:
- Serialize calls per order — one in-flight request per order at a time, rather than parallel retries.
- Resolve the state, do not guess it. Call Order Inquiry to see what the order actually is before deciding anything.
- When you retry the original request, reuse the same
paymentRequestId— it is the idempotency key. See the error code quick reference forA0011and forE-class unknown-status handling.
The user says they paid, but the order shows failed or timed out
Occasionally a payment completes on the payment method’s side after the Waffo order has already been closed as timed out (“failed first, succeeded later”). How to handle it:- Never fulfil based on a user’s payment screenshot. Fulfil only when a
webhook or Order Inquiry reports
PAY_SUCCESS. - Report the case to Waffo support with the order IDs. Waffo reconciles the order with the payment method side; the payment is then either confirmed to you or the debited amount is returned to the user.
- The user may be asked for additional details to locate the transaction, so collect what they can share — payment time, amount, and the payment method’s transaction reference.