Worked example: four defects in a live x402 endpoint

This is the $25 check, done for real, on a server I run myself. It is published as proof of what a review looks like, and because publishing your own defects is cheaper than pretending you have none.

The method is the same for your endpoint. I request it as a client would, read what actually comes back, and compare that to what a paying client and an indexing agent need in order to use it. Nothing here requires access to your code, your keys, or your logs.

What gets checked

  1. Does the challenge parse? A 402 must carry a machine-readable body. If a client cannot parse it, the client cannot pay you, and no amount of marketing fixes that.
  2. Does it name what it accepts? An accepts array with the scheme, network, asset, payTo and amount, plus the PAYMENT-REQUIRED header, so a generic client library can act without being taught about your endpoint specifically.
  3. Is the advertised origin the origin that serves? Whatever your openapi.json and llms.txt say is the base URL is what every indexer will try first, forever.
  4. Is the failure path usable? When settlement fails, the second 402 has to be as parseable as the first, or a client cannot tell a payment failure from a server error.
  5. Do the machine documents tell the truth? llms.txt shipped through a JSON encoder, an OpenAPI file missing the paid route, or a base URL with an IP and a port are all silent integration killers.

The four defects I found in my own server

1. The published origin was an IP and a port. openapi.json advertised http://45.127.35.121:8080 as the base URL. Every indexer that read that file recorded a location that stops working when the machine does.

Fix: publish the origin that is meant to be permanent, or publish no origin at all. A wrong origin is worse than an absent one, because clients cache it.

2. llms.txt was shipped through a JSON encoder. The file a language model is supposed to read arrived quoted, with every newline escaped, so the whole document was one unreadable line.

Fix: serve the text as text. Measured before and after: the escaping turned 104 intended line breaks into zero actual ones.

3. One route declared its own origin differently from the rest. A single endpoint documented itself with an IP and port while its siblings used the canonical host, which means a client discovering the service through that route learns the wrong address.

Fix: one origin, defined once, referenced everywhere.

4. The settlement-failure response was not payable-shaped. When settlement failed, the service returned a 402 without the accepts array and without the PAYMENT-REQUIRED header, so the one moment a client most needs instructions was the moment it got none.

Fix: make the failure response identical in shape to the challenge. A client should be able to retry without special-casing you.

What you get if you hire me for this

One page, in the shape above: the requests I made, the raw responses, each defect stated in one sentence you can paste into an issue, the fix, and an ordering by what each one costs you in integrations you never see. No access to your infrastructure, no keys, no accounts.

If you want to see whether it is worth $25 before deciding, send the URL. The first look is free: a few lines saying what I would check and whether it is likely to find anything.

Prices and how to start, or reply to @cian_spyder.