How to Use x402 From the Client Side
Make the request, and when a 402 comes back, parse the payment terms it carries. Decide whether to pay against a policy rather than accepting whatever is asked. Settle on the named network, then retry the original request with proof of payment attached. The decision step is where the real work is.
The four steps
Make the request normally. No special handling up front. Most requests will not return 402 at all, so payment logic belongs on the error path rather than in the happy path.
Parse the challenge. A 402 response carries machine-readable terms: the amount, the asset, the destination address, the network, and how long the quote remains valid. All of it is data your client reads rather than a page a human interprets.
Decide, then settle. This is the step the protocol does not specify and the one that determines whether the system is safe. Once decided, the payment is a transfer on the named network in the named asset.
Retry with proof. Repeat the original request with evidence of payment attached. The server verifies and serves the resource.
What makes this pleasant to implement is that it fits the shape of code you already have. A 402 is an HTTP status like any other, and payment handling slots into the same place as authentication retry logic. What makes it interesting is the third step, because everything else is plumbing.
The decision step
An agent that pays whatever it is asked is not making a decision. It is a wallet with a network connection, and the first hostile or misconfigured server it meets will demonstrate why that matters.
A policy evaluated before settlement should cover at least the following.
Amount ceilings. A maximum per call, and a maximum over a period. The per-call limit stops one absurd quote; the period limit stops a thousand reasonable ones.
Counterparty. Is this destination one we have paid before, or on a list we maintain? Deny by default and allow by rule is the right posture, because the cost of refusing a legitimate payment is a failed request and the cost of the reverse is money gone.
Expected price. If a resource cost one amount yesterday and asks a hundred times that today, something has changed and the correct response is to stop rather than to pay and log it.
Purpose. Does the current task have any business buying this? An agent researching a topic has no reason to be settling payments to a destination unrelated to it.
Budget remaining. Not the wallet balance, the budget for this task. Those are different numbers and confusing them is how a single task consumes a float meant for a week.
Critically, this policy has to be enforced outside the model. An agent that can be argued into ignoring a limit does not have a limit, so the ceiling belongs in the credential and the policy layer rather than in an instruction.
Bind the payment to the request
Agents retry aggressively, and a timeout tells you the response did not arrive rather than that the payment failed. Generate an identifier for the intent, attach it to the payment, and check for an existing settlement before paying again. Without this, ordinary retry behaviour becomes repeated payment for one unit of work, which is the most common expensive bug in client implementations.
Practical details that bite
Quote expiry. The challenge says how long its terms are valid. A client that spends ten seconds deliberating and then settles against an expired quote has paid for something the server will not serve. Check the window before settling, and treat an expired quote as a fresh request rather than a payment to push through.
Gas. Settlement requires the network's native asset for fees, separately from the asset being sent. A float holding only the settlement token is a payment system that cannot pay, and it fails at the moment of first use.
Confirmation policy. Decide how much finality you require before retrying. Waiting for deep confirmation is slow; retrying immediately risks presenting proof the server has not seen yet. On a fast-finality network this window is short, which is a large part of why network choice matters for this use.
Failure recording. Log the request identifier, the quote, the settlement and the outcome together. When something goes wrong the question is always which payments corresponded to which requests, and that cannot be reconstructed later.
Custody. The client needs signing authority, which means key material somewhere. Holding it in a file the agent can read means a compromised agent can drain the balance directly. Keys in the operating system keychain with a session-scoped, capped delegation are what make the spending limit real rather than advisory. That is the shape CryptoCadet implements: a bounded float on Base, non-custodial, with the cap enforced at the signing boundary rather than in a prompt.
Frequently asked questions
- How does a client use x402?
- Make the request, and on a 402 response parse the machine-readable payment terms it carries: amount, asset, destination, network and quote validity. Evaluate whether to pay against a policy, settle on the named network, then retry the original request with proof of payment attached.
- What should an agent check before paying an x402 challenge?
- Amount ceilings per call and per period, whether the counterparty is allowlisted, whether the price matches what this resource cost previously, whether the current task has any reason to buy it, and how much of the task budget remains. Enforce all of it outside the model.
- How do you stop retries from paying twice?
- Bind every payment to an identifier for the intent that caused it, and check for an existing settlement before paying again. A timeout tells you the response did not arrive, not that the payment failed, so without this ordinary retry behaviour becomes repeated payment for one unit of work.
- What happens if a quote expires before you settle?
- You have paid for something the server will not serve. The challenge states how long its terms are valid, so check the window before settling and treat an expired quote as a fresh request rather than a payment to push through regardless.
