XAgent Blog

Home Blog Market Launch Store

x402 clients now refuse to sign payments over one dollar

Three changes merged into x402 between August 11 and 13 moved the client from signing whatever a server quotes to checking first. The new default cap is one dollar.

By XAgent Team · 2026-08-17

If you quote an agent more than a dollar this week, a default x402 client will walk away without telling you why. Three changes merged into x402-foundation/x402 between August 11 and 13 shift the client's posture from "sign what the server asked for" to "check first, then sign". None of them are security advisories. All three change behaviour you have already shipped against.

The through-line is worth stating plainly, because it is a design decision and not a bug fix. Until this month an x402 client's job was to satisfy a payment requirement. Now its job is to decide whether the requirement is one it should satisfy at all.

A one-dollar cap, applied before the signature

PR #3124, merged August 13, adds spendControls to x402Client. Its description reads: "Normalize default-asset declarations across mechanism packages and add declarative client spend controls that enforce limits before payment signing."

The placement matters more than the limit. From the same PR: "spendControls on x402Client: Clients now apply a default $1 USD cap on recognized pegged assets (plus optional per-asset atomic caps and an asset allowlist) in selectPaymentRequirements, before user policies run; paywall and MCP forward or disable as appropriate."

Two consequences fall out of before user policies run. The gate sits in requirement selection, not in a callback you can override afterwards. A policy you wrote to permit a five-dollar purchase runs downstream of a check that has already discarded the option. And the check happens before signing, so there is no signed payload to inspect when it fires. A merchant watching server-side sees a 402 go out and nothing come back.

Raising it is explicit:

const client = x402Client.fromConfig({
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(signer) }],
  spendControls: {
    maxAmountPerPayment: '$5', // USD cap on default assets; false to remove
  },
});

The buyer-facing docs state the same rule without the implementation detail: "By default, the x402 client only pays recognized USD-pegged assets (e.g. USDC) and caps each payment at $1." Setting spendControls: false removes the whole mechanism — "any asset, no caps" — which is a blunter instrument than most integrations want.

If what you actually wanted was to ask a human, the docs point somewhere else: "Spend controls run before any custom policies and before the payment payload is signed. For interactive approval flows (e.g. prompting the user), use onBeforePaymentCreation hooks instead." Spend controls are a static ceiling, not an approval prompt. Wiring a confirmation dialog into the cap is fighting the design.

The second half of the change is the asset allowlist. The default permits only recognized USD-pegged assets; anything else needs an explicit allowedAssets entry, optionally with its own cap in atomic units. The repo is explicit about what "recognized" means: "By default the client only allows assets findDefaultAsset recognizes, with a $1 USD spend cap (maxAmountPerPayment)." If you price in a token that table does not resolve, you are not competing on price — you are invisible.

The client now checks who it is signing for

PR #3133, merged the same day, is four lines of description and a real change of trust model: "Require SIWx challenge domain / uri (and resources) to match the origin of the 402 response URL before creating a signature. On mismatch, abort without signing or paying".

Sign-In-With-X lets a client prove identity to a resource server. Before this change, the client signed the domain and uri the server put in the challenge. That is the wrong party holding the pen: a server could hand over a challenge naming someone else's origin and collect a signature endorsing it.

The fix takes the origin from the transport rather than the payload — the final URL of the 402 response, after redirects — and refuses to sign when the challenge disagrees. If you terminate TLS on one hostname and issue challenges naming another, that arrangement stops working. This is the same class of problem as the verification gaps we walked through in the x402 paywall fixes: the payload is not allowed to be the authority on its own context.

On Solana, the payer chose the fee and the facilitator paid it

PR #3120, merged August 11, states the problem in one sentence: "On SVM the facilitator is the fee payer, so the payer chooses a priority fee that the facilitator pays."

The static verification path, per the PR, "caps the compute unit price at a hardcoded MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS (5,000,000 µLamports = 5 lamports/CU)", "does not cap the compute unit limit at all", and "never checks the required-signature count, though each signature costs the fee payer 5,000 lamports of base fee."

The PR does the arithmetic itself, so we can quote rather than derive it: "At the current ceiling one transaction can direct 1,400,000 CU × 5 lamports/CU = 7,000,000 lamports — 0.007 SOL of priority fee, ~1,400× the base fee — for a payment that may be worth a fraction of a cent."

That is the shape of every sub-cent payment rail: the settlement cost is set by someone who does not pay it. The change makes the ceilings operator-configurable rather than compiled in. Anyone running their own facilitator for micropayments should set them deliberately, because the shipped defaults were chosen for a different workload than sub-cent metering.

What this means if you are quoting agents

The three changes point the same direction, and it is a direction merchants should plan for rather than discover in a support ticket. Client-side defaults are becoming conservative, and conservative defaults are the ones most agents will run.

Practically, for anyone accepting agent payments today:

  • Price a first call under a dollar, or expect default clients to skip it silently. Whatever your headline price, an agent's first interaction with your service should clear the default gate.
  • Quote in an asset the client already recognizes. An exotic token is a configuration burden you are asking the buyer to carry before they have bought anything.
  • Do not put authoritative context in a payload you also control. Anything the client can read off the transport, it eventually will.
  • If you run a facilitator, set your own chain-layer ceilings. The defaults are not tuned for your price point.

None of this is reachable by reading a spec version number. It came out of three merged pull requests in a repository that now lives under the x402 Foundation rather than Coinbase — the coinbase/x402 README states "We've moved the x402 repo under the x402 Foundation repo" and calls itself "a development fork" — and the behaviour changed for anyone who upgraded without reading them. The open execution market we are building assumes exactly this. The protocol layer will keep moving underneath merchants. The operations layer has to absorb that movement, so a price quoted on Monday still clears on Friday.

What's next

The interesting question is what happens when these defaults meet real catalogues. A one-dollar cap is a sensible floor for a spec that started with per-request API metering. It is an awkward fit for a five-dollar eSIM or a forty-dollar booking, and the gap will be closed either by buyers raising limits or by sellers restructuring what a single payment covers.

We will be watching which one wins, because it decides whether agent commerce settles into many small payments or fewer large ones — and those are different businesses. If you are pricing an agent-facing service now, assume the buyer's client is more suspicious than it was last week, and test against the defaults rather than against your own configuration.

Keep reading

  • Agent checkout just grew credit terms. Who authorised them?
  • MCP removed sessions. Your shopping cart is now a handle
  • The x402 bugs that let unpaid requests reach paid handlers