Caller-observed delivery proof for paid x402 endpoints
Everyone measures the endpoint. Delivered measures the goods.
Registries count settlements. Monitors probe the paywall. Nobody checks what a paying
caller actually receives, because checking costs money. Delivered pays as a real buyer, then holds the
response against the contract the seller itself published. Every verdict below ships with the
challenge, the response, and the on-chain settlement that proves it.
HTTP/1.1 402Payment Required
POST /api/v1/x402/is-prime
api.delx.ai answers with its price and,
in the same breath, its promise:
"outputSchema": {
"schema": { "type": "string" },
"n": { "type": "integer" },
"is_prime": { "type": "boolean" }
}
"amount": "1000" $0.001 USDC
PAYMENT-SIGNATUREEIP-3009, Base mainnet
transferWithAuthorization {
value: 1000,
to: seller,
nonce: 0x1f92…c4
}
signed, submitted by facilitator,
settled on-chain. Real money,
delivered before the goods.
HTTP/1.1 200OK · payment settled
{
"tool_name": "util_is_prime",
"result": {
"schema": "delx/is-prime/v1",
"n": 97,
"is_prime": true
}
}
The answer is right. The shape is not the one published: every promised field sits one level below the promised path.
A caller reading the contract gets response.is_prime → undefined. HTTP 200, money settled, no error anywhere. Cost to find: $0.001.
46paid attempts
33delivered, HTTP 200
29checkable vs contract
19conforms · 65.5%
10violations · 34.5%
$1.292925settled, on-chain
Base mainnet, 2026-08-26, 40 distinct hosts drawn from Coinbase's x402 discovery registry. Spend measured from the USDC Transfer log, never from quotes.
Every probe, with its receipt
Each row expands to the seller's declared contract, what came back, what was quoted
against what actually settled, and the settlement transaction on Basescan. Verdicts follow one rule:
only an HTTP 200 can be judged against a contract; a payment our client could not complete is our
failure and is never counted against a seller.
Four findings, all paid for
VIOLATION
9 of 10 violations are the same bug
The promised fields exist, nested under a wrapper envelope like {tool_name, result}.
A caller reading the declared path gets undefined while correct data sits one level
down. A contract violation, not fraud, and invisible to every tool that stops at the paywall.
PAID, NOT DELIVERED
Two endpoints settled and returned nothing
One took $0.100 with a settlement receipt,
then answered HTTP 422. Another settled $0.001 and answered HTTP 500. The money moved and nothing
came back, with no recovery path in the protocol. Other sellers hit with the same bad input refused
without charging, so the correct behaviour exists. It is not universal.
CLIENT SIDE
The buyer's toolchain is broken too
The official x402-fetch cannot pay v2 sellers at all. A v2 payload under the legacy
X-PAYMENT header is rejected by 13 of 46. Sending both header names reaches all but
one. Three runs, three interop states, each discovered with real money and reproduced in the
measurement log.
QUOTES
What you are charged is not what you were quoted
Settled amounts drift from listed prices, and some sellers deliver and charge nothing, so a
ledger built from quoted prices does not reconcile against the wallet. Delivered records quoted,
live, and settled amounts as three separate fields and trusts only the transfer log.
Reproduce it yourself
The prober, the conformance checker, and the reconciliation are open source. The
unpaid tier runs from a fresh clone with no wallet and no money at risk.
git clone https://github.com/sneg55/delivered && cd delivered
npm install
npm test # 46 tests, no wallet, no network
node src/fetch-registry.mjs # pull the live x402 registry (~15k listings)
node src/build-targets.mjs 24
node src/probe.mjs targets.json --no-pay # read live 402 challenges, spend nothing
The paid tier needs a funded throwaway wallet and enforces hard spend caps in code
before any signature: $0.15 per call, $5 per run, price read from the live challenge and never from
the listing. Every figure on this page regenerates from evidence/results.json in the repo.