How a check turns a live x402 payment request into pay, skip or recheck. Machine-readable: /rules.json (version 2026-10-15).
| reason_code | verdict | default confidence | rule |
|---|---|---|---|
price_ok | pay | high | Live 402 offers canonical USDC on a supported mainnet, to the listed wallet and network, at the listed price (within 1%). |
price_below_listing | pay | high | As price_ok, but the live price is more than 1% below the listed price. |
price_mismatch | skip | high | Live price is more than 1% above the listed or claimed price. |
pay_to_mismatch | skip | high | The 402 pays a different wallet than listed. |
network_mismatch | skip | high | The 402 asks for payment on a different network than listed. |
asset_not_usdc | skip | high | The 402 asks for a token other than canonical USDC. |
network_unsupported | skip | high | The 402 only offers a testnet or a network we do not support. |
ssrf_blocked | skip | high | Private, local or otherwise unsafe address; never fetched. |
no_paywall | skip | medium | The endpoint answered without an x402 payment request (one probe; a route may need another method or path). |
bad_challenge | skip | medium | A 402 came back but its payment request has no readable USDC price. |
ambiguous | skip | medium | The payment request is unclear (several incompatible offers). |
free_trial_active | recheck | low | The seller says a free trial is active, so there is no price to check yet. |
timeout | recheck | low | The endpoint did not answer in time. |
unreachable | recheck | low | Could not connect (DNS, TLS or network error). |
server_error | recheck | low | The endpoint returned a 5xx. |
within 1% of the listed price counts as the listed price.
Separate from reason_code; never changes a verdict. Folded into reputation.
| code | reputation value | rule |
|---|---|---|
quality_ok | 1 | Reachable, answered HTTP 402 with a well-formed payment request (JSON body or PAYMENT-REQUIRED header), declares an output schema, and the response sample it publishes validates against that schema. |
quality_unverified | 0.7 | Reachable, HTTP 402 with a well-formed content type, but there is nothing to validate: no output schema declared, or a schema without a sample. Not a fault; we never pay the seller to capture a real response. |
quality_bad_content_type | 0.4 | HTTP 402 whose terms are only in the body, and the body is not JSON (content-type is not application/json or +json). |
quality_schema_mismatch | 0.3 | The listing declares an output schema (bazaar extension or v1 outputSchema) and the sample it publishes does not validate against it. |
quality_bad_status | 0.2 | Reachable, but the response is not an HTTP 402 payment request (e.g. 200 without a paywall, 404, 5xx). |
quality_unreachable | 0 | No response: timeout, DNS/TLS/network error, or an address we refuse to fetch. |
score = round(100 * sum(w_i * c_i) / sum(w_i)), over the components c_i (each 0..1) that have data; a component with no data is left out and the remaining weights are renormalized. Cap: with at least 5 pay/skip checks in 30 days and pay_share under 0.2, score = min(score, 49).
| component | weight | definition |
|---|---|---|
stability | 25 | per endpoint: time the current payment terms (price, network, asset, pay_to) have held / time we have observed the endpoint (endpoint_history, last 30 observations); mean over endpoints. Observations without terms (timeouts) do not reset it. |
drift | 20 | 1 - min(1, 2 * penalty / transitions) over consecutive term-bearing observations of every endpoint; penalty per transition: pay_to change 1, network or asset change 1, price-only change 0.5. No transitions -> no data. |
verdicts | 30 | last 30 days of checks: pay_share * (0.5 + 0.5 * consistency). pay_share = pay / (pay + skip); consistency = share of checks that agree with their endpoint's latest verdict. Recheck verdicts (timeouts, 5xx) are left out. |
freshness | 10 | 1 if the newest check is under 24 h old, then linear down to 0 at 14 days. |
quality | 15 | mean over endpoints of the latest quality code's value: quality_ok=1, quality_unverified=0.7, quality_bad_content_type=0.4, quality_schema_mismatch=0.3, quality_bad_status=0.2, quality_unreachable=0. No quality data -> no data. |
reason_code: stable machine code (this list); never renamed, new codes may be addedreason: free answers: one plain-words line; paid answers: the code (unchanged since 0.6)confidence: high | medium | low (rules above)history: summary of the last 30 observations: stable_for_days, stable_since, last_changed, drifthistory_observations: paid, router and exempt answers only: the last 30 observations (time, price, network, pay_to, asset, status)quality: 0.37.0: paid, router and exempt answers: {code, checks {reachable, http_status, status_is_402, content_type, content_type_ok, body_bytes, schema_declared, schema_source, schema_match}}; free answers and dry runs: {code} only. Metadata of the unpaid 402 response; never changes verdict or reason_code.reputation: 0.37.0: seller host reputation. Paid, router and exempt answers: {host, score 0..100 or null, band, confidence, low_data, provisional_score?, breakdown, inputs}; free answers and dry runs: {host, band} only. Free page: /reputation/<host>.