402 Payment Required is decoded, quoted against your policy, signed locally, and retried with an X-PAYMENT header — all inside the call you already made.
You never construct a payment yourself. You decide whether one is allowed.
Spending controls
x402 payments are non-refundable, and an autonomous agent with no policy is an unbounded spender. Three controls, all optional and all strongly recommended:
The ceiling is expressed in the advertised asset’s base units, as an integer string. Base units are the only unambiguous unit available at that point: the quote does not always carry the asset’s decimals.
The quote
onPaymentRequired receives everything the server advertised, so a policy can branch on the asset and the network, not only the number:
What the SDK guarantees
- Every signed value comes from the live header. Chain, asset, transfer rail, amount, recipient, and the authorization window are read from the
PAYMENT-REQUIREDresponse, never hardcoded. - No
txIdis ever paid twice. The client remembers what it has paid for. The API reserves a payment and settles it only after the operation confirms, so apendingstatus must not be paid again — paying twice for onetxIdis money gone. - A paid send is never retried.
429,5xx, and transport failures retry with jittered backoff, but not a send for which a payment was already authorized. If that one fails, the error carries.paymentso you can reconcile the charge. - Payment metadata stays a sibling.
result.paymentis never spliced into the response body.
What is free and what is not
Preparing is free inbrickken-relayed mode only. The two client-controlled modes split the same total evenly across prepare and send — so a prepare-only call in client-signed mode is a paid call.
Dapp writes authenticated with an API key are not x402-priced at all; they draw on the per-method credit balance attached to your key, and exhausting one raises
CreditsExhaustedError carrying .method.
See Pricing for the per-operation table.
Payment asset
On Base Sepolia the x402 payment asset is Circle USDC:USDC, version 2, 300-second authorization window). A live sandbox quote looks like this:
Rate limits on prepare
Preparing is free in relayed mode, but not unlimited. The API caps how many prepared transactions a wallet may have outstanding and answers429 with Too many outstanding prepared transactions for this wallet.
The SDK honours the Retry-After it comes with, but only for the configured number of attempts — three by default. After that it throws RateLimitError, carrying .retryAfterSeconds. A loop that prepares without sending will therefore slow down and then fail: treat the quota as a limit to respect, not a delay to wait out.
Errors
Every failure class, and which ones carry payment state.