State of x402
Abstract
Reports of dead endpoints and silent catalog delisting in the x402 ecosystem have so far been anecdotes from individual operators. The figures below are the same phenomena measured across the entire public discovery catalog, with denominators attached. unverified is its own bucket — an entry that cannot be machine-checked is not counted as dead.
1.Headline measurements
| Measurement | Count | Share |
|---|---|---|
| Endpoints on record (denominator) | 40,583 | — |
| Currently listed in the catalog | 23,821 | 58.7% |
| Delisted (absent on a complete fetch) | 16,762 | 41.3% |
| Payment wall answers a valid 402 (published pass) | 25,025 | 61.7% |
| of which currently listed (the rest are delisted endpoints whose latest probe passed) | 17,448 | 73.2% of listed |
| of those listed, latest probe more than 7 days old | 135 | 0.8% |
| Payment wall failing on ≥2 consecutive probes (published fail) | 4,295 | 10.6% |
| Unverified (gate unmet, or not yet probed) | 11,263 | 27.8% |
| Catalog entries declaring no HTTP method (not machine-checkable) | 7 | 0.0% |
2.By chain
L0 observation has always been chain-agnostic and costs nothing to run, so this table covers every chain the public catalog lists an endpoint on — a wider set than the chains L1 purchasing has reached, which are the rows of the by-chain table in §3. Mainnets only: a row appears only for a network id vet402 knows to be a mainnet. Testnet listings (Base Sepolia, Solana devnet, Arc testnet, Celo Sepolia and the other testnets vet402 names) are excluded below, and so is a network id vet402 cannot name as either rather than assumed to be a mainnet. That makes this table's denominator narrower than the one in §1, which counts every listing on record including testnets: the rows here sum to 40,118, against 40,583 in §1, and the testnet (465) and unnamed listings this table drops are the difference. The two figures come from separate reads, up to a few minutes apart, so read that difference as of those reads rather than as a fixed count. The two denominators are otherwise the same set: both apply the same exclusion of endpoints paying vet402's own addresses. As this page was rendered that exclusion was taking out 0 of them — the count is printed rather than the rule, so a day when it removes nothing reads as nothing removed.
| Chain | n | Listed | Pass | Fail | Unverified |
|---|---|---|---|---|---|
| Base | 37,861 | 57.3% | 62.6% | 10.8% | 26.6% |
| Solana | 1,128 | 80.4% | 67.9% | 2.5% | 29.6% |
| Tempo | 1,075 | 90.7% | 23.7% | 14.0% | 62.2% |
| Arc | 24 | 100.0% | 95.8% | 0.0% | 4.2% |
| X Layer | 18 | 22.2% | 55.6% | 0.0% | 44.4% |
| Polygon | 3 | 100.0% | 100.0% | 0.0% | 0.0% |
| Arbitrum | 3 | 100.0% | 0.0% | 0.0% | 100.0% |
| Robinhood Chain | 2 | 50.0% | 50.0% | 0.0% | 50.0% |
| Algorand (algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=) | 2 |
3.L1 — real purchases
| Measurement | Count | Share of its own denominator |
|---|---|---|
| Paid purchase attempts (money signed and sent): the denominator of the next row | 11,504 | — (denominator) |
| Settled: transfer confirmed on-chain | 6,276 | 54.6% of attempts |
| settled (nonce-bound): the re-read also matched the signature nonce we generated, so that transaction belongs to this purchase | 4,655 | 74.2% of settled |
| settled (amount + payee): matched on amount, payee, asset and chain, with no nonce recorded — settled before the binding shipped on 2026-09-04 | 1,621 | 25.8% of settled |
| settled whose settlement block time falls within -5/+15 minutes of the attempt | 6,236 | 99.4% of settled |
| settled with no settlement block time on record (neither inside nor outside that window) | 40 | 0.6% of settled |
| settled where the seller returned no receipt and our own settlements index found the transfer afterwards (same on-chain re-read as the rest) | 574 | 9.1% of settled |
Delivered: settled and the paid request answered 2xx | 5,619 | 48.8% of attempts · 88.5% of attempts not held (vet402's hold) · 88.6% of attempts counted in the delivery rate (6,343: attempts, less held and awaiting on-chain verification) |
Awaiting on-chain verification (settle_claimed): the seller asserted a settlement and vet402 has not yet read it on-chain — in attempts, in neither delivered nor held (vet402's hold below); its ledger held_reason is empty | 5 | 0.0% of attempts · 0 waiting more than 1 day, 0 more than 7 days (oldest attempt 2026-10-03) |
Inconclusive: held, not counted against the seller — the paid request answered 4xx, or it ran while our own payer wallet was unfunded. “Held” on this page means vet402's hold (the rows with a ledger held_reason); attempts awaiting on-chain verification are the row above. The decision API's reason code l1_not_counted_held covers both | 5,156 | 44.8% of attempts |
| Chain | Paid attempts | Settled | Delivered | Inconclusive | settled (nonce-bound) | settled (amount + payee) |
|---|---|---|---|---|---|---|
| Base | 10,830 | 5,823 | 5,293 | 4,969 | 4,228 | 1,595 |
| Solana | 432 | 296 | 262 | 98 | 270 | 26 |
| Tempo | 133 | 115 | 31 | 72 | 115 | 0 |
| XRPL | 72 | 22 | 13 | 13 | 22 | 0 |
| Arc | 37 | 20 | 20 | 4 | 20 | 0 |
The two settled rows above split the same 6,276 receipts by how strong the evidence behind each is, and they sum back to it — the split labels strength, it does not change the count. Signature-nonce binding shipped at 2026-09-04 12:00 UTC; receipts confirmed before then were matched on amount, payee, asset and chain, which a seller holding several listings at the same price and payee could satisfy with a transfer it had received earlier. Those rows keep the settled label because demoting one would assert something we cannot show. The machine-readable form is l1.settledNonceBound and l1.settledAmountPayeeOnly, per chain in l1.byChain (this L1 breakdown is not mainnet-filtered, so it sums to the L1 totals; the §2 table above is L0 and mainnets-only). Methodology states what each strength does and does not establish.
Attempt and settled counts above are as reported by /api/v1/observatory/state (l1.attempts, l1.settled): an attempt is a paid request whose payment was signed and sent, whatever the seller answered. The per-endpoint cells on the register use the same denominator, and so does history — its rows are the same attempts, cut by UTC day and chain, recomputed for the trailing 14 days on each rollup, so its totals trail this table by whatever settled after the last rollup (the response says through which day it is rolled up, and when). Other machine-readable surfaces (decisions, export.csv) apply their own definition of an attempt and can differ; when a number is quoted from this site, the state API is the one to cite.
4.Listing-change events observed
| Event | Count |
|---|---|
| delisted — vanished from a complete fetch | 20,829 |
| relisted — returned after a delisting | 4,067 |
| settle_drop — catalog-reported 30-day calls fell ≥70% from a ≥100 base | 48 |
5.Coverage and ledger integrity
Coverage (7-day window): 20,453 of 23,821 active listed endpoints (85.9% of active listed endpoints) carry an L0 measurement from the last 7 days. This is the machine definition behind "endpoints under regular verification" — numerator and denominator as stated, nothing else.
Ledger integrity: daily hash chain over the full purchase ledger, latest root (2026-10-01): 28e90719bb9b3276… over that day's 366 ledger entries (an anchor counts the rows it hashed, not the L1 attempts above). A root covers that day's rows as they stood when it was computed; rows are still updated afterwards by design (a settlement verified on-chain, a correction), so an older root describes the ledger as it was then, not as it is. The chain is kept by vet402 and not yet fixed anywhere outside it, so it shows whether a root you saved was later changed — it does not by itself stop vet402 from editing rows. Check the links yourself from /api/v1/observatory/anchors alone: each day's prevRoot is the previous day's root (cli/verify-anchors.ts checks that and that no day is missing). Recomputing a root needs the raw purchase rows, which are not published in full — the open-source projection hashes fields export.csv leaves out (row id, payer, asset, sub-second time, and the statuses the export omits), so a root cannot be rebuilt from the published files.
6.Daily history
L0 probes per UTC day (upper line) and how many of them measured pass (lower line), all chains combined, 50 days with data (2026-08-14 to 2026-10-02). Machine-readable, per-chain: /api/v1/observatory/history.
7.Caveats
Figures are computed from days whose catalog fetch was complete; incomplete days withhold delisting judgements entirely. Probes cycle through the catalog on a rolling schedule, so unverified includes endpoints simply not yet reached. vet402's own listings, when present, pass through the identical pipeline (fairness commitments). None of these figures is an assessment of any individual operator.