Skip to main content

x402lint

A conformance linter for the x402 agent-payments protocol. Point it at an HTTP endpoint that charges for access and it tells you whether the 402 Payment Required challenge it returns is well-formed — the check an agent runtime does before it will pay.

$ x402lint check https://riddlex402.vercel.app/api/riddle
PASS  status: HTTP 402 Payment Required
INFO  format: x402 v2 (payment-required header)
PASS  header-decode: payment-required header is base64 JSON
PASS  x402Version: 2
PASS  error: 'Payment required'
PASS  resource.url: https://riddlex402.vercel.app/api/riddle
PASS  accepts: 1 payment option(s)
PASS  accepts[0].required: all required fields present
PASS  accepts[0].scheme: 'exact'
PASS  accepts[0].network: eip155:8453 (CAIP-2)
PASS  accepts[0].amount: 2000 atomic units
PASS  accepts[0].asset: valid EVM address
PASS  accepts[0].payTo: valid EVM address
PASS  accepts[0].maxTimeoutSeconds: 300
PASS  accepts[0].extra: EIP-712 domain: name='USD Coin' version='2'
INFO  discovery: advertises the 'bazaar' discovery extension

14 pass, 0 warn, 0 fail  (CONFORMANT)

Install

pip install x402lint

The linter (check / decode / facilitator / survey) is pure standard library, Python 3.12+. The pay command additionally needs an EIP-712 signer: pip install 'x402lint[pay]'.

Commands

x402lint check <url>

Fetches <url> with no payment header, expects a 402, and checks the payment challenge:

  • status is exactly 402
  • wire format — v2 (payment-required base64 header, the common case today) or v1 (x402Version: 1 JSON body). Reports which.
  • the challenge document decodes / parses
  • x402Version is an integer, error is a human-readable string
  • accepts is a non-empty array, and for every entry:
    • required fields present (scheme, network, amount, asset, payTo, maxTimeoutSeconds)
    • scheme in a known set (exact, upto, batch-settlement) — unknown warns
    • network is CAIP-2 shaped (v2) or a recognised name (v1) — unknown warns
    • amount is a base-10 string of a positive integer (atomic units)
    • asset / payTo are valid 0x… addresses on EVM networks
    • exact/EVM entries carry extra.name + extra.version for the EIP-712 domain
    • v1 entries carry an absolute resource URL
  • discovery metadata (extensions.bazaar / v1 outputSchema) — reported, not required

--json emits a machine-readable report (for CI). Exit code: 0 conformant (warnings allowed), 1 any failure, 2 tool error.

x402lint decode <blob>

Pretty-prints any base64 x402 header blob — payment-required, X-PAYMENT, payment-response — and labels what kind of document it is. - reads stdin.

curl -sD - https://weather.payapi.market/current \
  | grep -i ^payment-required: | cut -d' ' -f2 \
  | x402lint decode -

x402lint facilitator [url]

Fetches GET <url>/supported and lists every (x402Version, scheme, network) triple the facilitator can verify / settle, plus its advertised extensions. Warns on unknown schemes or non-CAIP-2 v2 networks. url defaults to https://x402.org/facilitator (the public testnet facilitator). --json.

$ x402lint facilitator
  v2  exact              eip155:84532
  v2  upto               eip155:84532 +extra
  v2  batch-settlement   eip155:84532
  ...
11 kind(s): schemes batch-settlement, exact, upto; 9 network(s); versions 1, 2

x402lint survey [catalogue]

Pulls a discovery catalogue (catalogue defaults to the Coinbase CDP .../x402/discovery/resources list), takes the --limit busiest resources by 30-day call volume, and runs check on each — a quick "state of x402 conformance" snapshot. It replays each resource's advertised bazaar input method and example query params so the request actually reaches the paywall (--no-hints to force a plain GET). --json.

$ x402lint survey --limit 8
ok   v2  https://x402.twit.sh/tweets/search?from=elonmusk&minLikes=100&words=bitcoin
FAIL v2  https://x402.tavily.com/search
       - accepts[1].amount: 'amount' must be a base-10 string of a positive integer, got '0.016'
...
7/8 endpoints conformant

x402lint pay <url>

Fetches the endpoint's 402, picks the first exact-scheme accepts[] entry (or --accept-index N), and signs an EIP-3009 TransferWithAuthorization payment offline — no transaction, no gas, just an EIP-712 signature. Prints the X-PAYMENT header value a client would send back. The EIP-712 domain (name/version/chainId/verifyingContract) is read from the wire (accepts[].extra + network + asset), never hardcoded.

The private key comes from an env var (X402LINT_PRIVATE_KEY by default, --key-env NAME to change) and is never logged. Needs the pay extra:

pip install 'x402lint[pay]'
export X402LINT_PRIVATE_KEY=0x...
$ x402lint pay https://api.example.com/data
# payer     0x19E7E376E7C213B7E7e7e46cc70A5dD086DAff2A
# asset     0x036CbD53842c5426634e7929541eC2318f3dCF7e  (USDC v2, chain 84532)
# payTo     0x209693Bc6afc0C5328bA36FaF03C514EF312287C
# value     1000 atomic units
# expires   validBefore=1756431600

X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3Qi...

--json emits the payer, authorization tuple, signature, full PaymentPayload, and header.

Roadmap

  • x402lint roundtrip <url>pay + actually submit the payment and verify on-chain settlement on Base Sepolia testnet

Protocol notes

Two wire formats exist. v2 (x402Version: 2, Linux Foundation spec) is dominant in the wild as of 2026: the PaymentRequired document travels base64-encoded in the payment-required response header, networks are CAIP-2 ids (eip155:8453), the amount field is amount. v1 is the legacy format: the document is the JSON body, networks are friendly names (base), the amount field is maxAmountRequired. x402lint handles both.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

x402lint-0.3.0.tar.gz (88.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

x402lint-0.3.0-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file x402lint-0.3.0.tar.gz.

File metadata

  • Download URL: x402lint-0.3.0.tar.gz
  • Upload date:
  • Size: 88.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for x402lint-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c821cba298f44cc404eb67e508174bca3d30e1f7128d54f747786cac8f05353d
MD5 0bd9f5406951731b0af99123d46ca938
BLAKE2b-256 81cc57c6c65cee24e1a751d6fa1b9d9ad584d7451db4ac5274205a8ec394aff2

See more details on using hashes here.

File details

Details for the file x402lint-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: x402lint-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 18.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for x402lint-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 723badd93e9f077b6d858b27ac2c318939e3c36113dcceb79a081b2c85305535
MD5 c6cb67d2fa8a26bc21fa2a3e41029d19
BLAKE2b-256 090006e22fcc765066aa9f51ef2080726de8abacaaa84e1b9bc4f29a4f5cc9ad

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

This release

0.3.0 This release

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page