x402 Payment Required: Bridging HTTP and Blockchain for Pay-Per-Use Systems
A Developer's Guide to x402 Payment Required on the Blockchain

I am a software developer. I'm enthusiastic about tech and the way it ease life.
Introduction
Traditionally, HTTP status codes have been used to indicate the result of a client request. Most developers are familiar with:
200 OK→ Request succeeded401 Unauthorized→ Authentication required403 Forbidden→ Access denied
However, the HTTP status code 402 Payment Required has remained largely unused. Its original intention was to indicate that a client must make a payment to proceed.
With the rise of blockchain and stablecoins, this idea has evolved into a practical pay-before-access mechanism. In this article, we’ll explore how to implement x402 for blockchain-based payments and provide testable code samples.
What is x402 Payment Required?
x402 is a pattern for pay-per-use systems that links HTTP requests to on-chain cryptocurrency payments. It allows developers to:
Request payment for resources or actions
Verify on-chain payments
Grant access automatically once payment is confirmed
Key characteristics:
Works without user accounts
Supports micropayments
Blockchain-agnostic (any token-compatible chain)
Agent-friendly: APIs can be accessed by bots, scripts, or humans
Think of it as HTTP meets smart contracts.
How x402 Works (Step by Step)
Client requests a resource
Server responds with 402 Payment Required + payment instructions
Client pays on-chain (stablecoins, ERC-20 tokens, etc.)
Client retries the request with proof of payment
Server verifies payment on-chain
The server grants access
Step 1: Client request
GET /generate-report
Host: api.example.com
Step 2: Server responds with x402
HTTP/1.1 402 Payment Required
X-Payment-Address: 0xAbC1234DEF...
X-Payment-Amount: 0.1
X-Payment-Token: USDC
X-Payment-Chain: Sepolia
X-Payment-Expires: 2025-12-16T12:00:00Z
This tells the client:
"You must pay 0.1 USDC to this address before your request can proceed."
Step 3: Client pays on-chain
For testing purposes, we can use Ethers.js and Sepolia testnet:
import { ethers } from "ethers";
// Example wallet (use test private key!)
const provider = new ethers.JsonRpcProvider("https://sepolia.infura.io/v3/YOUR_INFURA_KEY");
const wallet = new ethers.Wallet("0xYOUR_PRIVATE_KEY", provider);
const recipient = "0xAbC1234DEF...";
const amount = ethers.parseUnits("0.1", 6); // USDC has 6 decimals
const usdcAddress = "0xYourUSDCContractOnSepolia"; // ERC20 USDC
// ERC20 ABI (minimal)
const ERC20_ABI = [
"function transfer(address to, uint256 amount) external returns (bool)"
];
const usdcContract = new ethers.Contract(usdcAddress, ERC20_ABI, wallet);
async function pay() {
const tx = await usdcContract.transfer(recipient, amount);
console.log("Transaction sent:", tx.hash);
await tx.wait();
console.log("Transaction confirmed!");
}
pay();
Once confirmed, the client can retry the original request with the transaction hash as proof.
Step 4: Client retries the request with proof
GET /generate-report
Host: api.example.com
X-Payment-Tx: 0xTransactionHash...
Step 5: Server verifies payment
The server can use Ethers.js or Web3.js to validate the transaction:
const tx = await provider.getTransaction("0xTransactionHash...");
if (
tx.to.toLowerCase() === recipient.toLowerCase() &&
tx.value.eq(amount)
) {
console.log("Payment verified. Access granted!");
} else {
console.log("Payment invalid or insufficient.");
}
Step 6: Server grants access
Once the payment is verified, the API returns:
HTTP/1.1 200 OK
Content-Type: application/json
{
"report": "Your generated report goes here..."
}
Key Implementation Considerations
Anti-replay protection
- Mark each x402 payment request as “used” to prevent replay attacks.
Expiration
- Payment requests should expire after a certain time.
Token support
- While USDC is common, any ERC-20 token can work.
Automation
- Clients can automate x402 payments using scripts or wallets.
Micropayments
- Enables pay-per-use pricing instead of subscriptions.




