DEV Community

bot bot
bot bot

Posted on Originally published at forgemesh.io

The x402 ecosystem quietly split — and your endpoint may be unpayable

We run 19 paid x402 services — 800+ endpoints selling data to AI agents for USDC micropayments. Last week we tried to pay one of our own endpoints with the most-installed x402 npm client.

It couldn't.

No error. No rejection. The client fetched our paywall, silently failed to parse it, and moved on. Which means every agent running that client had been doing the same thing — for months.

The split nobody announced

The x402 protocol's server SDK (@x402/core) moved to protocol v2 in December 2025. The most-installed client, x402-fetch, shipped its last release on April 16, 2026 — v1 only. There is no v2-compatible client on npm as of this writing.

So if you built your paid API on the current server SDK — the correct, documented choice — you are speaking a dialect the most common buyer-side client cannot hear. Four separate wire-format breaks, all silent:

  1. The challenge moved. v2 servers put the 402 payment challenge in a base64 response header. The v1 client reads the body — and finds {}.
  2. Network IDs changed format. v2 says eip155:8453 (CAIP-2). The v1 client's validation only accepts plain names like base — it rejects the modern form outright.
  3. Fields got renamed. maxAmountRequired became amount; resource metadata moved from flat fields to a nested object. Neither side translates.
  4. The payment itself vanishes. Even when a v1 client manages to construct a payment, it sends it in a header the v2 server never reads. The server sees an unpaid request and re-serves the paywall. The client did everything right; the money never moved.

What it looks like in your metrics

This is the nasty part: nothing errors. Our fleet analytics showed paywall-challenge traffic holding steady at hundreds of thousands of hits per month — while settlements collapsed roughly 98% over two months. Agents were finding us, reading us, and walking away without so much as a failed attempt in the logs.

If you sell to agents and your challenge traffic looks healthy while your revenue doesn't, check which dialect you're serving before you blame your pricing.

How to test your own endpoint in one minute

Hit your paid route unpaid and look at where the challenge lives:

curl -s -D - -o /dev/null https://your-api.example.com/your-paid-route \
  | grep -i payment-required
Enter fullscreen mode Exit fullscreen mode

If the envelope is in that header and your response body is empty, stock v1 clients cannot read your terms. Then check the body:

curl -s https://your-api.example.com/your-paid-route | head -c 400
Enter fullscreen mode Exit fullscreen mode

If there's no accepts array with plain network names and maxAmountRequired, you're v2-only — technically correct, commercially invisible to the largest client population.

The fix is answering both dialects

We patched all 19 of our services to speak both — v2 headers for modern integrations, v1-readable challenges and payments for the stock client — and then proved it end-to-end: a real $0.05 USDC settlement on Base, initiated by stock x402-fetch 1.2.0, settled on-chain (tx), receipt decoded by the client.

The lesson we're taking away: in a fast-moving protocol ecosystem, you can outrun the market. Building on the newest spec made our fleet correct and unreachable at the same time. Ship current, serve legacy, and test payability with the clients your buyers actually run — not the ones in your own stack. (The same logic is why we also answer MPP dual-stack challenges — a second agent-payment rail that ~15% of catalog sellers already speak.)


Want to check your endpoint right now? Free scanner at forgemesh.io/scan — it grades your 402 and tells you which dialects you speak. And the settlement-proven dual-dialect + MPP middleware ships in our x402 Server Starter Kit ($49), with updates dropped in the buyers' Discord every time this ecosystem shifts — which lately is monthly.

Full story with the analytics: the original post on forgemesh.io.

Top comments (0)