You built an API. It's good. Maybe it serves weather data, runs AI inference, or crunches analytics. Now you want to get paid for it.
The traditional path looks like this: sign up for Stripe, integrate their SDK, handle webhooks, manage subscriptions, deal with chargebacks, wait for T+2 settlement, eat 2.9% + 30 cents per transaction. Oh, and forget about charging a tenth of a cent per request — minimum transaction thresholds make micropayments impossible.
x402 flips all of that. It's an open protocol that adds payments to any HTTP endpoint using the 402 Payment Required status code that's been sitting unused in the HTTP spec since 1997. One line of middleware. USDC settles directly to your wallet. No accounts, no minimums, no percentage cuts. Sub-cent payments are not only possible — they're the whole point.
Here's how to set it up.
Prerequisites
You need three things:
- A crypto wallet to receive USDC. Any EVM-compatible wallet works — MetaMask, Coinbase Wallet, a hardware wallet, a multisig. Grab your address and keep it handy.
- Node.js, Go, or Python installed on your machine. x402 has SDKs for all three.
- An existing API or server. If you don't have one, we'll build a simple Express server from scratch below.
That's it. No API keys to register for. No merchant accounts to apply to. No KYC forms.
Step 1 — Install dependencies
Pick your framework and install the x402 packages.
Express (Node.js):
npm install @x402/express @x402/core @x402/evm
Next.js:
npm install @x402/next @x402/core @x402/evm
Hono:
npm install @x402/hono @x402/core @x402/evm
Go:
go get github.com/coinbase/x402/go
Python (FastAPI):
pip install "x402[fastapi]"
Python (Flask):
pip install "x402[flask]"
The @x402/core package handles the protocol logic. The @x402/evm package handles Base-specific payment verification. The framework package (@x402/express, @x402/next, @x402/hono) is just a thin middleware adapter that plugs into your server's request lifecycle.
Step 2 — Add payment middleware
This is where it gets real. You're going to wrap your existing routes with a payment gate. Requests without valid payment get a 402 response. Requests with payment sail through to your handler like nothing changed.
Express
Here's a complete working server:
import express from "express";
import { paymentMiddleware } from "@x402/express";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const app = express();
// Your wallet address — this is where USDC lands
const payTo = "0xYourWalletAddress";
// The facilitator verifies payments and handles settlement
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator",
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
// Define which routes require payment and how much
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:84532", // Base Sepolia testnet
payTo,
},
],
description: "Get current weather data",
mimeType: "application/json",
},
},
server,
),
);
// Your actual route handler — unchanged
app.get("/weather", (req, res) => {
res.json({ weather: "sunny", temperature: 70 });
});
app.listen(4021, () => {
console.log("Server running on port 4021");
});
That's the whole thing. Your /weather endpoint now requires a $0.001 USDC payment on Base Sepolia. Every other aspect of your server is untouched.
Let's break down the key parts:
payTo— your wallet address. USDC goes here. Period.HTTPFacilitatorClient— points to a facilitator service that verifies payment signatures and settles transactions. The hosted one atx402.orgworks out of the box.registerExactEvmScheme— registers the "exact" payment scheme for EVM chains. This means "pay exactly this amount."paymentMiddleware— takes a route map and the server instance. Routes not in the map are unprotected and work normally.
Next.js
For Next.js, you use middleware to intercept requests before they hit your API routes:
// middleware.ts
import { paymentMiddleware } from "@x402/next";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const payTo = "0xYourWalletAddress";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator",
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
export const middleware = paymentMiddleware(
{
"GET /api/weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:84532",
payTo,
},
],
description: "Get current weather data",
mimeType: "application/json",
},
},
server,
);
export const config = {
matcher: "/api/:path*",
};
Then your API route stays completely standard:
// app/api/weather/route.ts
export async function GET() {
return Response.json({ weather: "sunny", temperature: 70 });
}
The middleware intercepts matching requests, checks for payment, and either returns a 402 or lets the request through. Your route handler never knows the difference.
Hono
Hono's middleware pattern is equally clean:
import { Hono } from "hono";
import { paymentMiddleware } from "@x402/hono";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const app = new Hono();
const payTo = "0xYourWalletAddress";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator",
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
app.use(
"*",
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:84532",
payTo,
},
],
description: "Get current weather data",
mimeType: "application/json",
},
},
server,
),
);
app.get("/weather", (c) => {
return c.json({ weather: "sunny", temperature: 70 });
});
export default app;
Same pattern every time. Define your routes, set your prices, plug in the middleware. The framework adapter handles the rest.
Step 3 — Understand the payment flow
Here's what happens when a request hits your server, step by step:
1. Request arrives without payment.
The middleware sees no X-PAYMENT header. It responds with HTTP 402 Payment Required and includes a response body describing what payment is needed — the price, the network, the wallet address, the accepted scheme. This is machine-readable. Clients that understand x402 know exactly what to do next.
2. Client sends a new request with payment.
The client crafts a payment authorization (a signed EIP-712 message), attaches it in the X-PAYMENT header, and retries the request.
3. Middleware verifies the payment. Your server forwards the payment data to the facilitator, which verifies the signature, checks that the amount and recipient match, and confirms the payment is valid. This happens in milliseconds.
4. Request proceeds to your handler.
If the facilitator says it's good, the middleware calls next() and your route handler runs exactly as it would without any payment layer. The request object is unchanged. Your business logic doesn't need to know payments exist.
5. Settlement happens. The facilitator settles the USDC transfer onchain. The funds land in your wallet. On Base, this costs a fraction of a cent in gas and confirms in seconds.
The beauty of this flow is that your application code never changes. The middleware handles everything. You write your API logic, the payment layer wraps around it like a shell.
Step 4 — Pricing strategies
x402 on Base unlocks pricing models that are simply impossible with traditional payment rails.
Micropayments
Charge $0.001 per request. Or $0.0001. On Base, gas costs are sub-cent, so payments this small are economically viable for the first time. This is the sweet spot for high-volume, low-value API calls — weather lookups, geocoding, simple data queries.
Tiered pricing
Different endpoints, different prices. A simple data fetch is cheap. A compute-heavy analysis costs more:
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:84532",
payTo,
},
],
description: "Current weather data",
mimeType: "application/json",
},
"GET /forecast": {
accepts: [
{
scheme: "exact",
price: "$0.01",
network: "eip155:84532",
payTo,
},
],
description: "7-day weather forecast",
mimeType: "application/json",
},
"POST /analyze": {
accepts: [
{
scheme: "exact",
price: "$0.10",
network: "eip155:84532",
payTo,
},
],
description: "Deep weather pattern analysis",
mimeType: "application/json",
},
},
server,
),
);
This maps naturally to how APIs actually work. Simple reads are cheap. Writes and computation cost more. Your pricing reflects your costs.
Usage-based pricing
The "upto" payment scheme is coming soon. Instead of a fixed price, the client authorizes up to a maximum amount, and you charge based on actual usage — tokens consumed, compute time, data volume. Think of it like a pre-authorized hold on a credit card, but settled precisely for what was used.
This is going to be huge for AI inference APIs where cost varies wildly by prompt length.
Pro tip
Start on testnet. Use eip155:84532 (Base Sepolia) while you're building. Test your flow end-to-end with fake money. Get everything working. Then flip to mainnet. The switch is trivial — we'll cover it next.
Step 5 — Go to mainnet
Ready for real money? Two changes:
1. Switch the network identifier:
- network: "eip155:84532", // Base Sepolia testnet
+ network: "eip155:8453", // Base mainnet
2. Point to a production facilitator:
- url: "https://x402.org/facilitator"
+ url: "https://your-production-facilitator.com"
That's it. Literally two config values. Your route handlers don't change. Your pricing config stays the same. Your middleware setup is identical. You just swapped which chain you're on and which facilitator verifies payments.
The fact that going from testnet to mainnet is a two-line diff is not an accident. The protocol was designed this way. Your development and production code should be nearly identical.
Multi-endpoint setup
Most real-world APIs have more than one endpoint. Here's what a more realistic configuration looks like:
const routeConfig = {
"GET /api/v1/weather/current": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:8453",
payTo,
},
],
description: "Current weather for a given location",
mimeType: "application/json",
},
"GET /api/v1/weather/forecast": {
accepts: [
{
scheme: "exact",
price: "$0.01",
network: "eip155:8453",
payTo,
},
],
description: "7-day forecast with hourly breakdown",
mimeType: "application/json",
},
"GET /api/v1/weather/historical": {
accepts: [
{
scheme: "exact",
price: "$0.05",
network: "eip155:8453",
payTo,
},
],
description: "Historical weather data for analysis",
mimeType: "application/json",
},
"POST /api/v1/weather/analyze": {
accepts: [
{
scheme: "exact",
price: "$0.10",
network: "eip155:8453",
payTo,
},
],
description: "AI-powered weather pattern analysis",
mimeType: "application/json",
},
};
app.use(paymentMiddleware(routeConfig, server));
Routes not listed in the config object are unprotected — they work normally without any payment. So your health check at /health or your docs at /api/docs stay free. Only the routes you explicitly list require payment.
You can also mix free and paid endpoints in the same server without any gymnastics. No route groups, no separate middleware stacks. One config object controls everything.
Advanced — Self-hosting a facilitator
The hosted facilitator at x402.org works great for getting started and for most production use cases. But if you want full control over the payment verification and settlement pipeline, you can run your own.
Reasons you might want to self-host:
- Privacy — you don't want a third party seeing your payment traffic
- Latency — co-locate the facilitator with your API server for faster verification
- Customization — modify settlement logic, add custom payment schemes, integrate with your own infrastructure
- Uptime guarantees — your facilitator, your SLA
The facilitator implementation is open source in the coinbase/x402 repository. Clone it, configure it, deploy it wherever you run infrastructure.
That said, most merchants should use a hosted facilitator. It's one less thing to operate, and the protocol is designed so that the facilitator never custodies your funds. It verifies and settles — the USDC goes directly to your wallet address regardless of who runs the facilitator.
What you're actually getting paid
Let's be concrete about the money flow.
USDC arrives directly in your wallet. Not in an escrow. Not in a platform balance you have to withdraw. Directly in the wallet address you specified in payTo. You can check it on Basescan.
No intermediary holds your money. The facilitator verifies payments and triggers settlement, but it never takes custody. Your funds flow from the buyer's wallet to yours. That's it.
No T+2 settlement. Traditional payment processors batch transactions and settle days later. On Base, settlement is onchain and final in seconds. You can see the USDC hit your wallet in real time.
Zero protocol fees. x402 is an open protocol. There's no percentage cut, no per-transaction fee, no monthly platform charge. The only cost is Base gas for the settlement transaction — and on Base, that's sub-cent. We're talking fractions of a penny.
Compare that to Stripe's 2.9% + $0.30. On a $0.001 micropayment, Stripe would charge you more in fees than the payment itself. x402 makes the economics work at any price point.
Real-world use cases
x402 isn't theoretical. Here's where merchants are using it today and where it's headed:
AI inference APIs. Charge per generation, per token, per image. An LLM wrapper that charges $0.01 per completion. A Stable Diffusion API at $0.05 per image. The pricing maps directly to your compute costs, and you don't need to manage API keys or subscription tiers.
Data feeds. Weather data, market prices, analytics, geolocation. Charge per query instead of forcing users into monthly plans. A developer who needs 10 requests doesn't have to pay for a plan that covers 10,000.
Premium content. Articles, research reports, datasets. Pay-per-read without a paywall login system. The reader's x402 client handles payment automatically — they click, they pay a cent, they read.
Developer tools. Compilation services, testing infrastructure, deployment pipelines. Charge per build, per test run, per deployment. Usage-based pricing that matches actual resource consumption.
Any HTTP endpoint. That's the point. If it responds to HTTP requests, you can put a price on it. x402 doesn't care what your API does. It's a transport-layer payment protocol. Your business logic is your business.
The most interesting use case is probably AI agents as customers. Agents that autonomously browse the web, consume APIs, and pay for resources as they go. x402 gives them a way to pay for any endpoint without pre-negotiated API keys or accounts. The agent sees a 402, pays, and gets the data. Read more about that side in our guide on using x402 as an AI agent.
Wrapping up
You now know how to monetize any HTTP API with x402 on Base. The setup takes minutes: install the SDK, add one middleware call, specify your wallet address and prices. That's the whole integration.
The protocol handles everything else — the 402 response for unpaid requests, signature verification, onchain settlement, USDC delivery to your wallet. You write your API logic. x402 handles the money.
Start on testnet. Get your flow working. Flip two config lines for mainnet. Collect USDC.
If you want to understand the protocol itself at a deeper level — the HTTP semantics, the payment negotiation, why 402 exists in the first place — read What is x402. If you're building the other side (a client or agent that pays for x402 APIs), check out Use x402 as an AI agent.
Related guides
- What is the x402 payment protocol — The big picture on how x402 works and why it matters
- Use x402 as an AI agent — The buyer side: how agents and clients pay for x402-protected APIs