x402 Envelope Inspector
The x402 debugger we wished existed when we launched. Give it a paid endpoint URL and it probes it with GET, decodes the PAYMENT-REQUIRED envelope and lints every accepts[] entry against the x402 v2 spec AND against how the CDP facilitator and Coinbase Bazaar behave in production: CAIP-2 network ids (plain 'base' breaks v2 clients), maxAmountRequired as an atomic-unit string (a float there breaks signing), payTo/asset address formats, scheme support (the public CDP facilitator settles only 'exact'), description quality (Bazaar ranking depends on it), timeout sanity, and the killer nobody documents loudly enough — extra.name must equal the token contract's EIP-712 domain name, which for USDC is 'USD Coin' on Base mainnet but 'USDC' on Base Sepolia; get it wrong and every single settlement fails with an invalid signature. Alternatively paste a base64 PAYMENT-REQUIRED header to lint offline, or a PAYMENT-SIGNATURE payload to check the client side: EIP-3009 authorization completeness, expired validBefore, payTo/value mismatches, and whether the server's advertised extensions were echoed back — the silent omission that makes the facilitator settle happily while Bazaar never indexes the resource. Findings return as error/warning/info, each explaining what will break in practice. At $0.001, run it in CI on every deploy of a paid endpoint.
Call with x402
1. Send the request. 2. Receive 402 with accepts[]. 3. Sign the payment and retry with the X-PAYMENT header.
curl -X POST https://agentbit.app/v1/x402/inspect \
-H 'Content-Type: application/json' \
-d '{"url":"https://agentbit.app/v1/web/search"}'
Input schema
{
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "A paid x402 endpoint to probe live (GET, expects the 402 envelope)"
},
"payment_required": {
"type": "string",
"description": "Base64 PAYMENT-REQUIRED header value to lint offline"
},
"payment_payload": {
"type": "string",
"description": "Base64 PAYMENT-SIGNATURE header value to lint the client payload (optionally alongside payment_required)"
}
}
}Output schema
{
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": [
"live-probe",
"requirements-lint",
"payload-lint"
]
},
"url": {
"type": [
"string",
"null"
]
},
"http_status": {
"type": [
"integer",
"null"
]
},
"verdict": {
"type": "string",
"enum": [
"pass",
"warnings",
"fail"
]
},
"findings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"level": {
"type": "string",
"enum": [
"error",
"warning",
"info"
]
},
"code": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
},
"counts": {
"type": "object"
},
"accepts_count": {
"type": [
"integer",
"null"
]
}
}
}Code examples
// JavaScript (x402-fetch)
import { wrapFetchWithPayment } from "x402-fetch";
const fetchWithPay = wrapFetchWithPayment(fetch, wallet);
const r = await fetchWithPay("https://agentbit.app/v1/x402/inspect", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({"url":"https://agentbit.app/v1/web/search"})
});
console.log(await r.json());
# Python (x402 client)
from x402.clients.requests import x402_requests
s = x402_requests(account)
r = s.post("https://agentbit.app/v1/x402/inspect",
json={"url":"https://agentbit.app/v1/web/search"})
print(r.json())
// PHP
$r = Http::withHeaders(['X-PAYMENT' => $signedPayment])
->post('https://agentbit.app/v1/x402/inspect',
array (
'url' => 'https://agentbit.app/v1/web/search',
));
$data = $r->json();