Posted on Aug 29 Edited on Aug 31
AI agents are increasingly making programmatic requests, but traditional billing (credit cards, OAuth, complex API keys) creates friction for automated microtransactions.
With x402-express, you can monetize any Express.js endpoint using HTTP 402 payment requirements on Base in 3 lines of code.
1. Installation
bash
npm install x402-express
2. Implementation
Add the middleware to any route you want to protect:
javascript
const express = require(‘express’);
const { x402Middleware } = require(‘x402-express’);
const app = express();
app.get(‘/api/agent-data’, x402Middleware({ price: ‘0.01’ }), (req, res) => {
res.json({ message: “Payment verified via x402!” });
});
app.listen(3000, () => console.log(‘Server running on port 3000’));
3. Verification & Registry
- GitHub Repository: github.com/IkeHentrel/x402-express
-
MCP Registry:
io.github.ihen404/x402-express
When an unauthenticated agent hits your endpoint, x402-express interceptively returns an HTTP 402 Payment Required payload containing payment parameters, verifying settlements autonomously.
🌐 Paid API Specification
Endpoint: POST https://your-deployed-app.up.railway.app/api/scrape
Protocol: x402 (HTTP 402 Payment Required)
Price: $0.02 USDC per request
Network: Base (chainId: 8453)
Asset Contract: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 (USDC)
Payout Address: YOUR_BASE_WALLET_ADDRESS
1. Unauthenticated Request (HTTP 402 Challenge)
Send a standard POST request without payment headers:
bash
curl -i -X POST [https://your-deployed-app.up.railway.app/api/scrape](https://your-deployed-app.up.railway.app/api/scrape) \
-H "Content-Type: application/json" \
-d '{"url": "[https://news.ycombinator.com](https://news.ycombinator.com)"}'
Expected Response Header:
HTTP/1.1 402 Payment Required
X-Payment-Required: eyJzY2hlbWUiOiJleGFjdCIsInBheVRvIjoiMHhZT1V...
Paid Request (Machine-to-Machine via x402 Client)
AI agents using @ihentrel/x402-express or x402-fetch automatically parse the challenge header, sign a $0.02 USDC payment payload on Base, and retry:
import { fetchWithX402 } from 'x402-client';
const response = await fetchWithX402('[https://your-deployed-app.up.railway.app/api/scrape](https://your-deployed-app.up.railway.app/api/scrape)', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: '[https://news.ycombinator.com](https://news.ycombinator.com)' })
});
const data = await response.json();
console.log(data.markdown); // Returns clean Markdown ready for LLM context
Enter fullscreen mode Exit fullscreen mode