Theory is great. Working code is better.
You'll build a complete x402 payment flow: a server that requires payment and a client that pays. We're using Base Sepolia (testnet) so you can experiment without spending real money.
By the end, you'll have made an actual blockchain payment for an API call.
Prerequisites
- Node.js 18+
- A code editor
- 5 minutes
That's it. No prior blockchain experience required.
Step 1: Project Setup
Create a new project and install dependencies:
mkdir x402-tutorial && cd x402-tutorial
npm init -y
npm install hono @hono/node-server viem x402-hono
npm install -D typescript @types/node tsx
Step 2: Create a Wallet
You need a wallet to receive and send payments. Generate one programmatically:
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
const privateKey = generatePrivateKey();
const account = privateKeyToAccount(privateKey);
console.log('Address:', account.address);
console.log('Private Key:', privateKey);
Step 3: Fund Your Test Wallet
Your client wallet needs testnet funds before making payments.
Get Testnet ETH
Visit the Alchemy Base Sepolia Faucet:
- Enter your client wallet address
- Click "Get tokens"
- Wait for the transaction (~30 seconds)
Get Testnet USDC
Base Sepolia USDC address: 0x036CbD53842c5426634e7929541eC2318f3dCF7e
Step 4: Build the Server
Create a server that requires payment for its endpoints using x402:
import { serve } from '@hono/node-server';
import { Hono } from 'hono';
const SERVER_WALLET = process.env.SERVER_WALLET || '0xYOUR_SERVER_WALLET';
const PRICE_AMOUNT = 1000n; // 0.001 USDC (6 decimals)
const app = new Hono();
app.get('/api/data', async (c) => {
const paymentProof = c.req.header('X-Payment-Proof');
if (!paymentProof) {
return c.json(
{ error: 'Payment required' },
402,
{
'X-Payment-Address': SERVER_WALLET,
'X-Payment-Amount': PRICE_AMOUNT.toString(),
'X-Payment-Asset': 'USDC',
'X-Payment-Network': 'base-sepolia',
}
);
}
// Verify payment and return data
return c.json({ message: 'You paid for this data!' });
});
serve({ fetch: app.fetch, port: 3000 });
Step 5: Build the Client
Create a client that handles the 402 flow automatically:
import { createWalletClient, createPublicClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { baseSepolia } from 'viem/chains';
const PRIVATE_KEY = process.env.CLIENT_PRIVATE_KEY as `0x${string}`;
const account = privateKeyToAccount(PRIVATE_KEY);
async function fetchWithPayment(url: string) {
// First request
const response = await fetch(url);
if (response.status !== 402) {
return response.json();
}
// Handle payment
const paymentAddress = response.headers.get('X-Payment-Address')!;
const paymentAmount = response.headers.get('X-Payment-Amount')!;
// Execute payment and retry
const txHash = await makePayment(paymentAddress, BigInt(paymentAmount));
return fetch(url, {
headers: { 'X-Payment-Proof': `tx:${txHash}` }
}).then(r => r.json());
}
Step 6: Run It
Open two terminal windows.
Terminal 1 - Start the server:
npx tsx src/server.ts
Terminal 2 - Run the client:
npx tsx src/client.ts
You just made your first x402 micropayment.
What Just Happened?
- Initial Request: Client calls
/api/datawith no payment - 402 Response: Server returns payment requirements in headers
- Payment: Client transfers USDC on Base Sepolia
- Proof: Client includes transaction hash in retry request
- Verification: Server verifies the on-chain transfer
- Response: Server returns the protected data
The entire payment—from request to response—takes about 3 seconds on testnet. On mainnet with proper RPC nodes, it's under 2 seconds.
Switching to Mainnet
When you're ready for real money:
- Change the network: Use
baseinstead ofbaseSepolia - Update USDC address:
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 - Fund with real USDC on Base
Same code, real payments.
Next Steps
You've built a working x402 payment flow. From here:
- Deploy the server to Cloudflare Workers for global distribution
- Add dynamic pricing based on request complexity
- Register on nullpath to get discovered by AI agents
The machine economy is pay-per-request. You just built its foundation.
