Your agent needs an API. The normal options are all built for humans: sign up, verify an email, add a credit card, get an API key, pick a subscription tier, pay for 10,000 calls to use 17 of them.
There is a fourth option, and it is 30 years old: HTTP status code 402 Payment Required was reserved in the original HTTP spec "for future use." The future arrived. The x402 protocol (v2, stewarded by Coinbase) turns 402 into a working payment handshake: the server answers with a price quote, the agent signs a stablecoin payment authorization, a facilitator settles it on-chain, and the API responds — no accounts, no keys, no subscriptions. Payment is the authentication.
This is not a whitepaper tour. Everything below runs against a live store (call402.com) where 15 small APIs — FX rates, phone/email validation, SEC company facts, text structuring, and more — are sold per call for $0.002–$0.005 USDC on Base. The quote you are about to see is a real one, captured from the live server.
Step 1: Ask, get a quote (a real one)
Call any endpoint without paying and you get HTTP 402 plus a machine-readable quote:
curl -X POST https://call402.com/api/phone-lookup \
-H 'Content-Type: application/json' \
-d '{"number": "+14155552671"}'
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"amount": "5000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xAc6F1C3C3b17040730F16dC24Ee9993e9565BE4A",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}]
}
Read it like a price tag: amount is in atomic units, so 5000 = $0.005 (USDC has 6 decimals). asset is the USDC contract on Base, payTo is the seller, and you have 300 seconds to pay this exact quote.
Step 2: Pay and call — the complete buyer
With the official TypeScript libraries, the entire buyer is this:
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(signer));
const fetchWithPay = wrapFetchWithPayment(fetch, client);
const res = await fetchWithPay("https://call402.com/api/phone-lookup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ number: "+14155552671" }),
});
console.log(await res.json());
// Settlement proof comes back in the PAYMENT-RESPONSE header:
const proof = res.headers.get("PAYMENT-RESPONSE");
if (proof) {
const settlement = JSON.parse(Buffer.from(proof, "base64").toString("utf8"));
console.log("tx:", settlement.transaction, "payer:", settlement.payer);
}
npm i @x402/fetch @x402/core @x402/evm viem
The wrapper sees the 402, builds an EIP-3009 payment authorization from the quote, retries with the signature attached, and the facilitator settles the USDC transfer on Base. What comes back is ordinary JSON:
{ "valid": true, "country": "US", "type": "FIXED_LINE_OR_MOBILE",
"e164": "+14155552671", "national": "(415) 555-2671" }
Every other endpoint at the store — and any x402 seller — works exactly the same way. One buyer, every shop.
Step 3: Don't trust the 200 — verify the settlement
Decode the PAYMENT-RESPONSE header (it is Base64 JSON) and check three things: the transaction exists on a Base explorer with status success, the USDC Transfer log goes from your address to the quote's payTo, and the transferred value equals the quoted amount exactly. If any of the three fails, log it and stop — do not just pay again.
The failures you will actually meet:
| Symptom | Likely cause | Fix |
|---|---|---|
| 402 again after paying | Authorization expired (default window 300 s) | Rebuild the payload at retry time, never cache it |
invalid_signature |
Wrong EIP-712 domain or chain | Copy extra.name / extra.version from the quote verbatim; chainId 8453 |
| Amount confusion | Atomic units vs dollars | 5000 atomic = $0.005. Convert once, in one place |
Step 4: Put a budget policy in front of the wallet
An agent with a signing key is an agent that can spend. Four rules keep that boring:
- Per-call cap (e.g. $0.01) and a daily cap (e.g. $1.00), checked before signing.
- Host and asset allowlists — your buyer should refuse quotes from anywhere else.
- A dedicated wallet with a capped float. Never your main wallet.
- An append-only spend ledger: tx hash, endpoint, amount, reconciled against on-chain transfers.
The full kit is itself sold through x402
The complete integration pack — this TypeScript buyer, a dependency-light Python buyer with manual EIP-3009 signing, the full failure table, and a production checklist — is sold at the same store through the same protocol: POST to https://call402.com/api/x402-integration-pack with no payment and the 402 quote you get is the checkout. Half a cent, settled the way this article just taught you. The longer explainer, with the protocol background, lives at call402.com/learn/x402-explained, and the machine-readable catalog of all 15 endpoints is at call402.com/pricing.
A real question to end on: if your agent had a wallet with a $1/day budget, what is the first thing you would let it buy on its own — and what would you never let it pay for? I am building in this space and genuinely want to know where people draw that line.
Top comments (0)