Skip to main content
Several Waffo pages say “see the field requirements table” or “see the error code list”. Those tables are collected here. This page is the full lookup; two neighbouring pages cover the same ground from a different angle and are usually the faster read: The one thing you cannot get from the quick reference is which API family a code belongs to — and several codes mean different things on different families. That is the first question below.

Does the same error code mean the same thing on every Waffo API?

No. The numeric part of a code is scoped to the API family, not global. Three codes in particular are traps: So an A0013 on /api/v1/payout/create means your earlier request with that payoutRequestId is still in flight — wait, then inquire on it before submitting again; an A0013 on /api/v1/order/cancel is terminal and must not be retried. Always resolve a code against the family of the endpoint you called. The prefix meaning is stable everywhere: A merchant-related, B user-related, C system-related, D risk rejection, E unknown (keep inquiring until a final status).

Which payee fields must I send on a payout, and which go inside payoutMethodProperty?

Requirements are a matrix of receiving country × payout method, not a property of the API. payeeFirstName, payeeMiddleName, payeeLastName and payeeIDType are declared conditional in the specification for exactly this reason. Two identity rules are stated outside the matrix, in the field definitions themselves: For every other corridor the payee fields are validated downstream rather than by a country rule, so send everything you hold. Rows are added to this matrix as corridors are onboarded — treat it as a floor, not a ceiling, and let a rejection tell you what is actually missing.

Which fields belong in payoutMethodProperty rather than at the top level?

payoutMethodProperty is a JSON string (max 512 characters), not an object, and it is the only place bank routing detail is accepted: The payee’s account identifier itself is not in payoutMethodProperty — it is payoutInfo.payoutMethodUserAccountNo, and its format depends on payoutMethodType: a bank account number for BANK_ACCOUNT, and for EWALLET the wallet’s own account number or public user identifier. payoutMethodName is the wallet name for EWALLET and is empty for BANK_ACCOUNT. See Payout FAQ for the create / inquire / notify loop itself.

What values can purpose take on a payout?

purpose on /api/v1/payout/create is required for payouts to mainland China and must then be one of the values below; for other corridors it is optional and passed through to the receiving side as supplied. The accepted values: Pick the one that genuinely describes the payment. Some corridors — mainland China in particular — are validated against it. Two adjacent free-text fields are often confused with it. description (max 128 characters) is printed on the payee’s bank or wallet statement, so keep it short: banks and wallets truncate it, and roughly 16 English words or 10 Chinese characters is the practical ceiling. extendInfo (max 128 characters, JSON) is echoed back to you untouched and never reaches the payee.

Which “Optional” fields on /api/v1/order/create become mandatory for certain payment methods?

The acquiring specification marks goodsInfo, addressInfo and most of userInfo optional, because whether they are required depends on the payment method actually used. Aggregated by payMethodType: Read this as sizing information, not as a contract: the same payMethodType can differ between markets, which is why several cells say varies by market. BNPL is the only type that requires the full itemised basket everywhere it is offered. If you use Waffo’s hosted cashier you can usually ignore this table. When the chosen method needs user information you did not supply, the buyer is redirected to the cashier and the cashier collects it. The table matters where there is no cashier in the flow. For the authoritative pattern — submit, read the returned missing-field list, resend — and for the full set of field paths that can be requested, see Conditionally required fields by payment method.

What does orderAction.actionData contain?

orderAction is returned by /api/v1/order/create and /api/v1/order/inquiry when orderStatus = AUTHORIZATION_REQUIRED, i.e. the buyer still has something to do. actionType is WEB (redirect the buyer to webUrl) or DEEPLINK (open deeplinkUrl). actionData is the alternative to redirecting: it carries the raw payment instrument so you can render your own cashier page. Only the subset relevant to the chosen payment method appears in any given response, so treat every field as optional and render what is present.

Payment voucher fields

Amount and FX fields

Bank transfer fields

A virtual account (bankAccount generated per order) reconciles on the account number alone; a shared collection account reconciles on referenceNumber. If both are returned, show both and treat referenceNumber as mandatory buyer input.

Full error code table — payout

/api/v1/payout/create, /api/v1/payout/inquiry and the payout notification. Note what payout does not have: no A0015–A0047. If you see one of those on a payout endpoint, you are looking at the wrong table.

Full error code table — acquiring

/api/v1/order/create, /inquiry, /cancel, /refund, /capture, /api/v1/refund/inquiry and the payment and refund notifications. The acquiring family is the widest, and the quick reference carries additional acquiring codes beyond this specification revision. Where the two disagree, the quick reference is the newer list.

Full error code table — subscription

/api/v1/subscription/create, /inquiry, /cancel, /manage, /change, /change/inquiry, /update and the subscription notifications. Two codes are unique to this family and worth handling explicitly: A0025 (a subscription must run for more than one period) and A0028 (asking for the management URL before the first payment has settled).

Full error code table — withdrawal, balance and transaction limit rules

/api/v1/account/balance/inquiry, /api/v1/account/history/inquiry, /api/v1/withdraw/consult, /create, /inquiry, the withdrawal notification, and /api/v1/risk/transactionlimit/create, /update, /inquiry. A0100–A0102 exist only here and appear only on the transaction limit rule endpoints. They are not in the general quick reference, so a A0100 is not a malformed A0010.

I received a code that is not in any of these tables. What is it?

Every code Waffo returns on a signed public API matches one of these shapes: 0, or a single letter A–E followed by four digits. A value in any other shape — a longer string, a different prefix, a mixed alphanumeric identifier — is not part of the public error contract and should not be branched on in your integration. Log it with the paymentRequestId / payoutRequestId and contact support; treat the transaction the way you would treat E0001 until you have a definitive status from an inquiry call. The same applies to a public-shaped code that is simply not in the table for the family you called: inquire the order for its real status rather than inferring an outcome from the code.