Why Python + FastAPI for x402 Services
Python is the dominant language in AI and machine learning. If you're building an AI-powered API that charges per query using the x402 protocol, FastAPI is the natural choice — it's async, fast, and has built-in request validation with Pydantic. The x402 Python SDK makes it straightforward to add USDC micropayments to any FastAPI endpoint.
In this x402 Python FastAPI tutorial, you'll build a fully working pay-per-query AI API that accepts USDC payments on Base network. By the end, you'll have an API similar to AskClaude.shop — a live production service where AI agents pay per query to get Claude AI responses.
What You'll Build
A FastAPI service with three paid endpoints:
/ask— Ask Claude AI a question ($0.01 USDC per query)/summarize— Summarize any text ($0.005 USDC per request)/analyze— Analyze sentiment of text ($0.003 USDC per request)
Each endpoint accepts USDC micropayments via the x402 protocol on Base network. No API keys, no subscriptions — just pay and get your response.
Prerequisites
Before starting this x402 Python FastAPI tutorial, make sure you have:
- Python 3.10 or higher
- A Coinbase Developer Platform (CDP) account for the facilitator
- A wallet address on Base network to receive USDC payments
- An Anthropic API key (for the Claude AI integration)
- Basic familiarity with FastAPI and async Python
If you need a refresher on how x402 payments work under the hood, read the x402 payment flow explained article first.
Step 1: Project Setup
Create a new project directory and set up a virtual environment:
mkdir x402-ai-api
cd x402-ai-api
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
Install the required packages. The x402 Python SDK includes a FastAPI integration that handles payment verification automatically:
pip install "x402[fastapi]"
pip install anthropic
pip install python-dotenv
pip install uvicorn
The x402[fastapi] package gives you middleware that intercepts requests, verifies USDC payments with a facilitator, and only lets paid requests through to your endpoint handlers.
Step 2: Environment Configuration
Create a .env file with your credentials:
# .env
# Your wallet address on Base network (receives USDC payments)
WALLET_ADDRESS=0xYourWalletAddressHere
# Anthropic API key for Claude AI
ANTHROPIC_API_KEY=sk-ant-your-key-here
# CDP API credentials (for x402 facilitator)
CDP_API_KEY_ID=your-cdp-key-id
CDP_API_KEY_SECRET=your-cdp-key-secret
# Server settings
HOST=0.0.0.0
PORT=4021
Create a .gitignore so you never commit secrets:
# .gitignore
.env
venv/
__pycache__/
*.pyc
Step 3: Build the FastAPI Application
Create main.py — this is the core of your pay-per-query API:
import os
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import anthropic
from x402.fastapi import x402_middleware
load_dotenv()
# --- Configuration ---
WALLET_ADDRESS = os.getenv("WALLET_ADDRESS")
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
if not WALLET_ADDRESS:
raise ValueError("WALLET_ADDRESS is required in .env")
if not ANTHROPIC_API_KEY:
raise ValueError("ANTHROPIC_API_KEY is required in .env")
# --- Initialize FastAPI ---
app = FastAPI(
title="x402 AI API",
description="Pay-per-query AI API powered by x402 and Claude",
version="1.0.0",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# --- x402 Payment Middleware ---
# This middleware intercepts requests to paid routes,
# returns 402 Payment Required if no payment is provided,
# and verifies USDC payments with the facilitator.
x402_middleware(
app,
facilitator_url="https://x402.org/facilitator",
payment_address=WALLET_ADDRESS,
network="base",
)
# --- Claude AI Client ---
claude = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)
# --- Request Models ---
class AskRequest(BaseModel):
question: str
max_tokens: int = 500
class SummarizeRequest(BaseModel):
text: str
max_length: int = 200
class AnalyzeRequest(BaseModel):
text: str
# --- Free Endpoints (no payment required) ---
@app.get("/")
async def root():
"""Service info — free, no payment needed."""
return {
"service": "x402 AI API",
"description": "Pay-per-query AI powered by Claude",
"endpoints": {
"/ask": {"price": "$0.01 USDC", "method": "POST"},
"/summarize": {"price": "$0.005 USDC", "method": "POST"},
"/analyze": {"price": "$0.003 USDC", "method": "POST"},
},
"network": "base",
"currency": "USDC",
"powered_by": "x402 protocol",
}
# --- Paid Endpoints ---
@app.post("/ask", x402={"price": "0.01", "currency": "USDC"})
async def ask_claude(req: AskRequest):
"""Ask Claude AI a question. Costs $0.01 USDC per query."""
try:
response = claude.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=req.max_tokens,
messages=[
{"role": "user", "content": req.question}
],
)
return {
"answer": response.content[0].text,
"model": "claude-sonnet-4-20250514",
"tokens_used": response.usage.output_tokens,
"price_paid": "0.01 USDC",
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"AI error: {str(e)}")
@app.post("/summarize", x402={"price": "0.005", "currency": "USDC"})
async def summarize_text(req: SummarizeRequest):
"""Summarize text. Costs $0.005 USDC per request."""
if len(req.text) < 50:
raise HTTPException(
status_code=400,
detail="Text must be at least 50 characters to summarize.",
)
try:
response = claude.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=req.max_length,
messages=[
{
"role": "user",
"content": f"Summarize the following text in {req.max_length} words or fewer. Be concise and capture the key points:\n\n{req.text}",
}
],
)
return {
"summary": response.content[0].text,
"original_length": len(req.text),
"price_paid": "0.005 USDC",
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"AI error: {str(e)}")
@app.post("/analyze", x402={"price": "0.003", "currency": "USDC"})
async def analyze_sentiment(req: AnalyzeRequest):
"""Analyze text sentiment. Costs $0.003 USDC per request."""
if len(req.text) < 10:
raise HTTPException(
status_code=400,
detail="Text must be at least 10 characters.",
)
try:
response = claude.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=150,
messages=[
{
"role": "user",
"content": f'Analyze the sentiment of this text. Respond with a JSON object containing "sentiment" (positive/negative/neutral), "confidence" (0-1), and "explanation" (one sentence).\n\nText: {req.text}',
}
],
)
return {
"analysis": response.content[0].text,
"price_paid": "0.003 USDC",
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"AI error: {str(e)}")
Step 4: Understanding the x402 Payment Flow
Here's exactly what happens when a client calls your /ask endpoint:
- Client sends POST to /ask without any payment header.
- x402 middleware intercepts the request and sees no payment proof.
- Server responds with HTTP 402 (Payment Required), including the price (0.01 USDC), the wallet address, the network (Base), and the facilitator URL.
- Client authorizes a USDC transfer using EIP-3009 (gasless authorization) on Base.
- Client resubmits the request with the payment authorization in the
X-PAYMENTheader. - x402 middleware verifies payment with the facilitator, which checks the authorization is valid and settles the USDC.
- Request reaches your endpoint handler, Claude processes the query, and the response is returned.
The beauty of x402 is that your endpoint code doesn't need to know anything about payments. The middleware handles everything. Your /ask handler just processes the question and returns the answer.
Step 5: Run the Server
Start your API server:
uvicorn main:app --host 0.0.0.0 --port 4021 --reload
Visit http://localhost:4021 to see the service info (free endpoint). Visit http://localhost:4021/docs for the auto-generated FastAPI Swagger documentation.
Step 6: Test Your Paid Endpoints
To test the payment flow, you can use the x402 Python client. Create a test_client.py:
import httpx
from x402.client import x402_client
# Create an x402-aware HTTP client
# This client automatically handles the 402 → pay → retry flow
client = x402_client(
wallet_private_key="0xYourPrivateKeyHere", # Testnet key with USDC
network="base",
)
# Ask Claude a question (pays 0.01 USDC automatically)
response = client.post(
"http://localhost:4021/ask",
json={"question": "What is the x402 protocol?"},
)
print(response.json())
# {
# "answer": "x402 is an HTTP-native payment protocol...",
# "model": "claude-sonnet-4-20250514",
# "tokens_used": 142,
# "price_paid": "0.01 USDC"
# }
# Summarize text (pays 0.005 USDC)
response = client.post(
"http://localhost:4021/summarize",
json={
"text": "The x402 protocol enables machine-to-machine payments "
"using the HTTP 402 status code. It allows AI agents to pay "
"for API access with USDC micropayments on blockchain networks "
"like Base, without requiring API keys or subscriptions..."
},
)
print(response.json())
Step 7: Add Multiple Price Tiers
One of the strengths of x402 is per-endpoint pricing. You can charge different amounts for different endpoints based on the compute cost or value provided. Here's how to add a premium endpoint that uses a more powerful model:
@app.post("/ask-premium", x402={"price": "0.05", "currency": "USDC"})
async def ask_claude_premium(req: AskRequest):
"""Premium AI query with Claude Opus. Costs $0.05 USDC."""
try:
response = claude.messages.create(
model="claude-opus-4-20250514",
max_tokens=min(req.max_tokens, 2000),
messages=[
{"role": "user", "content": req.question}
],
)
return {
"answer": response.content[0].text,
"model": "claude-opus-4-20250514",
"tokens_used": response.usage.output_tokens,
"price_paid": "0.05 USDC",
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"AI error: {str(e)}")
This pattern — charging more for more expensive compute — is exactly how AskClaude.shop operates in production. Different models and capabilities have different prices, all handled automatically by the x402 middleware.
Step 8: Deploy to Production
For production deployment, you'll want a proper ASGI server and a reverse proxy. Here's a minimal production setup:
Create a run.py for production:
import uvicorn
import os
from dotenv import load_dotenv
load_dotenv()
if __name__ == "__main__":
uvicorn.run(
"main:app",
host=os.getenv("HOST", "0.0.0.0"),
port=int(os.getenv("PORT", 4021)),
workers=4, # Multiple workers for production
log_level="info",
access_log=True,
)
Set up with systemd (Linux) or launchd (macOS):
# /etc/systemd/system/x402-ai-api.service
[Unit]
Description=x402 AI API
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/x402-ai-api
ExecStart=/opt/x402-ai-api/venv/bin/python run.py
Restart=always
RestartSec=5
EnvironmentFile=/opt/x402-ai-api/.env
[Install]
WantedBy=multi-user.target
Then expose it through a Cloudflare tunnel or nginx reverse proxy with HTTPS. AI agents need a public URL to reach your API.
Step 9: Register on x402 Discovery Services
Once your API is live, register it so AI agents can find it:
- x402scan — List your endpoints on the x402scan marketplace so agents can discover your service.
- x402 Bazaar — Register with x402 Bazaar for automated bot discovery.
- Your own domain — Point a domain at your service. AI agents can discover x402 endpoints by querying your root URL.
Complete Project Structure
Here's what your finished project looks like:
x402-ai-api/
main.py # FastAPI app with x402 middleware and endpoints
run.py # Production server runner
test_client.py # Test script for payment flow
.env # Environment variables (never commit this)
.gitignore # Git ignore rules
requirements.txt # pip freeze output
venv/ # Virtual environment
Generate your requirements.txt:
pip freeze > requirements.txt
Key Takeaways
- x402 + FastAPI is minimal code. The middleware handles all payment logic. Your endpoint handlers stay clean and focused on business logic.
- Per-endpoint pricing gives you flexibility. Charge $0.003 for lightweight analysis and $0.05 for premium AI queries — all in the same service.
- Base network keeps costs low. USDC on Base has near-zero gas fees, making micropayments practical.
- No API keys to manage. Clients pay per request. No sign-up forms, no rate limit tiers, no billing dashboards.
- AI agents can consume your API autonomously. The x402 protocol is designed for machine-to-machine commerce — agents discover your service, pay per query, and move on.
To see this pattern running in production, check out AskClaude.shop — it uses this exact architecture to serve AI queries at scale with x402 micropayments.
For more on choosing the right facilitator for your service, read our facilitator comparison guide. And if you're coming from Node.js, the Node.js x402 tutorial covers the same concepts with Express.