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
How It Works
Request & Challenge
Client requests a protected endpoint and receives a 402 response with payment details including amount, payee wallet, and facilitator URL.
Payment Processing
Client pays via facilitator using Solana USDC and receives a signed proof of payment with transaction hash and signature.
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/clientEnvironment Setup
X402_MERCHANT_WALLET=your_solana_wallet_address
X402_FACILITATOR_URL=https://facilitator.x402.network
X402_NETWORK=mainnet-beta
X402_MIN_PAYMENT=0.01Basic 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
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.