Back to Python tutorials
Intermediate19 min read

FastAPI REST APIs

Build high-performance APIs with FastAPI, Pydantic models, dependency injection, and OpenAPI docs.

FastAPI Application Structure

FastAPI builds on Starlette and Pydantic. Create app = FastAPI(), declare path operation functions with decorators @app.get, return Pydantic models or dicts.

Automatic OpenAPI docs appear at /docs and /redoc. Type hints drive validation and serialization.

Organize routers with APIRouter and include_router for modular apps mirroring domain boundaries.

  • Use lifespan context for startup/shutdown hooks
  • Set root_path when behind reverse proxies
  • Enable ORJSONResponse for large JSON payloads when needed
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float

@app.post("/items")
def create_item(item: Item):
    return item

Validation and Dependencies

Pydantic validates request bodies, query params, and path params. Field(...) adds constraints like min_length and gt.

Depends injects shared logic: database sessions, current user, pagination params. Dependencies nest and compose cleanly.

Return Response with status_code or raise HTTPException for error responses with consistent JSON bodies.

  • Reuse dependency types across routes for auth
  • Validate file uploads with UploadFile and size limits
  • Version public APIs with /v1 prefix routers
from fastapi import Depends, HTTPException

def get_current_user(token: str = Depends(oauth2_scheme)):
    user = decode(token)
    if not user:
        raise HTTPException(401, "Invalid token")
    return user

Async, Testing, and Deployment

Declare path functions async def when awaiting databases or HTTP clients. Sync def runs in threadpool—fine for CPU-light CRUD.

TestClient from starlette exercises routes in-process without network. Override dependencies in tests for fake auth and databases.

Deploy with uvicorn workers behind gunicorn or container platforms. Configure CORS middleware for browser clients explicitly.

  • Use async database drivers with async routes consistently
  • Generate clients from OpenAPI for frontend teams
  • Monitor latency and 5xx rates per endpoint in production
from fastapi.testclient import TestClient

client = TestClient(app)

def test_health():
    assert client.get("/health").status_code == 200

Get In Touch


Ready to discuss your next project? Drop me a message.