DEV Community

Cover image for 16 paid endpoints. None of them could be bought.
Kaven C
Kaven C

Posted on

16 paid endpoints. None of them could be bought.

I run a helpdesk that AI agents can pay to use. Sixteen endpoints, priced from $0.02 to $0.06, settled in USDC over x402.

The funnel showed zero conversions. I assumed that meant no demand. Everyone told me the agent economy was early, and that was a comfortable thing to believe.

It was wrong. Every one of those sixteen endpoints was unbuyable. Three separate bugs, none of which produced an error anywhere I was looking.

What a paywall failure looks like

Nothing. That's the problem.

A payment protocol failure isn't a 500 you find in your logs. From your side, a request arrives, you answer 402 Payment Required, and the caller leaves. That's also exactly what it looks like when someone reads your price and decides it's too expensive.

Your dashboard shows the same graph either way: requests in, no settlements. Indistinguishable from being unwanted.

The three bugs

The EIP-712 domain name isn't uniform across chains. I assumed USDC reports "USD Coin" everywhere. On Sei it reports "USDC". Get this wrong and the buyer's signature recovers to a different address than the one that signed. There's no error message. The signature is valid, it just belongs to nobody. Payment refused, both sides baffled.

The discovery manifest advertised a key nobody reads. I'd invented a sensible-looking name for the block describing my paid actions. The catalogs that index x402 services read one specific key. Mine wasn't it, so as far as every directory was concerned, my endpoints didn't exist.

MCP clients open a GET with Accept: text/event-stream before doing anything. My paywall answered 402. The correct answer is 405. Every compliant client hit a payment wall during transport negotiation and gave up before reaching anything purchasable.

Each of these is individually obvious in hindsight. Together they meant a working-looking product that could not take money.

What actually found them

Not tests. My test suite was green throughout, because it tested my server against my assumptions about clients.

What found them was calling my own paywall with a stock client I hadn't written, from outside, like a stranger. The first one failed in four seconds.

That gap is the whole lesson. Your tests encode what you believe. A third-party client encodes what the protocol actually says. Where those disagree is exactly where your revenue disappears silently.

So I packaged the probe

The tool I used to find this is now a CLI, and it works against any x402 server, not just mine:

npx try-x402 --dry-run
Enter fullscreen mode Exit fullscreen mode

That reads the real payment terms off a live endpoint and signs nothing. Drop --dry-run and it settles for real. Point it anywhere with --url.

It's built to refuse to hurt you, because a "just try it" tool that can drain a wallet is worse than no tool:

Rejects any asset that isn't the canonical USDC for that chain
Builds the EIP-712 signing domain locally, so a hostile server can't substitute a different token

Won't sign above --max-price, default 1 USDC

Generates a throwaway wallet per run and prints the key, so you never point a real one at it

MIT, no account, nothing to install: github.com/webmilmind1/try-x402

If you run a paywall of any kind

Go and buy from yourself.

Today.

With something you didn't write.

Not a test.

Not a staging mock.

A real client, hitting production, the way a stranger would.

If it doesn't work, you'd rather learn that from yourself than from a flat line on a graph you've been misreading for a month.

Top comments (0)