Point it at an x402 seller endpoint. It performs the handshake a paying
client would — GET with no X-PAYMENT header — and reports
what it observes about the 402 challenge against the 16 checks below,
with a fix for each finding.
Buyer-side x402 is well served by the official SDKs. Seller-side is where people get stuck, because the failures happen inside a facilitator you cannot see into.
$ curl -s -X POST https://x402-doctor.tsharpe.workers.dev/probe \
-H 'Content-Type: application/json' \
-d '{"url":"https://your-service.example/paid-endpoint"}'
| status | meaning |
|---|---|
| healthy | Nothing on the checklist fired. |
| advisories | Only warn / info findings. The endpoint works; these are things worth knowing, not breakage. |
| defects_found | At least one error finding — something a paying client or facilitator will actually choke on. |
| not_x402 | The response carries no x402 shape at all. Probably somebody's ordinary API, not a broken seller. |
| unreachable | No usable response. reason and blockedReason say why. |
This tool reports on other people's working endpoints, so it is built to say less rather than more: it reports what it observed on the 402 it fetched, and does not infer defects in responses it never requested.
Also an MCP server — point a client at POST /mcp for
probe_x402_endpoint, explain_defect and list_checks.
Every rule says where it came from. spec means the x402
specification requires it. observed means we watched a real facilitator
reject it, and names the source — so no finding has to be taken on trust.
| id | sev | check | provenance |
|---|---|---|---|
| no-402 | error | Endpoint did not answer 402 without payment | spec |
| body-not-json | error | 402 body is not parseable JSON | spec |
| oversized-body | warn | 402 body exceeded the read cap | observed (this probe) |
| missing-x402-version | error | x402Version is absent or not 1 | spec |
| accepts-empty | error | accepts is missing, not an array, or empty | spec |
| output-schema-null | error | outputSchema is explicitly null | observed (Coinbase CDP facilitator, 2026-07-17) |
| amount-not-atomic-string | error | maxAmountRequired is not an atomic-unit string | spec |
| asset-network-mismatch | warn | asset is not the USDC contract for this network | spec |
| missing-eip712-extra | error | scheme "exact" without the EIP-712 domain in extra | spec |
| unknown-network-name | info | network name is not one this probe recognises | spec |
| payto-not-an-address | error | payTo is not a valid address for this network | spec |
| payto-not-checksummed | info | payTo is not a checksummed address | spec |
| no-timeout-declared | info | maxTimeoutSeconds is absent | spec |
| challenge-cacheable | warn | 402 challenge is cacheable | observed (ours, 2026-08-15) |
| cors-headers-not-exposed | info | browser clients will need payment headers exposed on the settlement response | observed (x402-foundation/x402#2112) |
| bazaar-ext-inside-accepts | warn | Bazaar extension declared inside an accepts entry | observed (ours, 2026-08-14) |