x402 Protocol Documentation

What is x402?

x402 is a standardized HTTP-based payment protocol for monetizing API requests via Solana. It enables per-request micropayments with cryptographic proof verification.

Lightning Fast

Payments confirmed in milliseconds

Secure by Default

On-chain cryptographic proof verification

Developer First

Simple integration through middleware

POST/api/analyze
Request402 Payment RequiredPay200 OK

How It Works

1

Request & Challenge

Client requests a protected endpoint and receives a 402 response with payment details including amount, payee wallet, and facilitator URL.

2

Payment Processing

Client pays via facilitator using Solana USDC and receives a signed proof of payment with transaction hash and signature.

3

Verification & Access

Client retries the request with payment proof in headers. Server verifies the proof on-chain and grants access to the protected resource.

Installation

npm install @x402/middleware @x402/client
# or
yarn add @x402/middleware @x402/client

Environment Setup

X402_MERCHANT_WALLET=your_solana_wallet_address
X402_FACILITATOR_URL=https://facilitator.x402.network
X402_NETWORK=mainnet-beta
X402_MIN_PAYMENT=0.01

Basic Implementation

import express from 'express';
import { x402Middleware } from '@x402/middleware';

const app = express();

app.get('/api/generate',
  x402Middleware({ amount: "0.01', currency: "USDC' }),
  (req, res) => { 
    res.json(({ result: 'Your AI-generated content' }));
  ;

  (req, res) => { 
    res.json(({ result: 'Your AI-generated content' }));
  ;

app.listen(3000);

Middleware Configuration

const config = {
  amount: '0.05',
  currency: 'USDC',
  ttl: 120,
  facilitatorUrl: process.env.X402_FACILITATOR_URL,
  merchantWallet: process.env.X402_MERCHANT_WALLET,
  verifyOnChain: true,
  network: 'mainnet-beta'
;

app.use('/api/premium/*', x402Middleware(config));

Supports Solana, Base, and compatible networks.

402 Response Format

402
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
  "amount": "0.01",
  "currency": "USDC",
  "payee": "7xKz...merchant_wallet",
  "reference": "pay_abc123def456",
  "facilitatorUrl": "https://facilitator.x402.network",
  "ttl": "120",
  "message": "Payment required to access this resource"
}

Custom Verification

import { verifyPaymentProof } from '@x402/middleware';

async function customVerifier(proof) {
  const isValid = await verifyPaymentProof(proof);
  if (proof.amount < 0.01) throw new Error('Insufficient payment');
  if (Date.now() > proof.expiresAt) throw new Error('Payment expired');
  return isValid;
}

Payment Endpoint

POST /facilitator/pay
{
  "amount": "0.01",
  "currency": "USDC",
  "payee": "7xKz...merchant_wallet",
  "reference": "pay_abc123def456",
  "payer": "9yUv...payer_wallet"
}
Response:
{
  "txId": "2Qz7...hash",
  "signature": "3Rx8...facilitator_signature",
  "timestamp": 1698765432
}

Verification Endpoint

POST /facilitator/verify
{
  "reference": "pay_abc123def456",
  "signature": "3Rx8...facilitator_signature",
  "txId": "2Qz7...transaction_hash"
}
Response:
{
  "valid": true,
  "status": "confirmed"
}

X402 Client Usage

import { X402Client } from '@x402/client';

const client = new X402Client({
  facilitatorUrl: 'https://facilitator.x402.network',
  wallet: yourSolanaWallet,
  autoRetry: true
}); 

const response = await client.get('https://api.example.com/generate');
console.log(response.data);

Manual Payment Flow

// Step 1: Make initial request
const response = await fetch('/api/analyze');
if (response.status === 402) {
  const paymentDetails = await response.json();

  // Step 2: Pay via facilitator
  const paymentResponse = await fetch(paymentDetails.facilitatorUrl + '/pay', {
    method: 'POST',
    body: JSONstringify({
      amount: paymentDetails.amount,
      payee: paymentDetails.payee,
      reference: paymentDetails.reference
    })
  }); 

  const proof = await paymentResponse.json();

  // Step 3: Retry with proof
  const finalResponse = await fetch('/api/analyze', {
    headers: {
      'X-Payment-Proof': proof.signature,
      'X-Payment-TxId': proof.txId
    }
  }); 

  const data = await finalResponse.json();
}

React Integration

import { useX402 } from '@x402/react';

function MyComponent() {
  const { call, loading, error } = useX402();

  const handleGenerate = async () => {
    const result = await call('/api/generate');
    console.log(result);
  ;

  return (
    <button onClick={handleGenerate} disabled={loading}>
      {loading ? 'Processing payment...' : 'Generate'}
    </button>
  );
}

Need Help?

Get support, join the community, or report issues with the x402 protocol.