Guardrails before keys
Policy evaluation and an atomic budget reservation both complete before a signer is ever invoked. A refused request costs zero signatures, and a dry run costs zero of both.
tx402 wraps a normal HTTP client. When a server answers 402 Payment Required, tx402
interprets the challenge, checks it against your spend policy, picks a payment route across
the chains the merchant offered, signs one authorization, and retries the request. You get the
response body. Roughly a hundred lines of fragile glue code become three.
It is non-custodial and buyer-side only. tx402 never holds funds, never calls a
facilitator’s /verify or /settle — settlement is the merchant’s job — and never accepts a
raw private key in its main configuration.
Guardrails before keys
Policy evaluation and an atomic budget reservation both complete before a signer is ever invoked. A refused request costs zero signatures, and a dry run costs zero of both.
Deterministic routing
Offered several chains? The same challenge and the same health state select the same route every time — viability, then your preference, then fee, then health.
Integer money, always
Every amount is an integer in atomic units, end to end. No float, no Number, no
rounding surprise between the quote and the signature.
It tells you when it cannot tell
If a signature reached the merchant and the outcome is unknown, you get a distinct error and the budget stays reserved — so the same money is never spent twice by accident.
# TypeScript / Node 20+npm install tx402
# Python 3.10+pip install tx402Both packages are unscoped and named tx402. Chain support is opt-in: the core import path
loads no chain library in either language.
import { createTx402Client } from "tx402";
const tx402 = createTx402Client({ signers: { evm }, policy: { maxPerRequest: "0.10 USDC", maxPerHour: "5.00 USDC" },});
const response = await tx402.fetch("https://api.example.com/paid-resource");from tx402 import Policy, Tx402Client
with Tx402Client( evm_signer=evm, policy=Policy(max_per_request="0.10 USDC", max_per_hour="5.00 USDC"),) as tx402: response = tx402.get("https://api.example.com/paid-resource")Or without writing any code at all:
npx tx402 call https://api.example.com/paid-resource --max-spend "0.10 USDC" --dry-run--dry-run does everything a real call does except reserve budget and sign. It is the
fastest way to find out what a merchant is asking for and what tx402 would do about it.