HTTP 402 Payment Protocol - Complete Implementation Guide
What is HTTP 402?
HTTP 402 is a standard HTTP status code meaning "Payment Required". ChainX Protocol implements a complete payment protocol using blockchain transactions (Solana, Base, BSC).
Step 1: Client Makes Initial Request
// Client requests protected resource
const response = await fetch('https://chainx402.xyz/api/data', {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
console.log('Status:', response.status); // Will be 402
Step 2: Server Responds with HTTP 402
HTTP/1.1 402 Payment Required
X-Payment-Required: true
X-Payment-Id: payment_abc123xyz
X-Payment-Amount: 0.0004
X-Payment-Token: USDC
X-Payment-Token-Mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
X-Payment-To: SELLER_WALLET_ADDRESS
X-Payment-Memo: ChainX:payment_abc123xyz
X-Payment-Facilitator: https://chainx402.xyz/facilitator
{
"error": "Payment Required",
"code": 402,
"payment": {
"id": "payment_abc123xyz",
"amount": 0.0004,
"token": "USDC"
}
}
Step 3: Client Reads Payment Headers
if (response.status === 402) {
const paymentId = response.headers.get('X-Payment-Id');
const amount = parseFloat(response.headers.get('X-Payment-Amount'));
const token = response.headers.get('X-Payment-Token');
const sellerWallet = response.headers.get('X-Payment-To');
const facilitatorUrl = response.headers.get('X-Payment-Facilitator');
console.log('Payment Required:', { paymentId, amount, token });
}
Step 4: Client Creates Payment Transaction
// Get payment instructions from facilitator
const paymentRequest = await fetch(`${facilitatorUrl}/payment/request`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chain: 'solana',
seller: sellerWallet,
amount: amount,
token: token,
tokenMint: tokenMint,
metadata: {
apiEndpoint: '/protected-data',
paymentId: paymentId
}
})
});
const { paymentId: facilitatorPaymentId, paymentInstructions } =
await paymentRequest.json();
Step 5: Client Signs and Sends Blockchain Transaction
// Solana payment transaction
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import { getAssociatedTokenAddress, createTransferInstruction } from '@solana/spl-token';
async function sendPayment(instructions, wallet) {
const connection = new Connection('https://api.mainnet-beta.solana.com');
// Get token accounts
const tokenMint = new PublicKey(instructions.tokenMint);
const sellerWallet = new PublicKey(instructions.to);
const buyerTokenAccount = await getAssociatedTokenAddress(
tokenMint, wallet.publicKey
);
const sellerTokenAccount = await getAssociatedTokenAddress(
tokenMint, sellerWallet
);
// Create transfer instruction
const transferInstruction = createTransferInstruction(
buyerTokenAccount,
sellerTokenAccount,
wallet.publicKey,
instructions.amount * 1e6, // USDC has 6 decimals
[],
TOKEN_PROGRAM_ID
);
// Create and sign transaction
const transaction = new Transaction().add(transferInstruction);
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = wallet.publicKey;
const signed = await wallet.signTransaction(transaction);
const signature = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(signature);
return signature;
}
const signature = await sendPayment(paymentInstructions, wallet);
Step 6: Client Verifies Payment with Facilitator
const verifyResponse = await fetch(`${facilitatorUrl}/payment/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
paymentId: facilitatorPaymentId,
signature: signature,
chain: 'solana'
})
});
const verification = await verifyResponse.json();
// { status: 'verified', paymentId: '...', signature: '...' }
Step 7: Client Retries Request with Payment Proof
// Retry original request with payment headers
const paidResponse = await fetch('https://chainx402.xyz/api/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Payment-Id': paymentId,
'X-Payment-Signature': signature
}
});
if (paidResponse.status === 200) {
const data = await paidResponse.json();
console.log('Protected data:', data);
}
Step 8: Server Verifies Payment and Grants Access
// Server middleware verifies payment
async function verifyPayment(paymentId, signature) {
const response = await fetch(`${facilitatorUrl}/payment/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ paymentId, signature })
});
const result = await response.json();
return result.status === 'verified';
}
// Protected endpoint
app.get('/protected-data', async (req, res) => {
const paymentId = req.headers['x-payment-id'];
const signature = req.headers['x-payment-signature'];
if (!paymentId || !signature) {
return res.status(402).json({ error: 'Payment Required' });
}
const isValid = await verifyPayment(paymentId, signature);
if (!isValid) {
return res.status(402).json({ error: 'Payment verification failed' });
}
// Payment verified, return data
return res.json({ data: 'Protected content here' });
});
Complete Example: Paid API Server
// server.ts
import { createPaidAPIServer } from '@ChainX/seller-sdk';
const server = await createPaidAPIServer({
facilitatorUrl: process.env.FACILITATOR_URL,
sellerWallet: 'YOUR_WALLET_ADDRESS',
defaultToken: 'USDC',
defaultTokenMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
pricePerRequest: 0.0004, // $0.0004 USDC
port: 3000
});
console.log('ChainX Protocol API Server running on port 3000');
Complete Example: Client with Auto-Payment
// client.ts
import { createAPIClient } from '@ChainX/buyer-sdk';
const client = createAPIClient({
facilitatorUrl: process.env.FACILITATOR_URL,
rpcUrl: 'https://api.mainnet-beta.solana.com'
});
// Automatically handles 402, payment, and retry
const data = await client.get('https://chainx402.xyz', '/api/data', {
fromWallet: wallet.publicKey,
signTransaction: wallet.signTransaction
});
console.log('Data:', data);
HTTP 402 Headers Reference
| Header | Description | Example |
|---|---|---|
X-Payment-Id |
Unique payment identifier | payment_abc123 |
X-Payment-Amount |
Payment amount (decimal) | 0.0004 |
X-Payment-Token |
Token symbol | USDC |
X-Payment-To |
Seller wallet address | YOUR_WALLET_ADDRESS |
X-Payment-Signature |
Transaction signature (retry) | 5j7s8... |
Key Benefits
- ✅ Standard HTTP Status Code - Uses official HTTP 402
- ✅ Blockchain Payments - Supports Solana, Base, BSC
- ✅ Sub-second Verification - Fast payment confirmation
- ✅ Programmatic - Works with AI agents and automation
- ✅ No Subscriptions - Pay per request
- ✅ Automatic - SDK handles entire flow