---
title: FastAPI Integration
description: Start accepting x402 payments in your FastAPI server in 2 minutes
keywords: [x402, FastAPI, Python, blockchain payments, API monetization]
last_updated: 2026-08-20
---

# Getting Started with FastAPI

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

:::info Example Code
You can find the full code for this example on [GitHub](https://github.com/BlockEdenHQ/x402-examples/tree/main/python/servers/fastapi).
:::

## 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
```

:::tip 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
```

<div style={{padding: '1rem', background: '#d1fae5', borderRadius: '0.5rem', color: '#065f46', marginTop: '1rem', marginBottom: '1rem'}}>
  <ion-icon name="checkmark-circle" style={{fontSize: '1.5rem', verticalAlign: 'middle', marginRight: '0.5rem'}}></ion-icon>
  <strong>Your FastAPI server is now accepting x402 payments!</strong>
</div>

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.

:::note 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:

- <ion-icon name="flash"></ion-icon> **High performance**: One of the fastest Python frameworks available
- <ion-icon name="code-slash"></ion-icon> **Type safety**: Built-in type hints and validation
- <ion-icon name="document-text"></ion-icon> **Auto documentation**: Interactive API docs (Swagger/ReDoc) out of the box
- <ion-icon name="construct"></ion-icon> **Modern Python**: Uses async/await for concurrent requests
- **Easy to learn**: Intuitive API similar to Flask

## Next Steps

- <ion-icon name="arrow-forward-circle"></ion-icon> [Implement a crypto paywall](./implement-a-crypto-paywall-with-x402.md)
- <ion-icon name="arrow-forward-circle"></ion-icon> [View the merchant introduction](./x402-for-merchants.md)
- <ion-icon name="arrow-forward-circle"></ion-icon> [Read the Quick Start Guide](./quickstart.md)

## Need Help?

<div style={{padding: '1.5rem', background: '#f3f4f6', borderRadius: '0.5rem', marginTop: '2rem'}}>
  <div style={{display: 'flex', alignItems: 'flex-start', marginBottom: '1rem'}}>
    <ion-icon name="people" style={{fontSize: '1.5rem', marginRight: '0.5rem', color: '#374151'}}></ion-icon>
    <div>
      <h4 style={{margin: 0, fontSize: '1.125rem', fontWeight: 600, color: '#111827'}}>Join Our Community</h4>
      <p style={{margin: '0.25rem 0 0 0', color: '#6b7280'}}>Have questions or want to connect with other developers?</p>
    </div>
  </div>
  <a
    href="https://discord.gg/4Yfvs2HWey"
    target="_blank"
    rel="noopener noreferrer"
    style={{
      display: 'inline-flex',
      alignItems: 'center',
      gap: '0.5rem',
      padding: '0.625rem 1.25rem',
      background: '#5865F2',
      color: 'white',
      borderRadius: '0.5rem',
      textDecoration: 'none',
      fontWeight: 600,
      fontSize: '0.9375rem',
      transition: 'background 0.2s',
      border: 'none'
    }}
    onMouseOver={(e) => e.currentTarget.style.background = '#4752C4'}
    onMouseOut={(e) => e.currentTarget.style.background = '#5865F2'}
  >
    <ion-icon name="logo-discord" style={{fontSize: '1.25rem'}}></ion-icon>
    <span>Join Discord</span>
  </a>
</div>
