{"title":"The x402 endpoint preflight","version":"v2","batteries":{"served":["v1","v2"],"this_one":"v2","v2_adds":["payto-payable","amount-atomic","network-mainnet","transfer-method-signable","solana-rail-receivable"],"v2_series_begins":"2026-08-23","why_both":"v1 is frozen: a `ready` rendered under it today means what a `ready` rendered under it in week 34 meant, and every artifact this store has signed names the criteria it was rendered under. v2 folds the rail read into the verdict, because a payTo that owns no token account for the mint it asked for cannot be credited and is not ready by any reading a buyer would accept. Both are computed from the SAME probe and every response carries the other one's verdict in `also_under`, so a reader comparing two reports never has to guess whether the doors differed or the rules did.","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","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. Whether anything real happens after payment is a fact about the world; the paid behavioral rung of this ladder is standing_watch.","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."],"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 — every field the $5 artifact carries, unsigned, so you can see it before buying it."},"paid":[{"id":"service_audit","name":"The Once-Over","why":"these exact checks, signed and bound into a certificate at a permanent URL: for when you need to hand somebody the readout rather than run it","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"},{"id":"conformance_watch","name":"The Conformance Watch","why":"these exact checks 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"},{"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"}]},"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, no cookie, no caller identifier, and no allocation of our budgets by IP — the buckets bound our cost rather than ranking callers, which is a trade we would rather state than hide. We do not sell, share or publish what any caller asked us about; the weekly census is a separate instrument that walks public discovery feeds, never this door's traffic.","standards":"Disclosure is private-first and symmetric: an operator hears from us before the public does, and the same rule binds us when the defect is ours. Corrections are dated and public, never silent edits. Every signed artifact verifies offline against a published key, so you never have to ask us whether a document of ours is real.","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."}