{"title":"The x402 endpoint preflight","version":"v1","batteries":{"served":["v1","v2","v3"],"this_one":"v1","v2_adds":["payto-payable","amount-atomic","network-mainnet","transfer-method-signable","solana-rail-receivable"],"v2_series_begins":"2026-08-23","v3_adds":["discovery-info-validates","offer-amount-matches-accepts"],"v3_series_begins":"2026-10-02","verdict_additions":[],"why_both":"Each version keeps its scoring rules: v1 scores structure; v2 adds internal consistency and readable Solana receivability; v3 also rejects observed discovery/schema and offer/challenge contradictions. One probe supplies the versioned comparisons in also_under. Missing optional extensions do not fail v3, and unsupported or unread comparisons are not reported as passes. Older signed reports keep their original bytes and criteria.","defect_vocabulary":"https://scvd.store/defects"},"summary":"Send a URL; we GET it once and report whether it answers a well-formed x402 v2 payment challenge: a 402 status, a parseable base64 PAYMENT-REQUIRED header, accepts entries a client can actually sign against, and structurally valid signed offers if declared. Free, no account. One probe, one moment — a shape check, never an uptime claim.","method":"POST","inspection":{"type":"object","description":"One unpaid response, with observed protocols, unverified advertised term summaries, existing structural findings and coverage gaps. The x402 verdict retains its meaning. No artifact signature verification, payment signing, payment submission, settlement or delivery check.","properties":{"version":{"type":"string","enum":["inspection-v1"]},"subject_url":{"type":"string"},"observed_at":{"type":"string","format":"date-time"},"reachability":{"type":"object","properties":{"state":{"type":"string","enum":["responded","unreachable","method_unresolved"]},"http_status":{"type":["integer","null"]},"method":{"type":["string","null"]}}},"protocols":{"type":"object","properties":{"state":{"type":"string","enum":["read","partial","unobserved"]},"observed":{"type":"array","uniqueItems":true,"items":{"type":"string","enum":["x402","mpp"]}},"scope":{"type":"string"}}},"terms":{"type":"object","description":"Unverified summaries, at most 32 entries per protocol, each with state, entries, total and omitted. Not complete payment instructions."},"structure":{"type":"object","description":"Existing x402, frozen MPP and MPP core batteries, checked counts and failed check names. MPP core also names unmeasured checks; no global readiness verdict."},"coverage":{"type":"object","description":"Body read / over_limit / unobserved and MPP core read / absent / unmeasured."},"signatures":{"type":"object","properties":{"state":{"type":"string","enum":["not_checked"]},"reason":{"type":"string"}}},"unperformed":{"type":"array","items":{"type":"string"}},"gaps":{"type":"array","items":{"type":"string"}}}},"url":"https://scvd.store/api/preflight/v1","request":{"url":"REQUIRED. The https URL a buyer would GET expecting your 402 — your buy endpoint, not your homepage."},"rate_limit":"Two ceilings, both ours: a strict per-isolate bucket and a global best-effort cap of 60 probes/minute across all callers. Past either you get a 429 that says the budget is our cost bound, not a fact about your endpoint. The global cap is eventually-consistent, so it can run slightly generous — never tighter than stated. This endpoint makes one outbound GET per call to a host you chose; the cap is what keeps it a checker rather than a relay.","what_it_checks":["The endpoint answers 402 Payment Required (a 200 is the 'listed but functionally absent' failure; a redirect is refused, because payment clients refuse it too).","PAYMENT-REQUIRED header present and base64-JSON parseable — x402 v2 clients read the challenge there, not from the body.","x402Version is 2.","Every accepts entry carries scheme, network, amount, asset, payTo as strings — the same fields this store's own till refuses to sign offers without.","extensions.bazaar, if declared, carries a parseable info block (what discovery ingestion actually reads).","extensions['offer-receipt'] signed offers, if present, are structurally valid JWS. Their signatures are NOT verified here — that needs a second request to the issuer's did:web, which this probe refuses to make in your name. The conformance desk does it free."],"common_failures_this_catches":{"stuck_repeating_402":"A client that keeps getting 402 after attaching PAYMENT-SIGNATURE is very often paying against the wrong network: accepts offering eip155:84532 (Base Sepolia) or another testnet while the buyer is on Base mainnet, eip155:8453. The probe flags known testnets as an advisory.","listed_but_functionally_absent":"A directory lists your URL as an x402 endpoint but it answers 200, 404 or 500 instead of a 402. Independent probing found the majority of one directory's listings in this state. This is check one.","unparseable_challenge":"PAYMENT-REQUIRED header missing or not base64 JSON — surfaces client-side as 'Invalid payment header format' or a silent parse failure.","amount_units":"Amounts are ATOMIC units (USDC: 6 decimals, $0.005 = \"5000\"). A decimal point in an accepts amount usually means dollar-typed pricing, off by a factor of a million; the probe flags it.","unpayable_payto":"payTo must be the bytes a payment signs over — a 20-byte 0x address on EVM rails, a base58 pubkey on Solana. A name (ENS, Basename, SNS, Unstoppable) is a resolution step the protocol does not define, so most clients throw inside their signing library and you never learn a buyer came; the probe names the registry and the chain it resolves on. It also catches the wallet pasted into the wrong rail's entry — a 0x address in a solana accepts entry or base58 in an eip155 one — which nobody can pay, resolver or not.","inputs_only_discovered_by_paying":"If your resource needs parameters and the challenge does not declare them (extensions.bazaar.info.input), a buyer finds out by being refused AFTER signing a payment — and their ledger records that as YOUR endpoint failing. In the August 2026 field run this was the largest single cause of refused purchases at otherwise-working endpoints. The probe flags the missing contract and credits a declared one.","after_verify_failures":"Facilitator codes like invalid_exact_evm_payload_signature or settle_exact_failed_onchain happen AFTER the challenge stage, at verify/settle time, and depend on the specific payment attempt — a preflight cannot catch them and this one does not pretend to. For the artifact half (do the signed offers verify against the issuer's published key), use POST https://scvd.store/api/conformance/v1."},"what_it_cannot_check":["Delivery. This unpaid probe cannot observe a purchase. The launch_check rung records one bounded paid attempt and what was delivered; even that is not a guarantee about future purchases.","Reliability. One probe is one moment; this is not a monitor and its output is not an uptime claim.","Verify/settle-time failures — wallet state, signatures over a specific payment, on-chain conditions. Those belong to the payment attempt, not the endpoint's shape."],"optional_next_work":[{"title":"Agent shopping audit — The Aura Walk","when":"You run an x402 endpoint and need to see whether unfamiliar agents can find, understand and shop it.","url":"https://scvd.store/operators#shopping-audit"}],"the_ladder":{"free_first":{"artifact":"https://scvd.store/api/conformance/v1 — any issuer's signed offer or receipt, verified free.","endpoint":"https://scvd.store/api/preflight/v1 — this tool. Free.","the_buyer_side":"https://scvd.store/api/before-you-pay/v1 — whether YOUR client would actually pay it. Free.","a_sample_of_the_paid_one":"https://scvd.store/samples/once-over.json — a specimen of the signed report, unsigned, so you can see it before buying it."},"paid":[{"id":"launch_check","name":"The Launch Check","why":"one bounded paid purchase attempt with the response and blind spots recorded; for checking what happens beyond the unpaid challenge","price":"$5 fixed, one-off; nothing here charges again by itself, ever — there is no mechanism that could","price_usdc":5,"cadence":"one_off","buy_url":"https://scvd.store/api/buy/launch_check","buy_url_template":"https://scvd.store/api/buy/launch_check?url=<url>"},{"id":"service_audit","name":"The Once-Over","why":"the current battery with its frozen comparison, plus rail and cross-surface reads, signed and bound into a certificate at a permanent URL; the paid audit has a wider scope than this free probe","price":"$5 fixed, one-off; nothing here charges again by itself, ever — there is no mechanism that could","price_usdc":5,"cadence":"one_off","buy_url":"https://scvd.store/api/buy/service_audit","buy_url_template":"https://scvd.store/api/buy/service_audit?url=<url>"},{"id":"conformance_watch","name":"The Conformance Watch","why":"the frozen v1 battery once a day, each day signed alone: for catching a deploy that quietly breaks the challenge mid-week","price":"$5 fixed, covering a 7-day term, one payment; nothing here charges again by itself, ever — there is no mechanism that could","price_usdc":5,"cadence":"term","term_days":7,"buy_url":"https://scvd.store/api/buy/conformance_watch","buy_url_template":"https://scvd.store/api/buy/conformance_watch?url=<url>"},{"id":"standing_watch","name":"The Night Watch","why":"out-of-band hourly probes, signed: evidence rather than a readout","price":"$5 fixed, covering a 7-day term, one payment; nothing here charges again by itself, ever — there is no mechanism that could","price_usdc":5,"cadence":"term","term_days":7,"buy_url":"https://scvd.store/api/buy/standing_watch","buy_url_template":"https://scvd.store/api/buy/standing_watch?url=<url>"}]},"expected_outcome":"HTTP 200 and a report naming every check with ok true or false, the advisories, the verdict under this battery, and `also_under` carrying the other battery's verdict on the same probe. A not_ready verdict is a successful call — the tool worked and found something. Only the codes below mean the call itself did not happen.","errors":[{"code":"url_missing","http":400,"means":"no url was supplied, or the body was not JSON at all","what_to_do":"POST {\"url\": \"https://your-endpoint/...\"} with Content-Type: application/json. Retrying the same body will fail identically."},{"code":"url_unparseable","http":400,"means":"the string supplied is not a URL","what_to_do":"Fix the string. This is never a fact about the endpoint."},{"code":"target_refused","http":400,"means":"the URL is real but this store's published probe-target law refuses it: https only, default port, no credentials, and nothing private, loopback, link-local or reserved-internal","what_to_do":"Name a public https URL on its default port. The refusal is a statement about US and never an observation about that host — we did not look."},{"code":"own_host_refused","http":400,"means":"the URL is this store's own hostname, which a Cloudflare Worker cannot fetch","what_to_do":"Probe us from your side instead; our own 402s pass these checks in CI on every build and you should not take that on faith."},{"code":"budget_spent","http":429,"means":"the probe budget for this minute is spent — a cost bound on our side, never a fact about your endpoint","what_to_do":"Read Retry-After (a whole minute) or the RateLimit fields beside it, and come back. Do not treat this as a verdict."}],"security":{"what_this_does_in_your_name":"Exactly one outbound GET, to the URL you supplied, with no credentials and no body, bounded in time and in response size. Nothing is signed, no wallet is touched, and we never follow a redirect — payment clients refuse them and so do we. Your URL is the only thing we act on.","what_it_stores_about_you":"Nothing keyed to you. The probe result is returned and not retained; the only thing that persists is an unattributed counter of how many probes ran this minute, which is how the budget below is enforced.","what_we_never_do":"No account, cookie, caller identifier or IP-based budget. Budgets bound our cost, not caller rank. Requests are never sold, shared or published. The weekly census reads public discovery feeds, never these requests.","standards":"Disclosure is private-first and symmetric: notify the operator before publication, including our own defects. Corrections are dated and public. Signed artifacts verify offline against our published key.","reporting":"https://scvd.store/.well-known/security.txt for a vulnerability, https://scvd.store/corrections for something we got wrong."},"try_it_against_a_live_endpoint":"Any of this store's own buy URLs is a permanent, free, working example of what a passing challenge looks like — GET one and compare. We cannot probe our own hostname from inside the Worker (the platform forbids self-fetch), so CI proves the store passes these exact checks on every build instead, and you are encouraged to probe us from your side rather than take that on faith."}