Creating x402 Payment-Protected Servers in Python
Build FastAPI (async) or Flask (sync) servers that protect API endpoints behind Algorand USDC payments using x402 middleware.
Prerequisites
Before using this skill, ensure:
- Python 3.10+ is installed
- An Algorand address to receive payments (the
payToaddress) - A facilitator URL -- use
https://x402.org/facilitatoror run your own - Understanding of FastAPI or Flask basics
Core Workflow: Middleware-Based Payment Protection
The middleware intercepts requests to protected routes, checks for payment headers, verifies payments through the facilitator, and settles on success.
Client Request
|
v
x402 Middleware (checks route config)
|
+-- Not protected -> Pass through to handler
|
+-- Protected, no payment -> Return 402 with PaymentRequirements
|
+-- Protected, has payment -> Verify via Facilitator
|
+-- Invalid -> Return 402
|
+-- Valid -> Call handler, then settle paymentHow to Proceed
Step 1: Install Dependencies
For FastAPI (async):
pip install "x402-avm[fastapi,avm]"For Flask (sync):
pip install "x402-avm[flask,avm]"Step 2: Choose Your Framework Pattern
FastAPI uses async components:
x402ResourceServer(async)HTTPFacilitatorClient(async)PaymentMiddlewareASGIorpayment_middleware
Flask uses sync components:
x402ResourceServerSync(sync)HTTPFacilitatorClientSync(sync)PaymentMiddlewareorpayment_middleware
Step 3: Set Up the Resource Server
Create a facilitator client, resource server, and register the AVM scheme:
FastAPI:
from x402.server import x402ResourceServer
from x402.http import HTTPFacilitatorClient, FacilitatorConfig
from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2
from x402.mechanisms.avm.exact import ExactAvmServerScheme
facilitator = HTTPFacilitatorClient(FacilitatorConfig(url="https://x402.org/facilitator"))
server = x402ResourceServer(facilitator)
server.register(ALGORAND_TESTNET_CAIP2, ExactAvmServerScheme())Flask:
from x402.server import x402ResourceServerSync
from x402.http import HTTPFacilitatorClientSync, FacilitatorConfig
from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2
from x402.mechanisms.avm.exact import ExactAvmServerScheme
facilitator = HTTPFacilitatorClientSync(FacilitatorConfig(url="https://x402.org/facilitator"))
server = x402ResourceServerSync(facilitator)
server.register(ALGORAND_TESTNET_CAIP2, ExactAvmServerScheme())Step 4: Define Route Configurations
Routes map HTTP method + path patterns to payment requirements:
from x402.http import PaymentOption
from x402.http.types import RouteConfig
from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2
routes = {
"GET /api/weather": RouteConfig(
accepts=PaymentOption(
scheme="exact",
network=ALGORAND_TESTNET_CAIP2,
pay_to="YOUR_ALGORAND_ADDRESS",
price="$0.01",
),
),
}Step 5: Apply Middleware
FastAPI -- Option A (ASGI class, recommended):
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)FastAPI -- Option B (function-based):
from x402.http.middleware.fastapi import payment_middleware
x402_mw = payment_middleware(routes=routes, server=server)
@app.middleware("http")
async def x402_middleware(request, call_next):
return await x402_mw(request, call_next)Flask:
from x402.http.middleware.flask import PaymentMiddleware
PaymentMiddleware(app, routes, server)Step 6: Define Route Handlers
Routes listed in the configuration require payment. Unlisted routes pass through freely.
FastAPI:
@app.get("/api/weather")
async def get_weather():
return {"temperature": 72, "unit": "F"}Flask:
@app.route("/api/weather")
def get_weather():
return {"temperature": 72, "unit": "F"}Important Rules / Guidelines
- Match async/sync variants -- FastAPI uses
x402ResourceServer+HTTPFacilitatorClient, Flask usesx402ResourceServerSync+HTTPFacilitatorClientSync - Route format -- Keys must be
"METHOD /path"(e.g.,"GET /api/weather","POST /api/generate/*") - Wildcard paths -- Use
/*suffix to match all sub-paths (e.g.,"GET /api/premium/*") - Unlisted routes pass through -- Only routes in the config require payment
- Register scheme before middleware -- Call
server.register(...)before adding middleware - Price format -- Use
"$0.01"for auto-conversion orAssetAmount(amount="10000", asset="10458941")for explicit control - CAIP-2 network IDs -- Use the
ALGORAND_TESTNET_CAIP2/ALGORAND_MAINNET_CAIP2constants fromx402.mechanisms.avmrather than hardcoding. Testnet is"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="(as of x402-avm 2.0.2; note the TypeScript @x402/avm package ≥2.20.0 uses the 32-char formalgorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe— a TS server/client and a Python facilitator (or vice-versa) will not match until x402-avm adopts the same form)
Pricing Options
Simple String Price
from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2
PaymentOption(
scheme="exact",
network=ALGORAND_TESTNET_CAIP2,
pay_to="YOUR_ADDRESS",
price="$0.01", # Auto-converts to 10000 microUSDC
)Explicit AssetAmount
from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2
from x402.schemas import AssetAmount
PaymentOption(
scheme="exact",
network=ALGORAND_TESTNET_CAIP2,
pay_to="YOUR_ADDRESS",
price=AssetAmount(
amount="50000", # 50000 microUSDC = $0.05
asset="10458941", # USDC ASA ID on testnet
extra={"name": "USDC", "decimals": 6},
),
)Multi-Network (AVM + EVM + SVM)
from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2
routes = {
"GET /api/data/*": RouteConfig(
accepts=[
PaymentOption(scheme="exact", pay_to=AVM_ADDRESS, price="$0.01",
network=ALGORAND_TESTNET_CAIP2),
PaymentOption(scheme="exact", pay_to=EVM_ADDRESS, price="$0.01",
network="eip155:84532"),
PaymentOption(scheme="exact", pay_to=SVM_ADDRESS, price="$0.01",
network="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"),
],
),
}Common Errors / Troubleshooting
| Error | Cause | Solution |
|---|---|---|
TypeError: async errors in Flask |
Using async variants with Flask | Use x402ResourceServerSync and HTTPFacilitatorClientSync |
| 402 returned to all requests | Middleware applied but facilitator unreachable | Check FACILITATOR_URL and network connectivity |
| Route not protected | Path pattern mismatch | Verify route key format matches: "GET /exact/path" or "GET /prefix/*" |
| Settlement fails | Facilitator cannot reach Algorand network | Check facilitator logs and algod endpoint |
ImportError on middleware |
Missing extras | pip install "x402-avm[fastapi,avm]" or "x402-avm[flask,avm]" |
References / Further Reading
- create-python-x402-server-reference.md - Detailed API reference for middleware
- create-python-x402-server-examples.md - Complete code examples for FastAPI and Flask
- x402-avm Examples Repository
- x402 Algorand Documentation