Accept USDC payments for API endpoints using x402 protocol. Use when creating paid API endpoints, monetizing services with micropayments, building AI agents that sell data or services, or setting up payment middleware for Express, Hono, Next.js, FastAPI, Flask, or Go servers. Supports EVM (Base, Ethereum, Avalanche) and Solana via CDP Facilitator.
Resources
1Install
npx skillscat add must-be-ash/x402-skills/sell Install via the SkillsCat registry.
x402 Sell Skill
Enable AI agents to sell resources and accept USDC payments for API endpoints using x402.
Overview
x402 allows servers to payment-gate endpoints. When clients request a protected resource without payment, the server returns HTTP 402 with payment requirements. The server uses a Facilitator (like Coinbase CDP) to verify and settle payments on-chain.
Quick Start
1. Setup Receiving Wallet
Create a wallet to receive payments.
Non-interactive CLI commands (for AI agents):
# EVM wallet (Base, Ethereum, Avalanche) - pipes "1" to select EOA
echo "1" | npx add-wallet evm
# Solana wallet
npx add-wallet sol
# Top up with testnet USDC (for testing payments)
npx add-wallet topup testnetThis creates a .env file with WALLET_ADDRESS and WALLET_PRIVATE_KEY.
Use the address in your code:
// Read from .env or use directly
const payTo = process.env.WALLET_ADDRESS; // From .env file
// or
const payTo = "0xYourWalletAddress"; // EVM address
// or
const payTo = "YourSolanaAddress"; // Solana address2. Install Packages
# Express
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
# For Solana support:
npm install @x402/svm3. Add Payment Middleware (Express)
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();
const payTo = "0xYourAddress";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://api.cdp.coinbase.com/platform/v2/x402" // Mainnet (default)
// url: "https://x402.org/facilitator" // Testnet
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:8453", // Base Mainnet (use eip155:84532 for testnet)
payTo,
},
],
description: "Get weather data",
mimeType: "application/json",
},
},
server,
),
);
app.get("/weather", (req, res) => {
res.json({ weather: "sunny", temperature: 70 });
});
app.listen(4021);Facilitator URLs
Default: Mainnet (CDP) - Use for production payments.
| Environment | URL |
|---|---|
| Mainnet (CDP) | https://api.cdp.coinbase.com/platform/v2/x402 (default) |
| Testnet | https://x402.org/facilitator |
Price Format
The price field uses dollar notation. SDK converts to atomic units automatically.
| Price | Meaning | Atomic Units |
|---|---|---|
"$0.001" |
0.1 cents | 1000 |
"$0.01" |
1 cent | 10000 |
"$0.10" |
10 cents | 100000 |
"$1.00" |
1 dollar | 1000000 |
Network Identifiers (CAIP-2)
Default: Base Mainnet (eip155:8453) - Use for production payments.
| Network | CAIP-2 ID | Environment |
|---|---|---|
| Base Mainnet | eip155:8453 |
Production (default) |
| Avalanche C-Chain | eip155:43114 |
Production |
| Solana Mainnet | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
Production |
| Base Sepolia | eip155:84532 |
Testnet |
| Avalanche Fuji | eip155:43113 |
Testnet |
| Solana Devnet | solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
Testnet |
USDC Token Addresses
| Network | USDC Contract Address |
|---|---|
Base Mainnet (eip155:8453) |
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
Base Sepolia (eip155:84532) |
0x036CbD53842c5426634e7929541eC2318f3dCF7e |
Avalanche (eip155:43114) |
0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E |
| Solana Mainnet | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
Framework Examples
Next.js
// middleware.ts
import { paymentProxy } from "@x402/next";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://api.cdp.coinbase.com/platform/v2/x402" // Mainnet
});
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
export const middleware = paymentProxy(
{
"/api/protected": {
accepts: [{ scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "0xYour" }],
description: "Protected content",
},
},
server,
);
export const config = { matcher: ["/api/protected/:path*"] };Hono
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 facilitatorClient = new HTTPFacilitatorClient({ url: "https://api.cdp.coinbase.com/platform/v2/x402" });
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
app.use(
paymentMiddleware(
{
"/paid": {
accepts: [{ scheme: "exact", price: "$0.10", network: "eip155:8453", payTo: "0xYour" }],
},
},
server,
),
);
app.get("/paid", (c) => c.json({ message: "Premium content" }));Go (Gin)
import (
x402 "github.com/coinbase/x402/go"
x402http "github.com/coinbase/x402/go/http"
ginmw "github.com/coinbase/x402/go/http/gin"
evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
URL: "https://api.cdp.coinbase.com/platform/v2/x402", // Mainnet
})
r.Use(ginmw.X402Payment(ginmw.Config{
Routes: x402http.RoutesConfig{
"GET /weather": {
Accepts: x402http.PaymentOptions{
{Scheme: "exact", Price: "$0.001", Network: "eip155:8453", PayTo: "0xYour"},
},
Description: "Weather data",
},
},
Facilitator: facilitatorClient,
Schemes: []ginmw.SchemeConfig{
{Network: "eip155:8453", Server: evm.NewExactEvmScheme()},
},
}))
r.GET("/weather", func(c *gin.Context) {
c.JSON(200, gin.H{"weather": "sunny"})
})
r.Run(":4021")
}Python (FastAPI)
from fastapi import FastAPI
from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServer
app = FastAPI()
pay_to = "0xYourAddress"
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402") # Mainnet
)
server = x402ResourceServer(facilitator)
server.register("eip155:8453", ExactEvmServerScheme())
routes = {
"GET /weather": RouteConfig(
accepts=[PaymentOption(scheme="exact", pay_to=pay_to, price="$0.001", network="eip155:8453")],
description="Weather data",
),
}
app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
@app.get("/weather")
async def get_weather():
return {"weather": "sunny", "temperature": 70}Multi-Network Support
Accept payments on both EVM and Solana (mainnet):
import { registerExactEvmScheme } from "@x402/evm/exact/server";
import { registerExactSvmScheme } from "@x402/svm/exact/server";
const server = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(server);
registerExactSvmScheme(server);
app.use(
paymentMiddleware(
{
"GET /data": {
accepts: [
{ scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "0xYourEvmAddress" }, // Base Mainnet
{ scheme: "exact", price: "$0.01", network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", payTo: "YourSolanaAddress" }, // Solana Mainnet
],
},
},
server,
),
);Bazaar Discovery
Make your endpoint discoverable:
import { declareDiscoveryExtension } from "@x402/extensions/bazaar";
app.use(
paymentMiddleware(
{
"GET /weather": {
accepts: [{ scheme: "exact", price: "$0.001", network: "eip155:8453", payTo }], // Base Mainnet
description: "Real-time weather data",
mimeType: "application/json",
extensions: {
...declareDiscoveryExtension({
input: { city: "San Francisco" },
inputSchema: { properties: { city: { type: "string" } }, required: ["city"] },
output: { example: { city: "San Francisco", weather: "foggy" } },
}),
},
},
},
server,
),
);Server Payment Flow
- Client requests protected endpoint
- Server returns 402 Payment Required with
PAYMENT-REQUIREDheader - Client creates payment and sends with
PAYMENT-SIGNATUREheader - Server verifies payment via Facilitator (
/verify) - Server executes endpoint handler
- Server settles payment via Facilitator (
/settle) - Server returns response with
PAYMENT-RESPONSEheader
Testing Your Server
curl -i http://localhost:4021/weather
# Expected: HTTP/1.1 402 Payment Required
# PAYMENT-REQUIRED: <base64-encoded payment requirements>Setup Checklist
- Get a wallet address - Run
echo "1" | npx add-wallet evm(non-interactive) - Note the address - Check
.envforWALLET_ADDRESSto use aspayTo - Choose network - Use
eip155:8453(Base Mainnet) for production, oreip155:84532(Base Sepolia) for testing - Set price - Use dollar notation (
"$0.001") - Configure facilitator - Use
https://api.cdp.coinbase.com/platform/v2/x402for mainnet (orhttps://x402.org/facilitatorfor testnet) - Add middleware - Protect routes with payment requirements
- Test - curl should return 402 with payment instructions
Key Packages
TypeScript
@x402/express- Express.js middleware@x402/next- Next.js middleware@x402/hono- Hono middleware@x402/core- Core server utilities@x402/evm- EVM scheme@x402/svm- Solana scheme
Go
github.com/coinbase/x402/go- Core packagegithub.com/coinbase/x402/go/http/gin- Gin middleware
Python
x402[fastapi]- FastAPI supportx402[flask]- Flask support