PAYMENT-SIGNATURE — the Agent-side interaction requires no merchant API key.
Two integration modes
Mode 1: Merchant-hosted 402
Your server acts as the x402 server: it returns the 402 challenge to the Agent, receives the signature, then forwards it to Waffo for settlement through
order/create. Suits merchants who want the Agent to stay on their own API end to end and are willing to implement the x402 protocol details.Mode 2: Waffo-hosted 402
You only create the order and hand the Waffo-hosted URL to the Agent; the 402 challenge, signature collection, and settlement all happen on the Waffo cashier. Suits merchants who want to go live quickly without touching x402 protocol details.
order/create endpoint. The only differentiator is whether the request’s x402Info contains paymentSignatureHeader — with a signature it is Mode 1, without one it is Mode 2.
Prerequisites
x402 acquiring requires two provisioning steps, both arranged through the Waffo integration team:
- Enable the CRYPTO / USDC payment product in your merchant contract
- Configure your on-chain receiving parameters on the Waffo side
wallet/inquiry and order/create return error code A0010 (operation not allowed in merchant contract).Current scope
Fetching on-chain receiving parameters
Before constructing the 402 challenge in Mode 1, callPOST /api/v1/wallet/inquiry to fetch the receiving parameters. This endpoint is query-only: it creates no order and validates no amount.
| Field | Description |
|---|---|
network | CAIP-2 network identifier. Sandbox returns Base Sepolia eip155:84532; production returns Base mainnet eip155:8453 |
asset | USDC token contract address (varies by environment and network; Base mainnet in production is 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) |
payTo | Waffo platform receiving address. Waffo receives on-chain and settles to you per your contract |
All three fields come from Waffo configuration — use them verbatim when constructing the challenge. Do not replace
payTo with your own wallet address: the receiving address and amount inside the Agent’s signature are strictly verified before settlement.Mode 1: Merchant-hosted 402
You need to do four things:- Call
wallet/inquiryfornetwork/asset/payTo, then build the 402 challenge from your pricing (amount in atomic units,schemefixed toexact) and return it to the Agent - Take the signature from the Agent’s retry request header
PAYMENT-SIGNATUREand place it as-is intox402Info.paymentSignatureHeaderoforder/create(do not decode and reassemble it) - Decide on release from the synchronous response’s
orderStatus: release onPAY_SUCCESS, wait for the webhook ororder/inquiryfinal state onPAY_IN_PROGRESS, reject onORDER_CLOSE - When releasing, return the response’s
x402Info.x402Responseto the Agent as thePAYMENT-RESPONSEheader — the x402-compliant settlement receipt
goodsInfo, orderRequestedAt, and so on) are identical to a regular one-time payment order — refer to the API Reference.
paymentSignatureHeader is a base64-encoded x402 PaymentPayload. Decoded, it looks like this (generated by the Agent-side x402 SDK — merchants never construct it):
x402Response is the base64-encoded settlement receipt (x402 SettlementResponse), returned only when orderStatus = PAY_SUCCESS. Decoded:
transaction is the on-chain transaction hash, usable for reconciliation and on-chain verification; payer is the Agent’s paying wallet address.
Mode 2: Waffo-hosted 402
You need to do three things:- Call
order/createwithx402Info: { "x402Request": true }(no signature), plussuccessRedirectUrl/failedRedirectUrl - Parse
orderAction(a JSON string) from the response, takewebUrl, and 302-redirect the Agent there; the 402 challenge, signature collection, and settlement all happen on the Waffo cashier from that point - Release resources based on the
orderStatusfrom the webhook ororder/inquiry
webUrl, it receives HTTP 402 with the challenge in the response body (the x402 protocol places the challenge in the body — there is no dedicated response header):
PAYMENT-SIGNATURE request header (corresponding to X-PAYMENT in the x402 spec) — no merchant credentials required:
successRedirectUrl or failedRedirectUrl. The hosted URL serves both browsers (renders a checkout page) and x402 clients (returns protocol responses).
On success, the webhook notification and the order/inquiry response carry x402Info.x402Response (same structure as Mode 1); the rest of the notification is identical to a regular order — see Webhook event types.
Mode comparison
| Dimension | Mode 1: Merchant-hosted 402 | Mode 2: Waffo-hosted 402 |
|---|---|---|
| Who acts as the x402 server (issues 402, receives signature) | Merchant server | Waffo cashier |
| Must implement x402 protocol details | Yes (build challenge, parse signature header) | No |
order/create carries a signature | Yes (x402Info.paymentSignatureHeader) | No |
| Create response | Final status directly, or PAY_IN_PROGRESS | AUTHORIZATION_REQUIRED + hosted URL |
| Redirects | None (Agent talks to merchant API throughout) | Merchant 302 → cashier 302 back |
| Basis for releasing resources | orderStatus from sync response / webhook / inquiry | orderStatus from webhook / inquiry |
| Best for | Merchants building their own x402 service with deep customization | Merchants shipping fast without touching protocol details |
PAY_IN_PROGRESS, AUTHORIZATION_REQUIRED, and so on) match other payment methods — see Payment lifecycle.
Amounts and decimals (two layers of units)
The same transaction carries amounts in two layers — do not mix them:| Layer | Field | Representation | Example (9.99 USDC) |
|---|---|---|---|
| Waffo API layer | orderAmount | String, up to 2 decimal places | "9.99" |
| On-chain / x402 protocol layer | value, maxAmountRequired | String, atomic-unit integer (USDC has 6 on-chain decimals) | "9990000" |
orderAmount; amounts in the 402 challenge and the EIP-3009 signature are always atomic units. In Mode 1 both layers must represent the same value, or settlement verification fails.
Error codes
x402 reuses Waffo’s existing external error codes;msg explains the specific reason:
| Code | Meaning | Common x402 triggers |
|---|---|---|
A0003 | Parameter validation failed | The challenge / signature scheme is not exact; paymentRequestId missing |
A0007 | Transaction currency is not supported | orderCurrency is not USDC, or no usable same-currency USDC contract |
A0010 | Operation not allowed in merchant contract | CRYPTO/USDC payment product not enabled, or on-chain receiving parameters not configured |
FAQ
Which chain does the sandbox use?
Which chain does the sandbox use?
The sandbox runs on the Base Sepolia testnet (
eip155:84532) with USDC contract 0x036CbD53842c5426634e7929541eC2318f3dCF7e; production runs on Base mainnet (eip155:8453) with USDC contract 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. In both environments, always use the network / asset / payTo actually returned by wallet/inquiry.Are other currencies or networks supported?
Are other currencies or networks supported?
Currently only USDC on the Base network. Passing any other
orderCurrency returns A0007.orderStatus is PAY_IN_PROGRESS — can I release the resource early?
orderStatus is PAY_IN_PROGRESS — can I release the resource early?
No.
PAY_IN_PROGRESS only means on-chain processing is underway; it may still succeed or fail. Release resources only on orderStatus = PAY_SUCCESS, converged through the webhook or order/inquiry.Is the 402 challenge in a response header or the body?
Is the 402 challenge in a response header or the body?
In the response body (JSON). There is no header carrying the challenge. The only protocol request header in the x402 interaction is
PAYMENT-SIGNATURE, used by the Agent to submit the signature (corresponding to X-PAYMENT in the x402 spec); the settlement receipt is returned through the x402Info.x402Response field, corresponding to the spec’s X-PAYMENT-RESPONSE.Is this the same thing as the AI integration tool (waffo-integrate)?
Is this the same thing as the AI integration tool (waffo-integrate)?
No. The AI integration tool uses AI coding tools to generate your Waffo SDK integration code; this page is about AI Agents paying you in stablecoin for your services. They can be used together but solve different problems.
Further reading
- Payment lifecycle: order state machine and final-state convergence
- Currency and amounts: amount formats and decimal rules
- Idempotency: idempotency semantics of
paymentRequestId - Webhook overview: signature verification and retry policy
- API Reference: full field definitions for
order/create,order/inquiry, andwallet/inquiry