Which endpoints exist, and what do I need to call them?
All five arePOST, JSON in and out, signed exactly like /api/v1/order/create.
Two access rules catch most first calls. API keys are scoped: a key issued for payin only cannot
call these endpoints and fails with
A0004 “Permission denied” before the signature is even checked —
if a request that signs correctly elsewhere returns A0004, ask Waffo for a key whose scope includes
withdrawal. And merchantId in the body must match the MID your key resolves to, otherwise
A0003. /api/v1/withdraw/inquiry is the exception: it carries no merchantId — the MID comes from
the key, and an order belonging to another MID is reported as not found.
How do the three withdrawal calls fit together?
consult— sendcurrency, optionallyamount. Returns the fee, expected received amount, your agreement’s limits and the beneficiary account, so you can validate before committing.create— send the amount you settled on plus awithdrawRequestIdof your own.inquiry— poll until the status is final, or wait for the callback on yournotifyUrl.
create is deliberately not a completed withdrawal: the approval record and the balance deduction
are raised asynchronously, so a successful create normally returns IN_PROGRESS — treat it as
“accepted”, never as “paid”.
What does consult tell me, and what if I leave the amount out?
Omitamount and consult answers “how much could I withdraw in one go right now”: your
withdrawable balance — the settlement account’s available balance, reduced by the reserve
shortfall when the reserve balance is negative — capped at the agreement’s maximum.
The realised
fxRate and actualReceiveAmount appear on inquiry once the order completes.
What does create require, and how does idempotency work?
Leave
bankAccountId out and the agreement’s single bound account is used automatically; if the
agreement has more than one, omitting it fails with a parameter error asking for it. accountNo
matters only if you hold more than one balance account in the same currency — which happens after
re-contracting with a different Waffo entity.
withdrawRequestId is the idempotency key, scoped to your MID. Replay it with the same amount and
currency and you get the original order’s result back — no second withdrawal. Replay it with a
different amount or currency and the call fails with A0011 “Idempotent param mismatch error”. So
a timeout is safe to retry with an identical body; a genuinely new withdrawal needs a new id.
How do I poll status, and what do the statuses mean?
inquiry needs at least one of withdrawRequestId or withdrawOrderId; neither is a parameter error.
withdrawOrderId wins when both are sent, and if the two disagree the call fails rather than
returning the wrong order.
The Portal shows a longer, finer-grained status list for the same order — the mapping is in
Withdrawal & Batch Payout FAQ. On success
inquiry
backfills actualReceiveAmount, fxRate (always 1.00 for same-currency), bankRefId and
withdrawCompleteTime; on failure it carries failureCode and failureReason.
Which accounts does a balance query return?
Your settlement accounts only — one row per settlement currency, merged per contracting entity. Passcurrency to narrow it, or omit it for all currencies. The pending-settlement balance is not
exposed here.
How far back can an account-history query go, and what is in a row?
All times on this endpoint are UTC — both thestartTime / endTime you send (ISO-8601 local
date-time, e.g. 2026-08-01T00:00:00) and the transactionTime returned (...Z). The Portal
presents Account History in UTC+8 instead.
- Omit both bounds and you get today only; send both for anything else. The window may not exceed 180 days, and a query resolving to more than 60,000 rows is refused.
- Unlike the Portal’s Account History, this endpoint covers both the settlement and the reserve
ledger. Filter with
accountType=MERCHANT_SETTLEMENTorMERCHANT_RESERVE; omit it and both are returned.currencyandaccountNonarrow it further, and a filter naming an account you do not hold returns an account-not-found error rather than an empty list.
accountNo, accountType, currency, amount, accountDirection
(CREDIT / DEBIT), newBalance (the balance right after the movement), transactionTime,
businessId (the related business order) and businessType — codes such as SETTLEMENT,
WITHDRAWAL, RESERVE_WITHHOLDING, RESERVE_RELEASING, RESERVE_ADJUSTMENT and ADJUSTMENT, best
matched case-insensitively. Their meanings are in Balances & Account History.
Which errors should I handle explicitly?
Still stuck? Contact support with the
withdrawRequestId or
withdrawOrderId and the timestamp of the call.