Skip to main content

Overview

The x402 protocol makes the HTTP 402 Payment Required status code finally useful after 30+ years. Reserved since HTTP/1.1 in 1997, it now enables autonomous payment flows for AI agents and APIs. Key insight: Payments become just another HTTP status code—like 401 Unauthorized but for money.

How It Works

The x402 protocol transforms payment requirements into standard HTTP exchanges:
1

Request Protected Resource

Client makes a request to a paid endpoint without payment
curl -i http://localhost:3000/ping
2

Server Returns 402

Server responds with payment requirements in the response body
HTTP/1.1 402 Payment Required
Content-Type: application/json

{
  "payment": {
    "amount": "1000",
    "currency": "USDC",
    "to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "chainId": 84532,
    "network": "base-sepolia",
    "facilitator": "https://x402.org/facilitator"
  }
}
3

Client Signs Payment

Client creates cryptographic signature using EIP-712 typed data
const signature = await wallet.signTypedData({
  domain: {
    name: "x402 Payment",
    version: "1",
    chainId: 84532
  },
  types: {
    Payment: [
      { name: "amount", type: "uint256" },
      { name: "currency", type: "address" },
      { name: "to", type: "address" },
      { name: "nonce", type: "uint256" }
    ]
  },
  primaryType: "Payment",
  message: {
    amount: "1000",
    currency: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    nonce: Date.now()
  }
});
4

Retry with Payment Header

Client retries the request with the X-PAYMENT header containing the signature
curl -i \
  -H "X-PAYMENT: 0x1234...abcd" \
  http://localhost:3000/ping
5

Server Verifies & Settles

Server verifies the signature and settles the payment on-chain
HTTP/1.1 200 OK
Content-Type: application/json
X-Transaction-Hash: 0xabc...def

{
  "message": "pong",
  "transactionHash": "0xabc...def"
}

Payment Flow Diagram

Basic Implementation

Server-Side (Express)

The simplest x402 server uses the x402-express middleware:
server.ts
import express from "express";
import { paymentMiddleware } from "x402-express";

const app = express();
const payTo = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb";

// Configure payment requirements
app.use(paymentMiddleware(payTo, {
  "GET /ping": { price: "$0.001", network: "base-sepolia" }
}));

// Protected endpoint
app.get("/ping", (_req, res) => {
  res.json({ message: "pong" });
});

app.listen(3000);
See ping/src/server.ts:1-22

Client-Side

Clients can handle 402 responses automatically:
import { createX402Client } from "x402-client";

const client = createX402Client({
  wallet: crossmintWallet,
  onPaymentRequired: async (requirement, retryFn) => {
    // 1. Show payment confirmation to user
    const approved = await confirmPayment(requirement);
    if (!approved) throw new Error("Payment declined");
    
    // 2. Sign payment
    const signature = await wallet.signPayment(requirement);
    
    // 3. Retry with signature
    return retryFn(signature);
  }
});

// Make request - automatically handles 402
const response = await client.get("http://localhost:3000/ping");

Payment Requirements Format

The 402 response must include a payment object:
payment.amount
string
required
Amount in token’s smallest unit (e.g., 6 decimals for USDC)Example: "1000" = 0.001 USDC
payment.currency
string
required
Token identifier (symbol or contract address)Example: "USDC" or "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
payment.to
string
required
Recipient wallet addressExample: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
payment.chainId
number
required
EVM chain IDExample: 84532 (Base Sepolia), 8453 (Base Mainnet)
payment.network
string
Human-readable network nameExample: "base-sepolia", "base"
payment.facilitator
string
URL of the x402 facilitator serviceExample: "https://x402.org/facilitator"

The Facilitator

The facilitator is a critical component that handles blockchain interactions:

Responsibilities

Signature Verification

Validates that signatures match the payment message and signer

Balance Checking

Ensures the payer has sufficient USDC balance

Transaction Submission

Submits USDC transfer transactions to the blockchain

Settlement Tracking

Returns transaction hashes for verification

Facilitator API

The facilitator exposes a simple verification endpoint:
POST /verify
Content-Type: application/json

{
  "signature": "0x1234...abcd",
  "message": {
    "amount": "1000",
    "currency": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    "to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "nonce": 1234567890
  },
  "signer": "0xGuestWalletAddress"
}
Response:
{
  "verified": true,
  "txHash": "0xabc...def",
  "blockNumber": 12345678
}
Production deployments should run their own facilitator or use a decentralized alternative. The public facilitator at https://x402.org/facilitator is for testing only.

EIP-712 Typed Data

The x402 protocol uses EIP-712 for human-readable signatures. Users see exactly what they’re signing:
{
  domain: {
    name: "x402 Payment",
    version: "1",
    chainId: 84532,
    verifyingContract: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
  },
  types: {
    Payment: [
      { name: "amount", type: "uint256" },
      { name: "currency", type: "address" },
      { name: "to", type: "address" },
      { name: "nonce", type: "uint256" }
    ]
  },
  primaryType: "Payment",
  message: {
    amount: "1000",      // 0.001 USDC
    currency: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    nonce: 1234567890
  }
}
In MetaMask or WalletConnect, this appears as:
Pay 0.001 USDC to 0x742d...0bEb
Much better than signing a random hex string!

Advantages

Uses standard HTTP status codes and headers. No WebSockets, no polling, no custom RPC.
Works with any HTTP server (Express, FastAPI, Cloudflare Workers, etc.)
AI agents can handle 402 responses just like 401 auth challenges
EIP-712 signatures prevent replay attacks and ensure non-repudiation
Currently supports EVM chains, but protocol design allows for Solana, Bitcoin, etc.

Real-World Examples

Ping

Minimal x402 server - perfect starting point

Weather API

Paid weather data with city parameter

Tweet Agent

Pay to post tweets via agent

Event RSVP

MCP-based event booking with payments

Next Steps

A2A Payments

Learn about agent-to-agent payment patterns

Smart Wallets

Understand Crossmint smart wallet integration

Payment Flow

Deep dive into end-to-end payment flows

Quickstart

Build your first x402 server

Resources

Build docs developers (and LLMs) love