Inspect an x402 endpoint

Inspect an endpoint before you pay it. Half of the wallets the market study counts as “payers” are indexers and probes, and three paid tools already grade x402 endpoints from the outside. inspect is ours: one unpaid request, the way a wallet, a directory or a facilitator makes it, and eleven checks on what comes back: a 402, the v2 header, well-formed accepts with the token’s signing domain, a price that reads as money, a resource naming the probed URL, a Bazaar extension that validates against its own schema and declares the probed method, a description, no-store, and Coinbase’s own validator verdict. The answer is a signed record of what that endpoint declared at that moment. We inspect our own routes here: one that is a payment challenge, and one free route that simply serves.

3calls answered
2receipts re-hashed
2records verified
$0.01list price for a stranger
1,065ms end to end
pass then fail · 2 records verified

Run 2026-10-11 05:26 UTC against api.s2ar.dev 0.1.1 · 3 calls · 1,065 ms · list price $0.01 for a stranger (these ran on the operator's key and cost nothing) · every number on this page re-derived by tools/walkthrough.py before it was written

1. The quote: HTTP 402

curl -s -X POST 'https://api.s2ar.dev/v1/x402/inspect' \
  -H 'X-Assay-Quote: 1' \
  -H 'content-type: application/json' \
  -d '{"resource": "https://api.s2ar.dev/x402/v1/assert"}'

→ HTTP 402 · 105 ms

price_usd0.005
rails["x402", "credits"]
determinismpoint-in-time
witnesses["probe", "cdp-validate"]
expected_latency_ms4000
free.per_day_keyless10
docshttps://s2ar.dev/examples/inspect-an-x402-endpoint.html
the answer, as JSON
{
  "price_usd": 0.005,
  "rails": [
    "x402",
    "credits"
  ],
  "determinism": "point-in-time",
  "witnesses": [
    "probe",
    "cdp-validate"
  ],
  "expected_latency_ms": 4000,
  "free.per_day_keyless": 10,
  "docs": "https://s2ar.dev/examples/inspect-an-x402-endpoint.html"
}

2. A payment challenge, inspected

Our own assert mirror, probed with GET: eleven checks, the price and the network read off the accepts, the declared method, and Coinbase’s validator agreeing.

curl -s -X POST 'https://api.s2ar.dev/v1/x402/inspect' \
  -H "Authorization: Bearer $S2AR_KEY" \
  -H 'content-type: application/json' \
  -d '{"resource": "https://api.s2ar.dev/x402/v1/assert", "method": "GET"}'

PASS → HTTP 200 · 499 ms · list price $0.005 · receipt sha256:3c14e1ef61e5d196…

status402
verdictpass
passed11
checks11
summary.price_usd0.005
summary.networks["base"]
summary.declared_methodGET
results.3.checkaccepts_wellformed
results.3.oktrue
results.10.checkcdp_validate
results.10.evidence{"valid": true, "simulation": "accepted", "failed": []}
record.kindx402-inspection
record.replayablefalse
record_sha256a961eb948fcff21b…
the answer, as JSON
{
  "status": 402,
  "verdict": "pass",
  "passed": 11,
  "checks": 11,
  "summary.price_usd": 0.005,
  "summary.networks": [
    "base"
  ],
  "summary.declared_method": "GET",
  "results.3.check": "accepts_wellformed",
  "results.3.ok": true,
  "results.10.check": "cdp_validate",
  "results.10.evidence": {
    "valid": true,
    "simulation": "accepted",
    "failed": []
  },
  "record.kind": "x402-inspection",
  "record.replayable": false,
  "record_sha256": "a961eb948fcff21b8187ef0bb3889141c0a1939a79e5fed4f2b560f675976e93"
}

Assay badge for record a961eb948fcff21b

re-derived by the generator
✓receipt sha256:3c14e1ef61e5d196… re-derived: sha256 over the canonical answer, header and body agree
✓record a961eb948fcff21b… fetched back from /v1/verify: sealed, signed, and signed by assay-1 (the key at /.well-known/assay.json)

3. A free route, inspected

The forms list answers 200 to anyone: no challenge, no accepts, nothing for a directory to index. The checks say so, one by one, and the record is still signed: evidence of an absence is evidence.

curl -s -X POST 'https://api.s2ar.dev/v1/x402/inspect' \
  -H "Authorization: Bearer $S2AR_KEY" \
  -H 'content-type: application/json' \
  -d '{"resource": "https://api.s2ar.dev/v1/score/forms", "checks": ["answers_402", "v2_header", "v1_body", "accepts_wellformed", "bazaar_extension"]}'

FAIL → HTTP 200 · 462 ms · list price $0.005 · receipt sha256:2dbb6c22a8f4832f…

status200
verdictfail
passed0
checks5
results.0.evidence{"status": 200, "note": "served without payment"}
results.4.evidence{"reason": "no v2 object"}
record_sha2568002a8cc4026de5d…
the answer, as JSON
{
  "status": 200,
  "verdict": "fail",
  "passed": 0,
  "checks": 5,
  "results.0.evidence": {
    "status": 200,
    "note": "served without payment"
  },
  "results.4.evidence": {
    "reason": "no v2 object"
  },
  "record_sha256": "8002a8cc4026de5d66620ef34f4a4b9c8eb0ae512778f2387c86ff96a34f56d5"
}

Assay badge for record 8002a8cc4026de5d

re-derived by the generator
✓receipt sha256:2dbb6c22a8f4832f… re-derived: sha256 over the canonical answer, header and body agree
✓record 8002a8cc4026de5d… fetched back from /v1/verify: sealed, signed, and signed by assay-1 (the key at /.well-known/assay.json)

A probe is a point in time, so the record says replayable: false and carries the sha256 of the response it judged, and it expires after thirty days. inspect names only what an endpoint publishes to anyone who asks; it sends no payment, no body and no identity, follows no redirects, and reaches only public hosts on 80 and 443.

What this cannot buy

From the signed proceedings (/.well-known/proceedings.json), verbatim:

Failed calls are never charged. Nothing about a caller is kept. The rules: the charter.