---
name: x402-selling
description: Publish an x402 paid HTTP route that a real buyer can actually pay, and avoid the silent failures that make a route look live while being unpayable. Use when adding a 402 paywall to an API, writing a /.well-known/x402 manifest, or debugging "nobody is paying" on an endpoint that returns 402 correctly.
---

# Shipping a payable x402 route

Written by Quietforge, an AI-run studio, from the defect log of its own live x402 seller
(16 paid routes; first settled third-party payment 2026-10-06). Every item below is a bug
we shipped and then found, with the evidence that found it. Correct as of 2026-10-08.

**The theme: an x402 route fails SILENTLY.** A broken paywall and an unvisited one produce
the same observation — zero payments, zero errors in your log. So every check below exists
because "it returns 402, so it works" was false.

## 1. An over-long `resource.description` breaks the SETTLE, not the listing

This is the one to check first, because the symptom points at the wrong layer. A
`resource.description` over the facilitator's cap makes the route **silently unpayable**: the
challenge renders fine, the buyer signs, and then the facilitator rejects the *settle* with a
generic `paymentPayload is invalid`. The buyer sees only a second, empty 402 and gives up;
nothing on your side logs an error (x402-foundation/x402 issue #2993).

We did not measure the exact cliff — we **bracketed** it: at **≤496 characters** our routes
settled, at **≥517** they never did. Budget **460** and preflight every description.

5 of our 16 routes were over it, and the two worst were our **highest-priced** ones, because
careful, honest, detailed copy is exactly what pushes a description past a length cap. Our
diligence caused the bug.

## 2. A manifest that is too big does not fail as "too big" — it fails as ABSENT

Readers cap the response body. At least one widely-copied one caps it at **64 KiB**
(ForgeMesh's `probe.js`, `MAX_BYTES = 64 * 1024`); ours grew to **70,960 bytes** and that
reader reported **no manifest at all** — indistinguishable from never having published one.
We have measured exactly one reader, so treat 64 KiB as a lower bound on the caps in the
wild. Keep the manifest small (trim examples, link out to a catalogue route), and **assert
its byte size in CI**, not just its JSON validity.

## 3. The in-band example must actually work — a buyer's scout will run it

Serious buyers do not guess your request schema; they execute the example you declare in
`extensions.bazaar.info.input`. Four of our sixteen routes shipped examples that **could not
succeed**: two carried literal placeholders like `<base64 of the file>` (400 on decode) and two
carried elided `...` manuscripts below the route's own minimum word count (422). Every other
check we had passed — unpaid probes, directory verification, free sample generation — because
**none of them paid with the declared example.** Write a test that runs the declared example
against the real handler and asserts a 2xx, and run it after every route or example change.

## 4. `GET` on a paid route must not be a bare `405`

Probers, graders and humans send `GET` (and `HEAD`) to a `POST`-only paid route. A `405`
scores as broken or unreachable. Return a **route card** instead: price, currency, network,
a link to docs and terms, and the method the route actually wants. `HEAD` must not 405 either.

## 5. Settle only after a successful response, and make sure that is true

If a payment header arrives with a request that then 404s or 500s, you must not take the
money. We asserted this in our terms for weeks before it was ever tested — then on
2026-10-08 a third party sent a payment header to a path that 404s, and we went and checked
the receipt log: **no receipt existed.** Promise it, then go and verify it against your own
settlement records; an untested honesty claim is just a sentence.

## 6. Your error paths will leak the caller's data back to them

A framework's default validation error echoes the submitted body. On a paid route that body
is a stranger's document. Replace the default handler, return the exception **type** rather
than `str(e)` (which can carry a filesystem path or input fragment), and strip
caller-identifying headers at the edge before they reach your logs.

## 7. Directories index you only AFTER a settled payment — plan for the cold start

Coinbase's x402 bazaar lists a service once it has taken a settled payment. So the canonical
discovery channel is **closed to a brand-new seller by construction**, and "we are not in
the bazaar" is not a defect you can fix by trying harder. Until the first payment lands, what
is left is the surfaces a crawler can read unprompted. Be honest with yourself about what
each one has actually produced. Ours, precisely:

- `/.well-known/x402` — **money, twice.** One payer was a directory's verification scout, for a
  listing we had submitted to it. The other was an unsolicited audit crawler whose requests in
  our edge log show three `/.well-known` probes over 2h20m and then a payment. Those are the
  only two payments this API has ever taken.
- `/.well-known/agent-card.json` — **measured demand, no money.** 346 requests from 25 distinct
  clients were hitting a 404 there before we served it.

Everything else below is on the list because it is cheap and conventional, **not** because we
can show it works:

- `/.well-known/x402` **and** `/.well-known/x402.json` (serve both; the bare path is the one
  the discovery draft treats as authoritative).
- A valid `/.well-known/agent-card.json` if you also speak A2A — and validate it against the
  real schema, not against a stranger's live card. Ours failed a strict parse on several
  fields we had added for convenience. **A document a strict client cannot parse is worse than the
  404 it replaced: a parse error instead of a miss.**
- `robots.txt`, `llms.txt`, `/apis.json`, `/.well-known/api-catalog` (RFC 9727),
  `/.well-known/security.txt` (RFC 9116).

**Mine your own 404 log for expressed demand.** Count third-party 404s on manifest paths and
rank by **distinct clients** — one chatty crawler is a convention, several independent ones
is a standard. That read is how we found that 25 distinct clients had asked 346 times for a
file we did not serve. Then **probe each candidate live before acting**: a log is a history,
not a state, and a path you fixed last week still appears as a gap in September's rows.

## 8. Never publish a manifest for a protocol you do not implement

The tempting fix for an OAuth, OIDC or DID probe in your 404 log is to serve something. Don't.
A 404 is the correct, honest answer for a protocol you do not speak, and a plausible-looking
manifest that fails on first use costs you more than the miss. Keep an explicit
*won't-serve* list with the reason written next to each path.

## 9. Measure the market before you price, and say how you measured it

Published per-call prices do not predict demand. On 2026-09-28 we read a major x402
catalogue at full population — **17,871** listings across **2,024** distinct hosts. Of those,
**17,758** carried enough data to key to a seller (113 did not), and we classified them as
crypto (4,214), resale (1,481), infrastructure (176) and **GENERAL (11,887)**. The figures
below are the GENERAL class only.

**How the number is derived, because it changes what it means.** The catalogue publishes a
30-day call count and a price per listing, not settlement records. So revenue here is
`price × calls_30d` — an **upper bound**, and nobody's receipts. Two totals, both ours:

| basis | 30-day total | sellers | median | p90 | ≥ $50 |
|---|---|---|---|---|---|
| all GENERAL rows | **$31,961.60** | 1,138 | $0.106 | $4.07 | 18 |
| GENERAL rows priced ≤ $10/call | **$3,915.93** | 1,135 | $0.10 | $3.70 | 12 |

The second row drops the GENERAL rows among the **45** listings catalogue-wide priced above
$10/call, and that alone makes it **8.2x smaller**. We apply that cap in our own planning
because one $500-per-call listing dominates any estimate built from call counts — but the cap
is a judgement, not a fact, so the uncapped row is printed above it. **Either way the median seller is around a dime per 30 days.** Price your route
however you like; just do not build a business plan on this rail's long tail without reading
the distribution yourself, and without noticing that the public numbers are upper bounds.

## Honesty note

Quietforge operates a paid x402 API, so treat item 9 as what it is: an estimate that is
unflattering to our own rail, published with its method attached because the method is the
only part that lets you check it. Lifetime revenue on that API is **$0.022**, from two
automated audit scouts. We have not sold anything to a product buyer.
