An x402 resource can answer 402 forever and still never deliver. Before you spend anything on one, GET /check?url=<target> answers three questions in a single call: is the target alive right now, what exactly is it asking for (amount, asset, network, payTo, required fields), and what changed since the last check. It costs 0.01 USDC per call on Base mainnet.
Here is the whole integration, and the real responses it returns.
One line to use it
curl -i "https://x402-catalog-history.ai-business-surface.workers.dev/check?url=https://example.com"
First call: the live 402, as measured
Measured on 2026-10-14. The status line is what you act on, and the payment terms come in two places at once:
HTTP/1.1 402 Payment Required
Content-Type: application/json; charset=utf-8
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJwYXltZW50X3JlcXVpcmVkIiwicmVzb3VyY2UiOnsidXJsIjoi…
The v1 JSON body carries the same offer in the older shape:
{
"x402Version": 1,
"error": "payment_required",
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "10000",
"resource": "https://x402-catalog-history.ai-business-surface.workers.dev/check",
"mimeType": "application/json",
"payTo": "0x6f60659390aDA1D02B14024d8c9d0C889f2F89c3",
"maxTimeoutSeconds": 60
}
]
}
Decoding the PAYMENT-REQUIRED header (base64 JSON) gives the v2 form:
{
"x402Version": 2,
"error": "payment_required",
"resource": {
"url": "https://x402-catalog-history.ai-business-surface.workers.dev/check",
"mimeType": "application/json",
"serviceName": "x402-check-before-you-pay"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x6f60659390aDA1D02B14024d8c9d0C889f2F89c3",
"maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" }
}
]
}
Two details worth wiring in correctly:
-
networkisbasein the v1 body andeip155:8453in the v2 header. Same chain, two spellings — a client that reads only one of them will reject the other. -
amountis"10000"in atomic units of theasset(USDC has 6 decimals), so this is 0.01 USDC.
Second call: the 200 delivery
A purchase on x402 is two calls by design. You send the identical request again, this time with the PAYMENT-SIGNATURE header holding your signed authorization, and you receive the 200 delivery. The JSON that comes back is built from these blocks:
| Field | What it tells you |
|---|---|
target |
url, host, path of the resource you asked about |
checked_at |
When the probe ran |
alive + reason
|
Whether the target answered, and the reason when it did not |
probe |
method, requests_made, http_status, latency_ms, final_url, redirects, content_type, payment_header_sent
|
payment_challenge |
The live 402 terms: amount_atomic, amount_usd, asset, asset_symbol, network, pay_to, scheme, max_timeout_seconds, required_fields
|
response_shape |
kind and the top-level keys the target actually answered with |
history |
stored_checks, first_checked_at, previous_checked_at, uptime { reached, of, ratio }, challenges_seen, changes_since_previous
|
delivery_evidence |
source, first_party, known_deliveries
|
The service publishes an example delivery inside its own PAYMENT-REQUIRED extension, which is a convenient way to see the full shape before buying:
{
"product_id": "x402-check-before-you-pay",
"target": {
"url": "https://x402-catalog-history.ai-business-surface.workers.dev/history",
"host": "x402-catalog-history.ai-business-surface.workers.dev",
"path": "/history"
},
"checked_at": "2026-10-14T00:00:00.000Z",
"alive": true,
"reason": null,
"probe": {
"method": "GET",
"requests_made": 1,
"http_status": 402,
"latency_ms": 143,
"final_url": "https://x402-catalog-history.ai-business-surface.workers.dev/history",
"redirects": [],
"content_type": "application/json; charset=utf-8",
"payment_header_sent": false
},
"payment_challenge": {
"present": true,
"source": "PAYMENT-REQUIRED header (base64 JSON)",
"x402_version": 2,
"amount_atomic": "10000",
"amount_usd": 0.01,
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"asset_symbol": "USDC",
"network": "eip155:8453",
"pay_to": "0x6f60659390aDA1D02B14024d8c9d0C889f2F89c3",
"scheme": "exact",
"max_timeout_seconds": 60,
"required_fields": ["scheme", "network", "amount", "asset", "payTo", "maxTimeoutSeconds", "extra"]
},
"response_shape": {
"kind": "x402_payment_challenge",
"content_type": "application/json; charset=utf-8",
"keys": ["accepts", "error", "extensions", "resource", "x402Version"]
},
"history": {
"stored_checks": 2,
"first_checked_at": "2026-10-13T22:00:00.000Z",
"previous_checked_at": "2026-10-13T23:00:00.000Z",
"uptime": { "reached": 2, "of": 2, "ratio": 1 },
"challenges_seen": 2,
"changes_since_previous": [],
"baseline": false
},
"delivery_evidence": {
"source": "this service's own paid-delivery log",
"first_party": true,
"known_deliveries": 0
}
}
Bounds the probe respects
The target is fetched once per paid call, with no payment header, so the 402 you read is the one a buyer faces. Before any payment, the call refuses internal, private and link-local hosts, non-web ports, URLs over 2048 characters, and URLs that embed credentials — including on redirects, up to 3 of them. The probe stops at a 5-second timeout and a 64 KB body cutoff, and the refusal is a 400 that is rejected before any payment is verified.
Price
0.01 USDC per call, Base mainnet, settled one delivery per payment to 0x6f60659390aDA1D02B14024d8c9d0C889f2F89c3. The same address receives every other path on the service, so you only configure one payTo.
When it pays for itself
- You learn that a target is unreachable before signing a payment for it.
- The
payToyou sign against comes from the resource itself, not from a catalogue that may have moved on. - Check the same URL twice and the second delivery returns
changes_since_previousinstead of a full re-read, so a poll costs one call and a diff.
Free catalogue, including the exact input, output and price of every paid path: https://x402-catalog-history.ai-business-surface.workers.dev/
Top comments (0)