Skip to main content

FastAPI Integration

Start accepting x402 payments in your FastAPI server in 2 minutes

Share
Last updated on August 20, 2026

Start accepting x402 payments in your FastAPI server in 2 minutes.

Example Code

You can find the full code for this example on GitHub.

Step 1: Install Dependencies

Install the required packages for your FastAPI server:

bash
pip install x402 fastapi uvicorn python-dotenv

Step 2: Set Your Environment Variables

Create a .env file in your project root:

bash
echo "ADDRESS=0x...\nNETWORK=sui" > .env

Your .env file should look like this:

env
ADDRESS=0x... # wallet public address you want to receive payments to
NETWORK=sui # recommended for fastest settlement
# Optional: Configure facilitator URL if using custom facilitator
# FACILITATOR_URL=https://x402.bex.co
Network Options

bex.co supports multiple networks:

  • sui (recommended for fastest settlement)
  • ethereum
  • base
  • polygon
  • avalanche

Step 3: Create a New FastAPI App

Create a main.py file with the following code:

python
import os
from typing import Any, Dict
 
from dotenv import load_dotenv
from fastapi import FastAPI
from x402.fastapi.middleware import require_payment
from x402.types import TokenAmount, TokenAsset, EIP712Domain
 
# Load environment variables
load_dotenv()
 
# Get configuration from environment
ADDRESS = os.getenv("ADDRESS")
NETWORK = os.getenv("NETWORK", "sui")
 
if not ADDRESS:
    raise ValueError("Missing required environment variables")
 
app = FastAPI(
    title="x402 Payment Server",
    description="FastAPI server with x402 payment integration",
)
 
# Apply payment middleware to weather route
app.middleware("http")(
    require_payment(
        path="/weather",
        price="$0.001",
        pay_to_address=ADDRESS,
        network=NETWORK,
    )
)
 
# Apply payment middleware to premium routes
app.middleware("http")(
    require_payment(
        path="/premium/*",
        price=TokenAmount(
            amount="10000",
            asset=TokenAsset(
                address="0x...",  # USDC contract address for your network
                decimals=6,
                eip712=EIP712Domain(name="USDC", version="2"),
            ),
        ),
        pay_to_address=ADDRESS,
        network=NETWORK,
    )
)
 
 
@app.get("/")
async def root() -> Dict[str, str]:
    return {
        "message": "x402 Payment Server",
        "status": "running",
    }
 
 
@app.get("/weather")
async def get_weather() -> Dict[str, Any]:
    """Get weather data - requires payment"""
    return {
        "report": {
            "weather": "sunny",
            "temperature": 70,
            "location": "San Francisco",
        }
    }
 
 
@app.get("/premium/content")
async def get_premium_content() -> Dict[str, Any]:
    """Get premium content - requires payment"""
    return {
        "content": "This is premium content",
        "type": "article",
        "timestamp": "2025-01-01T00:00:00Z",
    }
 
 
@app.get("/premium/analytics")
async def get_premium_analytics() -> Dict[str, Any]:
    """Get premium analytics - requires payment"""
    return {
        "analytics": {
            "users": 1000,
            "revenue": 50000,
            "growth": 25.5,
        }
    }
 
 
if __name__ == "__main__":
    import uvicorn
 
    uvicorn.run(
        app,
        host="0.0.0.0",
        port=4021,
        log_level="info",
    )

Step 4: Run the Server

Start your FastAPI server:

bash
uvicorn main:app --reload

Or run directly with Python:

bash
python main.py
Your FastAPI server is now accepting x402 payments!

Your server will be available at http://localhost:4021. You can view the interactive API docs at http://localhost:4021/docs.

Step 5: Test the Server

You can test payments against your server locally using HTTP clients like curl, Postman, or by building a Python client application.

Coming Soon

Client implementation guides for httpx and requests libraries will be available soon.

Manual Testing with curl

bash
# This will return a 402 Payment Required response
curl http://localhost:4021/weather
 
# The response will include payment details in headers

Payment Configuration Options

The require_payment middleware accepts flexible payment configurations:

Simple Dollar Amount

python
app.middleware("http")(
    require_payment(
        path="/weather",
        price="$0.001",
        pay_to_address=ADDRESS,
        network="sui",
    )
)

Token Amount with Specific Asset

python
from x402.types import TokenAmount, TokenAsset, EIP712Domain
 
app.middleware("http")(
    require_payment(
        path="/premium/data",
        price=TokenAmount(
            amount="10000",
            asset=TokenAsset(
                address="0x...",  # Token contract address
                decimals=6,
                eip712=EIP712Domain(name="USDC", version="2"),
            ),
        ),
        pay_to_address=ADDRESS,
        network="sui",
    )
)

Wildcard Routes

Protect all routes under a path:

python
app.middleware("http")(
    require_payment(
        path="/premium/*",  # Matches /premium/anything
        price="$0.05",
        pay_to_address=ADDRESS,
        network="sui",
    )
)

Advanced Features

Custom Payment Verification Callback

Add custom logic when payments are verified:

python
# Note: Custom payment verification callbacks may vary based on
# the x402 library version. Check the official documentation for
# the exact callback mechanism supported by your version.
 
app.middleware("http")(
    require_payment(
        path="/weather",
        price="$0.001",
        pay_to_address=ADDRESS,
        network="sui",
    )
)
 
# You can add custom logic in your route handler after payment verification
@app.get("/weather")
async def get_weather():
    # Payment has been verified if this handler is reached
    # Add your custom logic here
    return {"report": {"weather": "sunny", "temperature": 70}}

Error Handling

Add custom error handling:

python
from fastapi import Request, status
from fastapi.responses import JSONResponse
from x402.exceptions import X402PaymentError
 
@app.exception_handler(X402PaymentError)
async def payment_error_handler(request: Request, exc: X402PaymentError):
    return JSONResponse(
        status_code=status.HTTP_402_PAYMENT_REQUIRED,
        content={
            "error": "Payment required",
            "details": str(exc),
            "path": str(request.url),
        },
    )

CORS Configuration

Enable CORS for cross-origin requests:

python
from fastapi.middleware.cors import CORSMiddleware
 
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "https://yourdomain.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Request Context Access

Access payment information in your route handlers:

python
from fastapi import Request
 
@app.get("/weather")
async def get_weather(request: Request) -> Dict[str, Any]:
    # Access payment details from request state
    payment_info = getattr(request.state, "x402_payment", None)
 
    return {
        "report": {"weather": "sunny", "temperature": 70},
        "payment": {
            "tx_hash": payment_info.tx_hash if payment_info else None,
        }
    }

Production Deployment

Before deploying to production:

  1. Switch to production network (e.g., sui instead of sui-testnet)
  2. Use environment variables for all sensitive data
  3. Enable HTTPS (use a reverse proxy like nginx)
  4. Set up proper logging and monitoring
  5. Configure CORS for your production domains
  6. Use a production ASGI server (Gunicorn + Uvicorn)

Production Example

python
import os
import logging
from typing import Any, Dict
 
from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from x402.fastapi.middleware import require_payment
 
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
 
load_dotenv()
 
app = FastAPI(title="Production x402 Server")
 
# CORS configuration
app.add_middleware(
    CORSMiddleware,
    allow_origins=os.getenv("ALLOWED_ORIGINS", "").split(","),
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
 
# Payment middleware
app.middleware("http")(
    require_payment(
        path="/api/data",
        price="$0.01",
        pay_to_address=os.getenv("ADDRESS"),
        network="sui",  # Production Sui network
    )
)
 
@app.get("/api/data")
async def get_data() -> Dict[str, Any]:
    logger.info("Delivering protected data")
    return {"data": "Protected content"}
 
if __name__ == "__main__":
    import uvicorn
 
    uvicorn.run(
        app,
        host="0.0.0.0",
        port=int(os.getenv("PORT", "4021")),
        workers=4,  # Multiple workers for production
        log_level="info",
    )

Deploy with Gunicorn

For production, use Gunicorn with Uvicorn workers:

bash
pip install gunicorn
 
gunicorn main:app \
  --workers 4 \
  --worker-class uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:4021 \
  --timeout 120

Troubleshooting

Common Issues

Payment verification fails

  • Verify your BEX_API_KEY is correct
  • Check that the wallet address format matches the network
  • Ensure the facilitator URL is accessible

CORS errors

  • Add CORS middleware before payment middleware
  • Configure allowed origins properly

Network mismatch

  • Ensure client and server use the same network
  • Check that the token address is valid for the network

Module import errors

  • Ensure you installed x402 package
  • Verify your Python version is 3.8 or higher

Port already in use

  • Change the port in uvicorn.run() configuration
  • Kill any existing processes: lsof -ti:4021 | xargs kill

Why Choose FastAPI?

FastAPI is an excellent choice for x402 payment servers:

  • High performance: One of the fastest Python frameworks available
  • Type safety: Built-in type hints and validation
  • Auto documentation: Interactive API docs (Swagger/ReDoc) out of the box
  • Modern Python: Uses async/await for concurrent requests
  • Easy to learn: Intuitive API similar to Flask

Next Steps

Need Help?

Join Our Community

Have questions or want to connect with other developers?

Join Discord

One API key for 30+ chains

bex router is a single multi-chain gateway — one key, one bill, metered in compute units instead of an account per network.

Explore bex router