Skip to content

Paying with x402

github-actions[bot] edited this page Jul 28, 2026 · 14 revisions

Paying with x402 (USDC)

x402 is an open HTTP payment standard (the 402 Payment Required status, finally used). Settlement infrastructure exists from Coinbase (CDP facilitator — what this service uses) and Stripe.

The flow

  1. Client calls a paid endpoint.
  2. Server replies 402 with a machine-readable quote: price, asset (USDC), network (eip155:8453 = Base mainnet), and the pay-to address.
  3. Client signs a USDC transferWithAuthorization from its own wallet (no gas needed — the facilitator sponsors it) and retries with the payment header.
  4. Facilitator verifies + settles on-chain; the server serves the result. End-to-end this is seconds.

The payer needs only USDC on Base, Solana, Polygon, Arbitrum, Monad, Celo, Avalanche, Sei, Optimism, Stellar, or Algorand — no ETH, no account, no API key. (Sellers can also settle USDG on Robinhood Chain when the operator enables it.)

JavaScript (x402 v2 SDKs)

import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.AGENT_KEY) });
const payFetch = wrapFetchWithPayment(fetch, client);

const res = await payFetch("https://agent402.tools/api/extract", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ url: "https://example.com/article" }),
});
console.log(await res.json());

Paying over MPP instead (dual-stack)

Every paid endpoint also speaks MPP (Machine Payments Protocol — the IETF-track Payment HTTP auth scheme from tempoxyz/mpp). Same URL, same price, same on-chain USDC settlement; the only difference is the HTTP dialect, and MPP responses add a signed Payment-Receipt header. With the reference mppx client:

import { Fetch, evm } from "mppx/client";
import { privateKeyToAccount } from "viem/accounts";

const payFetch = Fetch.from({
  methods: [evm.charge({
    account: privateKeyToAccount(KEY),
    currencies: [evm.assets.base.USDC],
    maxAmount: "1.00",
  })],
});
const res = await payFetch("https://agent402.tools/api/uuid"); // 402 -> sign -> paid retry -> 200
console.log(res.headers.get("payment-receipt"));               // signed MPP receipt

The buyer's client picks the dialect: mppx prefers the native MPP challenge and pays via Authorization: Payment; x402 clients keep using PAYMENT-SIGNATURE. Both settle the identical EIP-3009 authorization.

Command line: Stripe's purl

Stripe's open-source purl ("curl for paid endpoints") works against Agent402 out of the box — our CI proves it on demand with a real settled payment:

purl wallet add --name me --type evm -k 0xYOUR_KEY -p yourpass --set-active=true
purl --dry-run "https://agent402.tools/api/dns?name=example.com&type=A"  # see the quote
purl "https://agent402.tools/api/dns?name=example.com&type=A"            # pay + get result

Spend controls

Client-side caps belong on the buyer:

  • purl: PURL_MAX_AMOUNT (atomic units; 1000 = $0.001 USDC).
  • agent402-mcp: AGENT402_MAX_PER_CALL (refuse any single call above this USD price) and AGENT402_BUDGET (hard session cap) — both enforced before a payment is signed, so a confused model cannot drain the wallet.

Verifying you weren't cheated

Every settled call is an on-chain USDC transfer to agent402.base.eth (a Base name resolving to the public revenue wallet) — auditable by anyone at Basescan. The service also publishes served-call counters at /api/stats; the chain, not the counter, is the source of truth.

Clone this wiki locally