Dev.to AI šŸ¤– Ai šŸ‘ 0 šŸ“– 6 min read

The seven most common x402 seller mistakes, and how to fix them

An x402 API asks for payment with an HTTP 402 Payment Required answer, and an AI agent pays it per call in stablecoins. That only works when the 402 is exactly what the agent's client expects. x402 Doctor calls every pai

An x402 API asks for payment with an HTTP 402 Payment Required answer, and an AI agent pays it per call in stablecoins. That only works when the 402 is exactly what the agent's client expects. x402 Doctor calls every paid endpoint it can find once a day, about 50,000 of them, the way a paying agent would. On 17 October, 93% were payable as listed. These are the mistakes behind most of the rest, with the fix for each.

  • 2,009 endpoints whose 402 names another URL
  • 1,042 listed URLs that don't answer 402 at all
  • 206 offer only a testnet
  • 7% of Stellar endpoints can't be paid by the official client

1. The 402 names another URL (resource mismatch)

2,009 endpoints. The resource.url in the 402 is not the URL the agent called: a relative path, another host, or http:// instead of https://. Clients and indexes that check the resource refuse the challenge, and the CDP Bazaar may not list the route. The usual cause is a proxy that ends TLS (Render, Fly, Railway, Heroku), so the app builds an http URL.

// Express behind Render, Fly, Railway or Heroku: the proxy ends TLS, so without this
// req.protocol is "http" and the 402 names http://… instead of your public URL.
app.set("trust proxy", 1); // before paymentMiddleware

Or set the field yourself, with the full public URL of the route:

"resource": { "url": "https://api.example.com/v1/price" }

2. The listed URL doesn't answer 402

1,042 endpoints. The URL in the listing answers 404, 401, a login page, or 200 for free. Often the route answers 402 only on POST while the listing says GET, an API-key check runs before the paywall, or the payment middleware is registered after the handler. Agents and indexes only see a paid resource when the first answer to the listed method is a 402.

app.use(paymentMiddleware({
  "GET /v1/price": {
    accepts: [{ scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: process.env.PAY_TO }],
    description: "Latest price for a symbol",
    mimeType: "application/json",
  },
}, resourceServer));

app.get("/v1/price", handler); // after the payment middleware

Register the payment middleware before the handler and before any API-key check (the payment is the authorization), list the method the route really uses, and let a request without input reach the paywall instead of failing validation first.

3. Only a testnet is offered

206 endpoints. The 402 offers only Base Sepolia or another testnet. Agents with real USDC on mainnet can't pay, so the endpoint is invisible to them. A testnet option next to a mainnet one is fine; 4% of payable endpoints do that.

accepts: [
  { scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: process.env.PAY_TO },   // Base mainnet
  // { scheme: "exact", price: "$0.01", network: "eip155:84532", payTo: ... },             // Base Sepolia: test only
],

4. The MPP challenge names another host as its realm

102 endpoints. On endpoints that also take MPP (the Machine Payments Protocol), the WWW-Authenticate: Payment challenge has a realm that is not the service's own host, often a leftover from a template or a gateway domain. Clients may refuse a challenge for another domain. Set it to your own host (or its base domain):

WWW-Authenticate: Payment id="…", realm="api.example.com", method="tempo", intent="charge", request="…"

5. The 402 asks more than the listing says

73 endpoints. The price in the 402 is higher than the price in the listing the agent found. A careful agent stops there: x402 Doctor's preflight says caution for a higher price and no_go from ten times the listed price. Keep one source for the price:

const PRICE = "$0.01"; // one source for the route config and for every listing that shows the price

6. Stellar: the asset is a name, not the token contract

47 of 631 Stellar endpoints (7%), from 3 sellers. The asset field says "USDC" or "USDC:G…", but the official @x402/stellar client expects the address of the USDC token contract. Its payments fail before they start. With a dollar price ("$0.01") the SDK fills in the right asset; otherwise:

"network": "stellar:pubnet",
"asset": "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75"  // USDC (Soroban token contract), not "USDC"

Every Stellar endpoint and its status: x402-doctor.fizzl.eu/stellar. More in x402 on Stellar.

7. The Bazaar example has no input that works

The discovery extension in the 402 tells agents how to call the route. When its example has no parameters, or parameters the route rejects, an agent that found the route through the Bazaar sends a bare request, pays, and gets an error back. In x402 Doctor's spot-buy of 18 October, 3 of 27 purchases ended with an error after paying: 404, 404, and a 400 that said missing_required_parameters. None of them charged, but the agent got nothing. Declare a real example, and check input before you settle the payment:

import { declareDiscoveryExtension } from "@x402/extensions/bazaar";

const discovery = declareDiscoveryExtension({
  method: "GET",
  input: { symbol: "BTC" },                                   // a real request that works
  inputSchema: { properties: { symbol: { type: "string" } }, required: ["symbol"] },
  output: { example: { symbol: "BTC", price: 67000 } },
});
// In the route config: extensions: discovery

And one security bug: HEAD gets the paid answer for free

A bug in the x402 SDKs (x402-foundation/x402#3796) let some paid GET routes answer a HEAD request with 200 and the full work behind it, without payment. Anyone can make such a server do paid work for free. Update @x402/core and your framework adapter to a release with the fix, or refuse HEAD on paid routes until then. x402 Doctor's web check flags it as head-unpaid.

// Until your @x402 packages include x402-foundation/x402#3796: refuse HEAD on paid routes.
app.use((req, res, next) => (req.method === "HEAD" ? res.sendStatus(405) : next())); // before paymentMiddleware

Check your endpoint

  • Free web check: x402-doctor.fizzl.eu reads your 402 the way a paying agent does, flags every problem above and gives the fix as code for your stack.
  • In CI: npx github:Fizzl13/x402-doctor <url> (exits 1 on failures), or the GitHub Action Fizzl13/x402-doctor-action@v1.
  • For the CDP Bazaar: Coinbase's free validate API. How it compares to six other checkers: x402 endpoint checkers compared.

How we measure

Every endpoint listed in the CDP Bazaar, Circle's Agent Marketplace, the MPP directory and other public x402 indexes is called once a day without paying, and its 402 is checked the way a paying agent would. Counts are endpoints in the scan of 17 October 2026 with that problem; one endpoint can have more than one. The weekly spot-buy pays up to 30 random endpoints that look payable, at most $0.05 each. The whole index is an open dataset on Hugging Face (CC BY 4.0), and the overall picture is in We check 50,000 paid x402 endpoints every day.

Questions

What is a resource mismatch in x402?

The 402's resource.url names another URL than the one the agent called: a relative path, another host, or http instead of https. Clients and indexes that check it refuse the challenge. On 17 October 2026 it was the most common problem among paid x402 endpoints, on 2,009 of them.

Why doesn't my x402 endpoint show up in the CDP Bazaar?

The Bazaar indexes a route after its first payment settles through the CDP facilitator, and only when the 402 is valid: resource.url must be the exact public https URL, the listed method must answer 402, and the discovery extension should declare an example request that reaches the paywall. Coinbase's free validate API and x402 Doctor's free web check show which of these fails.

Why does an agent get a 402 again after paying?

Usually the seller's facilitator could not settle the payment (the 402 or its PAYMENT-RESPONSE header then carries an error such as settlement_failed), or the server did not see the payment: x402 v2 clients send it in the PAYMENT-SIGNATURE header, v1 clients in X-PAYMENT. Check the facilitator's logs and that the payment middleware runs on the paid route for that method.

How can I test my x402 endpoint for free?

x402 Doctor's web check at https://x402-doctor.fizzl.eu reads your 402 the way a paying agent does and gives each problem with the fix as code for your stack; npx github:Fizzl13/x402-doctor <url> and a GitHub Action run the same check in CI. Coinbase's validate API checks whether the CDP Bazaar can index the route.

Originally published at fizzl.eu.

šŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.