> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fd.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# FastAPI Integration

> Protect FastAPI endpoints with blockchain micropayments

<Info>
  **Coming soon.** The `prism-fastapi` package is not yet published to PyPI. This page describes the planned API.
</Info>

## Overview

The **prism-fastapi** package provides async middleware for FastAPI applications, leveraging Python's modern async/await syntax for high-performance payment validation.

<CardGroup cols={3}>
  <Card title="Async/Await" icon="bolt">
    Full async support with Python asyncio
  </Card>

  <Card title="Dependency Injection" icon="puzzle-piece">
    Works with FastAPI's Depends system
  </Card>

  <Card title="Type Hints" icon="code">
    Full type hint support with Pydantic
  </Card>
</CardGroup>

***

## Installation

<Tabs>
  <Tab title="pip">
    ```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
    pip install prism-fastapi fastapi uvicorn
    ```
  </Tab>

  {" "}

  <Tab title="poetry">`bash poetry add prism-fastapi fastapi uvicorn `</Tab>

  <Tab title="requirements.txt">
    ```
    prism-fastapi>=1.0.0
    fastapi>=0.100.0
    uvicorn[standard]>=0.23.0
    ```
  </Tab>
</Tabs>

***

<Note>
  The canonical SDK config is `identify_token` (`PRISM_IDENTIFY_TOKEN` env var) — formerly `api_key` / `PRISM_API_KEY`. SDKs accept the legacy names as fallback during the migration window; new code should use the canonical names.
</Note>

## Quick Start

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
from fastapi import FastAPI, Request
from prism_fastapi import prism_payment_middleware, PrismMiddlewareConfig

app = FastAPI()

# Configure Prism middleware
prism_config = PrismMiddlewareConfig(
    identify_token="dev-key-123",
    base_url="https://prism-gw.fd.xyz",
    routes={
        "/api/premium": {
            "price": 0.01,  # $0.01 USD
            "description": "Premium API"
        }
    }
)

# Add middleware
app.middleware("http")(prism_payment_middleware(prism_config))

# Protected endpoint
@app.get("/api/premium")
async def premium_endpoint(request: Request):
    payer = request.state.prism_payer  # Wallet address

    return {
        "message": "Premium content",
        "payer": payer
    }

# Run: uvicorn main:app --reload
```

***

## Configuration

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
from dataclasses import dataclass
from typing import Dict, Union

@dataclass
class RoutePaymentConfig:
    price: Union[float, str]  # USD price
    description: str
    mime_type: str = "application/json"

@dataclass
class PrismMiddlewareConfig:
    identify_token: str
    base_url: str = "https://prism-gw.fd.xyz"
    debug: bool = False
    routes: Dict[str, RoutePaymentConfig] = None
```

***

## Route Protection

### Multiple Routes

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
from prism_fastapi import PrismMiddlewareConfig, RoutePaymentConfig

config = PrismMiddlewareConfig(
    identify_token="your-project-identify-token",
    routes={
        "/api/premium": RoutePaymentConfig(
            price=0.01,
            description="Premium API"
        ),
        "/api/weather": RoutePaymentConfig(
            price=0.001,
            description="Weather data"
        ),
        "/api/data/*": RoutePaymentConfig(
            price=0.005,
            description="Data API (wildcard)"
        )
    }
)

app.middleware("http")(prism_payment_middleware(config))
```

***

## Accessing Payment Info

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
from fastapi import FastAPI, Request

@app.get("/api/premium")
async def premium_endpoint(request: Request):
    # Access payer address
    payer = request.state.prism_payer
    # '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'

    # Access payment object
    payment = getattr(request.state, 'prism_payment', None)

    if payment:
        return {
            "message": "Premium data",
            "payer": payer,
            "network": payment.get("network"),
            "asset": payment.get("asset")
        }

    return {"message": "No payment info"}
```

***

## Settlement Validation

FastAPI middleware intercepts responses to validate settlement:

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# Internal implementation (automatic!)
@app.middleware("http")
async def prism_payment_middleware(request: Request, call_next):
    # ... payment validation ...

    # Call endpoint
    response = await call_next(request)

    # Validate settlement
    settlement_result = await core.settlement_callback(...)

    if not settlement_result or not settlement_result.get("success"):
        # ❌ Settlement failed
        return JSONResponse(
            status_code=402,
            content={
                "error": "Payment settlement failed",
                "details": settlement_result.get("errorReason")
            }
        )

    # ✅ Settlement succeeded
    response.headers["X-PAYMENT-RESPONSE"] = settlement_result["transaction"]
    return response
```

***

## Dependency Injection

### Payer Dependency

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
from fastapi import Depends, Request

def get_payer(request: Request) -> str:
    return getattr(request.state, 'prism_payer', None)

@app.get("/api/premium")
async def premium_endpoint(payer: str = Depends(get_payer)):
    return {
        "message": "Premium content",
        "payer": payer
    }
```

***

## Testing

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import pytest
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_payment_required_without_header():
    response = client.get("/api/premium")

    assert response.status_code == 402
    assert response.json()["paymentRequired"] is True

def test_access_granted_with_valid_payment():
    payment = {
        "scheme": "eip3009",
        "signature": "0x" + "0" * 130
    }

    response = client.get(
        "/api/premium",
        headers={"X-PAYMENT": str(payment)}
    )

    assert response.status_code == 200
    assert "payer" in response.json()

@pytest.mark.asyncio
async def test_async_endpoint():
    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.get("/api/premium")
        assert response.status_code == 402
```

***

## Production Deployment

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# main.py
from fastapi import FastAPI
from prism_fastapi import prism_payment_middleware, PrismMiddlewareConfig
import os

app = FastAPI(
    title="Prism Payment API",
    docs_url="/docs" if os.getenv("ENV") != "production" else None
)

# Configure Prism
config = PrismMiddlewareConfig(
    identify_token=os.environ['PRISM_IDENTIFY_TOKEN'],
    base_url=os.getenv("PRISM_BASE_URL", "https://prism-gw.fd.xyz"),
    debug=os.getenv("DEBUG", "false").lower() == "true",
    routes={
        "/api/premium": {
            "price": 0.01,
            "description": "Premium API"
        }
    }
)

app.middleware("http")(prism_payment_middleware(config))

# CORS (if needed)
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=os.getenv("ALLOWED_ORIGINS", "*").split(","),
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=int(os.getenv("PORT", 8000)),
        reload=os.getenv("ENV") != "production"
    )
```

### Docker Deployment

```dockerfile theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```

***

## Type Hints

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
from typing import Optional, Dict, Any
from fastapi import Request

@app.get("/api/premium")
async def premium_endpoint(request: Request) -> Dict[str, Any]:
    payer: Optional[str] = getattr(request.state, 'prism_payer', None)
    payment: Optional[Dict[str, Any]] = getattr(request.state, 'prism_payment', None)

    return {
        "message": "Premium content",
        "payer": payer,
        "network": payment.get("network") if payment else None
    }
```
