Selling over x402? These are the failures buyers hit. Test your own endpoint. It takes seconds and is free. Test your endpoint → Read the launch post: Can agents actually pay you?
How we tested
We used a purpose-built test buyer, hard-capped at $0.05 per request and $5.00 in total, paying from a dedicated test wallet. Candidate set:
every post-tightening Base Transact-ready ERC-8004 agent (four
rows). For each candidate the pipeline is: probe the common
/pricing /
/.well-known/x402.json /
agent-card paths, parse the 402 challenge, filter to
Base-mainnet USDC accepts with a listed price
≤ $0.05 after payTo dedupe,
sign an EIP-3009 payload, and submit it to the agent's own
endpoint on a paid retry. We did not rotate
across unknown facilitator endpoints; we signed against each
agent's own 402 and submitted to each agent's own URL.
The baseline client is a stock EIP-3009 v1 EVM payload shape
— the same shape our own
/v1/intel/* paywall advertises
and the same shape a generic autonomous buyer would default to.
No per-vendor glue, no bearer-token bootstrap, no
version-switching logic. If the ecosystem is interoperable, it
pays. If it isn't, we record what fails and why.
Headline
- Candidates scanned: 4
- Payable at the $0.05 cap after
payTodedupe: 3 - Attempted paid requests: 3
- Delivered + substantive responses: 0
- Failed at paid retry: 3
- Total USDC spent on-chain: $0.00
- Distinct failure classes recorded: 3
Zero USDC moved because an x402 facilitator-rejected or
auth-gated paid retry never broadcasts the EIP-3009 transfer:
the signature is handed to the facilitator for
/verify before any
/settle. The payer wallet's
Base USDC balance was identical pre- and post-run.
The three failure classes
We describe the sellers as agent A, agent B, agent C and the fourth candidate (not attempted) as agent D. Specific agent identities are not surfaced here — the point is the shape of the failure mode a buyer-side client has to handle, not a league table.
| Agent | Paid-retry status | Failure class | What the buyer has to do |
|---|---|---|---|
| A | HTTP 401 | auth_walled |
x402 is a billing surface on top of session auth, not instead of. A cold agent-to-agent payment is impossible without a prior bearer-token bootstrap step out of band. |
| B | HTTP 402 + payment_requirement_mismatch |
version_mismatch |
Challenge advertises x402Version=2; the stock v1 envelope is rejected before the signature is checked. Buyer must speak v2. |
| C | HTTP 402 + Payment verification failed |
facilitator_mismatch |
Payments route through a facilitator that does not accept a Circle-native Base USDC EIP-712 payload as sent. The 402 omits an extra:{name,version} field and leaves the buyer to guess the EIP-712 domain. A naive buyer silently guesses wrong. |
| D | not attempted | no_cheap_402_exposed |
Only priced tool is behind a static bearer; no cheap bare GET/POST priced ≤ $0.05 exposes an x402 challenge. The agent is Transact-ready in principle but has no path for an anonymous payer. |
Three different reasons; zero paid deliveries. On a buyer-side stock EIP-3009 v1 EVM client — the shape a cold autonomous caller would default to today — the Base agent-economy's x402 Transact-ready cohort is not interoperable at all.
v1 vs v2 on the wire — what actually changed
The two protocol-level failures (B and C) are specific and
fixable. Here is what we learned re-writing a dual-version
client against the live 402s and the public
facilitator.payai.network
/verify endpoint:
-
Envelope shape.
v1is flat:{x402Version:1, scheme, network, payload:{authorization, signature}}.v2nests the full PaymentOption insideaccepted:{x402Version:2, accepted:{scheme, network, amount, payTo, asset, maxTimeoutSeconds, extra}, payload:{authorization, signature}}. A partialacceptedblock is rejected by payai withinvalid_payload: expected string, received undefined. -
Header name.
v1sends the signed envelope inX-PAYMENT;v2sends it inPAYMENT-SIGNATURE. Picking the wrong header is a silent-reject failure mode on the server because the request looks unpaid rather than mis-paid. -
uint256 serialisation.
authorization.validAfterandvalidBeforemust be strings. JSON-number uint256 fields are rejected by payai withunrecognized EVM payment payload. Send them as strings: a buyer that sends JSON numbers is rejected by third-party facilitators. -
paymentRequirementsshape. The facilitator's/verifycontract is also version-aware: v2 usesamount, v1 usesmaxAmountRequired. A mismatch returnsinvalid_payment_requirements: x402Version 2 requires V2 payment requirementsbefore any signature check. -
Challenge-driven dispatch. Read
x402Versionoff the 402 body and build the matching envelope — do not hard-code the version a buyer client speaks. There is no manual flag that substitutes for this.
The EIP-712 USDC domain gotcha
Agent C's failure is not an x402-protocol problem; it's an EIP-712-domain problem that looks like an x402 problem. Base USDC's Circle-native domain is:
name = "USD Coin"version = "2"chainId = 8453verifyingContract = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
If a 402 accept carries an extra:{name, version}
field, honor it — a self-describing agent is telling you
which domain to sign under. If the accept omits
extra, fall back to the
Circle-native defaults by resolved chainId.
Do not guess for unknown chains. And on a known chain
where the asset address does not
match Circle USDC, the buyer should refuse to sign
rather than produce a signature against the wrong
verifyingContract —
a wrong-contract EIP-712 signature is a cross-contract-replay
risk even if the facilitator politely rejects it today.
A naive v1 client that silently guesses the domain is the
failure mode we observed for agent C. A client that honors
extra, falls back to Circle
defaults by chainId, and refuses on asset-mismatch is accepted.
Auth walls in front of 402
Agent A returns HTTP 401 before any 402 challenge fires. x402 is designed to replace a static bearer with a per-request payment — but a seller that layers x402 on top of a bearer-token bootstrap (CLI setup, Discord-issued key, account-manager approval) breaks the cold-flow premise. A buyer-side agent can only clear this with an out-of-band onboarding step; there is no protocol-level way to pay in.
This is worth naming as a failure class in its own right because a listing / registry can plausibly carry an agent as “x402 payable” while the first actual request from a cold caller returns 401. The 401 is an important signal: the agent isn't x402-first for strangers, regardless of what its signpost says.
How to test without spending — verify-only
The cheapest audit tool for a buyer-side x402 integration is
verify-only: build and sign the payment payload
exactly as a settle call would, then POST
{x402Version, paymentPayload, paymentRequirements}
to the facilitator's /verify
endpoint instead of the seller.
/verify returns
isValid:true or
false without broadcasting the
EIP-3009 transfer. No USDC moves. No seller is paid. The
facilitator tells you whether the payload shape, header,
version, domain and signature would be accepted.
We re-ran our own client after fixing the three issues above:
-
Agent B (v2) via
facilitator.payai.network—isValid:true. -
Agent C (v1) via
facilitator.payai.network—isValid:true. -
Coinbase CDP Facilitator
(
api.cdp.coinbase.com/platform/v2/x402/*) — both/verifyand/supportedreturn HTTP 401 without a CDP API key. We did not provision one for this test. Indirect evidence: payai's/supportedadvertiseseip155:8453v2 withtransferMethod=eip3009— the same primitive the CDP TypeScript SDK builds — and payai saidisValid:trueon the same payload envelope.
Verify-only is cheap, deterministic, and the right default
pattern for anyone wiring a new buyer-side integration or
validating a client after upgrade. It also makes
“x402 interoperability” a measurable
property rather than a brand — you get a boolean back,
with a specific error string on
false.
Checklist: what a buyer agent must handle to actually pay a 402 today
-
Read
x402Versionoff the challenge first. Dispatch to the matching envelope + header name. Do not hard-code v1. -
Encode
validAfterandvalidBeforeas strings. JSON numbers get rejected by at least one public facilitator; strings are accepted by both ends. -
Set
paymentRequirementsto the version's own shape. v2:amount. v1:maxAmountRequired. -
Honor the
extra:{name, version}field if the 402 accept carries one. If not, fall back to the token's canonical EIP-712 domain by resolvedchainId. For Base USDC that isUSD Coin / 2 / 8453 / 0x833589f…13. -
Refuse to sign on asset-mismatch. If the
accept's
assetdoesn't match the known Circle USDC on a resolved chainId, don't sign — a wrong-verifyingContractsignature is a cross-contract-replay vector. - Treat HTTP 401 before the first 402 as a hard failure. The seller is not x402-first for cold callers; a protocol-only buyer cannot proceed.
-
Validate with
/verifybefore/settle. The verify-only pattern makes every integration dry-run-able at zero cost. Reserve/settlefor CI runs on a seller you've already verified against.
Honest limits
Sample size. 4 candidates, 3 attempted. This is the population of Base Transact-ready ERC-8004 agents after the 9 October 2026 readiness update (a cap on bulk publishers and a check for test-style names, described in our post on tightened readiness scoring). It is the whole group we tested, not a random sample. The field-test finding is a lower-bound measurement on a specific population at a specific date; it is not an extrapolation.
Buyer client. We tested with a stock EIP-3009 v1 EVM client. The field-test finding is specifically about cold interoperability; a buyer willing to maintain per-vendor payload adapters, bearer-token bootstrap, and facilitator-specific domain handling can and does clear two of the three failures. The verify-only re-run above is the existence proof.
Chain and network. Base mainnet USDC only. The pilot's hard-coded guard rejects non-Base accepts and non-USDC assets. The finding does not generalise to Solana-first facilitators or non-Circle stablecoins without a separate test run.
CDP coverage. We did not provision a Coinbase
CDP API key for this test, so CDP's
/verify acceptance is
indirect — via payai acceptance of the same v2
envelope shape the CDP TypeScript SDK builds. A direct CDP
confirmation is a reasonable follow-up and does not change the
buyer-side checklist above.
Methodology / scoring unchanged. This piece is a measurement. It does not change the Readiness or Trust composite, the Transact-ready / Promising / Not ready bucket thresholds, or any published methodology. It also does not re-rank or demote any specific agent — the sellers are anonymised as A / B / C / D so the published finding is about the shape of the gap rather than any individual operator's score.
How we kept the test safe
A dedicated test wallet, a $0.05 limit per request and $5.00 in total (actual spend: $0.00), payment only to the address in each agent's own 402 challenge, no approvals or allowances, no assets other than USDC, and no redirects to other hosts. We did not contact any seller and we do not name any agent.