Skip to the content.

x402 Preflight — a complete x402 service you can fork

Live: https://x402-preflight.broke2builtai.com · $0.001 per call · USDC on Base (eip155:8453) · x402 v2 · no dependencies

One Cloudflare Worker, about 200 lines, that does everything a listable x402 service has to do: answers 402 with a spec-shaped PAYMENT-REQUIRED header, publishes /.well-known/x402, verifies and settles through a facilitator, and never charges for work it did not deliver.

It is also useful on its own. POST /v1/preflight checks someone else’s x402 endpoint before an agent pays it: does it answer 402, can the terms be read, is the price in Base USDC, and does payTo match the wallet you expected (Bankr Cloud aware)? Those are the same checks this directory’s free health check runs, and scripts/health-check.mjs runs them locally for nothing. The paid route is for agents that cannot run a script.

Try it without a wallet

# Any unpaid call answers 402 with the price. The body does not matter yet.
curl -si -X POST https://x402-preflight.broke2builtai.com/v1/preflight \
  -H 'content-type: application/json' -d '{}' | head -5

# Decode the terms from the header
curl -s -D - -o /dev/null -X POST https://x402-preflight.broke2builtai.com/v1/preflight \
  | tr -d '\r' | awk 'tolower($1)=="payment-required:"{print $2}' | base64 -d
{
  "x402Version": 2,
  "error": "PAYMENT-SIGNATURE header is required",
  "resource": { "url": "https://x402-preflight.broke2builtai.com/v1/preflight", "mimeType": "application/json", "description": "..." },
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:8453",
    "amount": "1000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x7a3E312Ec6e20a9F62fE2405938EB9060312E334",
    "maxTimeoutSeconds": 300,
    "extra": { "name": "USD Coin", "version": "2" }
  }]
}

Call it with payment

Use any x402 v2 client that sends a PAYMENT-SIGNATURE header. Request body:

{ "url": "https://penniless-json-repair.sjaman.workers.dev/repair/json",
  "wallet": "0x3D98800c64C345950E1eAaa076D88C12d1BF5F37" }

method (GET or POST, default POST) and body are optional. Omit body and the target gets {}, which is what tests whether it answers 402 before validating. The response is a report:

{
  "verdict": "PASS",
  "httpStatus": 402,
  "x402Version": 2,
  "price": { "atomic": "1000", "usd": 0.001 },
  "payTo": "0x3D98800c64C345950E1eAaa076D88C12d1BF5F37",
  "checks": [
    { "id": "answers-402", "pass": true, "detail": "HTTP 402 to POST" },
    { "id": "readable-terms", "pass": true, "detail": "1 offer(s), read from the header" },
    { "id": "v2-header", "pass": true, "detail": "PAYMENT-REQUIRED header present" },
    { "id": "base-usdc", "pass": true, "detail": "eip155:8453 / 0x8335..." },
    { "id": "payto-matches", "pass": true, "detail": "payTo 0x3D98..." },
    { "id": "discovery-document", "pass": true, "detail": "GET /.well-known/x402 -> 200" }
  ]
}

verdict is gated on answers-402, readable-terms and payto-matches. The rest is advice.

The four rules

Each one is marked RULE 1–RULE 4 in src/index.js. Each exists because a real submission to this directory broke it.

  1. Price first. Answer 402 before you parse or validate anything. Two queued services answered 400 to an empty body, so a discovering agent saw an error instead of a price. We had to hand-craft probe bodies to check them at all.
  2. Check the payment is for your price. A facilitator verifies the signature and the balance. It does not know what you charge. Compare accepted.amount, asset, network and payTo against your own terms before calling /verify.
  3. Do the work before you settle. If the input is bad or the work fails, return the error and never call /settle. Failure is then free for the buyer.
  4. Settle, then deliver. If settlement fails, the buyer gets a 402, not your output.

Two more that are not in the code:

Fork it

  1. Copy this folder.
  2. In wrangler.toml, set PAY_TO to your wallet and PRICE_ATOMIC to your price (USDC has 6 decimals, so 1000 = $0.001). Delete the routes line unless you have a domain on your own Cloudflare account.
  3. Replace preflight() with your own work. Keep handlePaidRoute as it is.
  4. Deploy: npx wrangler deploy
  5. Check it exactly the way this directory will:
    node scripts/health-check.mjs --url https://<your-worker>.workers.dev/v1/preflight --wallet <your PAY_TO>
    
  6. When that prints PASS, submit it. See CONTRIBUTING.md.

The facilitator is PayAI, which needs no API key. Its /supported endpoint lists x402Version 2 / exact / eip155:8453. Any v2 facilitator with the same /verify and /settle shape works.

Tests

node test/preflight.test.mjs

Live against real endpoints. Every PASS case has a control that must FAIL: the right service with the wrong wallet, and a Bankr Cloud route checked against a different seller. A checker that cannot fail is not checking anything.

What has and has not been exercised

Measured 2026-09-15 against the deployed Worker:

Not exercised: a real settled payment. No paid call has been made to this Worker yet. The settle path follows the x402 v2 HTTP transport spec, but until a transaction hash is recorded here, treat it as untested.

This service is listed in directory/queue.json on the same terms as every community submission: HEALTH_CHECKED and not verified. It gets no badge it did not pay a first-party test for.