Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

FastAPI User Guide

Generated May 2026 from tiangolo/fastapi at 9653034

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Quick Start

FastAPI is a modern, high-performance Python web framework for building APIs with standard Python type hints. It generates OpenAPI 3.1.0 schemas automatically, provides interactive API documentation out of the box, and achieves performance on par with Node.js and Go thanks to its foundation on Starlette (ASGI) and Pydantic (data validation).

Key Features:

  • Automatic OpenAPI 3.1.0 schema generation from your code
  • Interactive API docs: Swagger UI (/docs) and ReDoc (/redoc) included by default
  • Full data validation via Pydantic models and Python type hints
  • Dependency injection system for reusable logic across endpoints
  • Built-in OAuth2, JWT, API key, and HTTP auth security schemes
  • WebSocket support with the same decorator pattern as HTTP routes
  • Server-Sent Events (SSE) via EventSourceResponse
  • Background task execution without blocking responses
  • File upload handling with UploadFile and File
  • Sub-application mounting and modular routing via APIRouter
  • Async-first (async def) with full sync (def) support
  • Automatic request/response serialization with JSON, ORJSON, UJSON

Prerequisites: Python 3.8+

Minimal setup (under 2 minutes):

pip install "fastapi[standard]"

Create main.py:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

Run the development server:

fastapi dev main.py
INFO     Using path main.py
INFO     Resolved absolute path /home/user/app/main.py
INFO     Searching for package file structure from directories with __init__.py files
INFO     Importing from /home/user/app

 ╭─ FastAPI CLI - Development mode ─╮
 │                                   │
 │  Serving at: http://127.0.0.1:8000│
 │                                   │
 │  API docs: http://127.0.0.1:8000/docs │
 │                                   │
 │  Running in development mode, for │
 │  production use: fastapi run       │
 │                                   │
 ╰───────────────────────────────────╯

Open http://127.0.0.1:8000/docs to see interactive documentation for your API.

Tip

The fastapi dev command enables auto-reload by default. Every time you save a file, the server restarts automatically, making development fast and iterative.

2. Installation

Install Options

Method Command What You Get
Standard (recommended) pip install "fastapi[standard]" FastAPI + Uvicorn + fastapi CLI + email validation + multipart
Minimal pip install fastapi FastAPI core only; bring your own ASGI server
With ORJSON pip install "fastapi[standard]" orjson Faster JSON serialization via ORJSONResponse
With UJSON pip install "fastapi[standard]" ujson Alternative JSON serialization via UJSONResponse

Dependency Tree

FastAPI's core dependencies (installed automatically):

Package Purpose
starlette ASGI framework (routing, middleware, requests, responses)
pydantic Data validation and serialization via type hints
typing_extensions Backported type hint features

The [standard] extra adds:

Package Purpose
uvicorn[standard] ASGI server for development and production
fastapi-cli Provides fastapi dev and fastapi run CLI commands
httpx Async HTTP client (used with TestClient)
jinja2 Template rendering
python-multipart File upload and form data parsing
email-validator Email string validation for Pydantic models

Important

If you install fastapi without the [standard] extra, the fastapi CLI command is not available. You will need to run your app directly with uvicorn main:app --reload instead of fastapi dev main.py.

Verifying the Installation

python -c "import fastapi; print(fastapi.__version__)"
0.135.3
fastapi --version

If the CLI is not installed, you will see:

RuntimeError: To use the fastapi command, please install "fastapi[standard]"

Running Your Application

Environment Command Notes
Development fastapi dev main.py Auto-reload enabled, binds to 127.0.0.1
Development (manual) uvicorn main:app --reload Equivalent to fastapi dev
Production fastapi run main.py No auto-reload, binds to 0.0.0.0
Production (manual) uvicorn main:app --host 0.0.0.0 --port 8000 Full control over server settings
Production (Gunicorn) gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker Multi-worker process manager

3. Application Setup

FastAPI applications are configured through the FastAPI() constructor. There are no external configuration files or config keys; all settings are passed as Python arguments.

FastAPI Constructor Parameters

Parameter Type Default Purpose
title str "FastAPI" API title shown in docs
summary str | None None Short API summary for docs
description str "" Detailed API description (supports Markdown)
version str "0.1.0" API version shown in docs and OpenAPI schema
debug bool False Enable debug mode (detailed error responses)
openapi_url str | None "/openapi.json" OpenAPI schema endpoint; set to None to disable
docs_url str | None "/docs" Swagger UI endpoint; set to None to disable
redoc_url str | None "/redoc" ReDoc endpoint; set to None to disable
default_response_class type[Response] JSONResponse Default response class for all endpoints
redirect_slashes bool True Auto-redirect /items to /items/ (or vice versa)
root_path str "" ASGI root path for reverse proxies
root_path_in_servers bool True Include root_path in OpenAPI servers list
lifespan Lifespan | None None Async context manager for startup/shutdown
dependencies Sequence[Depends] | None None Global dependencies applied to all routes
middleware Sequence[Middleware] | None None Middleware stack
exception_handlers dict | None None Custom exception handlers
responses dict | None None Additional OpenAPI responses for all endpoints
callbacks list | None None OpenAPI callbacks
webhooks APIRouter | None None OpenAPI webhooks
terms_of_service str | None None URL to terms of service
contact dict | None None Contact info for the API
license_info dict | None None License info for the API
openapi_tags list[dict] | None None Tag metadata for OpenAPI docs
servers list[dict] | None None Server list for OpenAPI schema
swagger_ui_parameters dict | None None Custom Swagger UI config parameters
swagger_ui_oauth2_redirect_url str | None "/docs/oauth2-redirect" OAuth2 redirect URL for Swagger UI
swagger_ui_init_oauth dict | None None OAuth2 init config for Swagger UI
generate_unique_id_function Callable auto Function to generate operation IDs
separate_input_output_schemas bool True Generate separate schemas for input/output models
strict_content_type bool True Enforce Content-Type header validation (CSRF protection)
include_in_schema bool True Include this app in the OpenAPI schema
deprecated bool | None None Mark all routes as deprecated in OpenAPI
openapi_external_docs dict | None None External documentation link for OpenAPI

Practical Setup Examples

Production-ready configuration:

from fastapi import FastAPI

app = FastAPI(
    title="My Service API",
    version="2.1.0",
    description="Service for managing inventory and orders.",
    docs_url="/api/docs",
    redoc_url="/api/redoc",
    openapi_url="/api/openapi.json",
    root_path="/v2",
)

Disable all documentation endpoints (headless API):

app = FastAPI(
    openapi_url=None,  # disables /openapi.json, /docs, and /redoc
)

Note

Setting openapi_url=None disables the OpenAPI schema entirely, which also disables both Swagger UI and ReDoc since they depend on the schema. To disable only one docs interface, set docs_url=None or redoc_url=None individually.

Lifespan events (startup/shutdown):

from contextlib import asynccontextmanager
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup: initialize resources
    db_pool = await create_db_pool()
    app.state.db = db_pool
    yield
    # Shutdown: clean up resources
    await db_pool.close()

app = FastAPI(lifespan=lifespan)

Warning

The on_startup and on_shutdown event handlers are deprecated. Use the lifespan context manager instead. The lifespan approach properly handles resource sharing between startup and shutdown, and ensures cleanup runs even if startup fails partway through.

4. Core Usage

4.1 Defining Path Operations

Every endpoint in FastAPI is a "path operation" consisting of an HTTP method decorator and a function:

from fastapi import FastAPI

app = FastAPI()

@app.get("/items")
async def list_items():
    return [{"id": 1, "name": "Widget"}]

@app.post("/items", status_code=201)
async def create_item(name: str):
    return {"id": 2, "name": name}

@app.put("/items/{item_id}")
async def update_item(item_id: int, name: str):
    return {"id": item_id, "name": name}

@app.patch("/items/{item_id}")
async def partial_update(item_id: int, name: str | None = None):
    return {"id": item_id, "name": name}

@app.delete("/items/{item_id}", status_code=204)
async def delete_item(item_id: int):
    return None

All available HTTP method decorators:

Decorator HTTP Method Typical Use
@app.get() GET Retrieve resources
@app.post() POST Create resources
@app.put() PUT Full resource replacement
@app.patch() PATCH Partial updates
@app.delete() DELETE Remove resources
@app.options() OPTIONS CORS preflight, capability discovery
@app.head() HEAD Retrieve headers only (no body)
@app.trace() TRACE Diagnostic echo
@app.api_route() Any/multiple Register one function for multiple methods

Using api_route for multiple methods:

@app.api_route("/health", methods=["GET", "HEAD"])
async def health():
    return {"status": "ok"}

4.2 Path Parameters

Path parameters are extracted from the URL path and automatically converted to the declared Python type:

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    return {"user_id": user_id}

Requesting /users/42 returns {"user_id": 42}. Requesting /users/abc returns a 422 validation error automatically.

Path parameter validation with Path():

from fastapi import Path

@app.get("/items/{item_id}")
async def get_item(
    item_id: int = Path(title="Item ID", ge=1, le=10000)
):
    return {"item_id": item_id}

Predefined values with Enum:

from enum import Enum

class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"

@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    return {"model": model_name.value}

File-path parameters (capturing slashes):

@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"path": file_path}

Requesting /files/home/user/data.csv captures file_path = "home/user/data.csv".

4.3 Query Parameters

Any function parameter that is not a path parameter is automatically treated as a query parameter:

@app.get("/items")
async def list_items(skip: int = 0, limit: int = 10, q: str | None = None):
    return {"skip": skip, "limit": limit, "q": q}

GET /items?skip=20&limit=5&q=widget parses all three parameters with type validation.

Query parameter validation with Query():

from fastapi import Query

@app.get("/search")
async def search(
    q: str = Query(min_length=3, max_length=50, pattern="^[a-zA-Z0-9 ]+$"),
    page: int = Query(default=1, ge=1),
    size: int = Query(default=20, le=100),
):
    return {"q": q, "page": page, "size": size}

Receiving a list of query parameters:

@app.get("/items")
async def filter_items(
    tags: list[str] = Query(default=[])
):
    return {"tags": tags}

GET /items?tags=python&tags=fastapi produces tags = ["python", "fastapi"].

Required query parameters (no default value):

@app.get("/items")
async def list_items(category: str):  # required, no default
    return {"category": category}

4.4 Request Body with Pydantic Models

Define request and response schemas with Pydantic models. FastAPI validates incoming JSON automatically:

from pydantic import BaseModel, Field

class ItemCreate(BaseModel):
    name: str = Field(min_length=1, max_length=100)
    price: float = Field(gt=0)
    description: str | None = None
    tags: list[str] = []

class ItemResponse(BaseModel):
    id: int
    name: str
    price: float
    description: str | None
    tags: list[str]

@app.post("/items", response_model=ItemResponse, status_code=201)
async def create_item(item: ItemCreate):
    # item is already validated
    return ItemResponse(id=1, **item.model_dump())

Sending the request:

curl -X POST http://127.0.0.1:8000/items \
  -H "Content-Type: application/json" \
  -d '{"name": "Widget", "price": 9.99, "tags": ["sale"]}'
{"id": 1, "name": "Widget", "price": 9.99, "description": null, "tags": ["sale"]}

Multiple body parameters:

from fastapi import Body

@app.put("/items/{item_id}")
async def update_item(
    item_id: int,
    item: ItemCreate,
    importance: int = Body(gt=0),
):
    return {"item_id": item_id, "item": item, "importance": importance}

Expected body: {"item": {...}, "importance": 5}.

Embedding a single body parameter:

@app.post("/items")
async def create_item(item: ItemCreate = Body(embed=True)):
    return item

Expected body: {"item": {...}} instead of just {...}.

4.5 Headers and Cookies

from fastapi import Header, Cookie

@app.get("/info")
async def info(
    user_agent: str | None = Header(default=None),
    accept_language: str | None = Header(default=None),
    session_id: str | None = Cookie(default=None),
):
    return {
        "user_agent": user_agent,
        "accept_language": accept_language,
        "session_id": session_id,
    }

Note

HTTP headers use hyphens (User-Agent), but Python variables cannot. FastAPI automatically converts underscores to hyphens, so user_agent maps to the User-Agent header. You can disable this with Header(convert_underscores=False).

Duplicate headers (e.g., multiple X-Token values):

@app.get("/items")
async def read_items(x_token: list[str] | None = Header(default=None)):
    return {"X-Token values": x_token}

4.6 Response Handling

Setting response status codes:

from fastapi import status

@app.post("/items", status_code=status.HTTP_201_CREATED)
async def create_item(item: ItemCreate):
    return item

Custom response headers and cookies:

from fastapi import Response

@app.get("/custom")
async def custom_response(response: Response):
    response.headers["X-Custom-Header"] = "custom-value"
    response.set_cookie(key="session", value="abc123", httponly=True)
    return {"message": "done"}

Available response classes:

Class Content-Type Import
JSONResponse application/json fastapi.responses
HTMLResponse text/html fastapi.responses
PlainTextResponse text/plain fastapi.responses
RedirectResponse (redirect) fastapi.responses
StreamingResponse any fastapi.responses
FileResponse auto-detected fastapi.responses
ORJSONResponse application/json fastapi.responses (requires orjson)
UJSONResponse application/json fastapi.responses (requires ujson)

Returning a file:

from fastapi.responses import FileResponse

@app.get("/download")
async def download():
    return FileResponse(
        path="report.pdf",
        filename="report.pdf",
        media_type="application/pdf",
    )

Streaming response:

from fastapi.responses import StreamingResponse

@app.get("/stream")
async def stream():
    async def generate():
        for i in range(100):
            yield f"data: chunk {i}\n\n"
    return StreamingResponse(generate(), media_type="text/event-stream")

Controlling response model output:

@app.get("/items/{item_id}", response_model=ItemResponse)
async def get_item(item_id: int):
    return {"id": item_id, "name": "Widget", "price": 9.99,
            "internal_code": "W001"}  # internal_code is filtered OUT

response_model filters the output to include only fields defined in ItemResponse. Use response_model_exclude_unset=True to omit fields the user did not set.

4.7 Form Data and File Uploads

Receiving form fields:

from fastapi import Form

@app.post("/login")
async def login(username: str = Form(), password: str = Form()):
    return {"username": username}

Important

Form data and file uploads require the python-multipart package. This is included in fastapi[standard] but must be installed separately with the minimal install: pip install python-multipart.

Single file upload:

from fastapi import File, UploadFile

@app.post("/upload")
async def upload(file: UploadFile):
    contents = await file.read()
    return {
        "filename": file.filename,
        "content_type": file.content_type,
        "size": len(contents),
    }

Multiple file uploads:

@app.post("/upload-many")
async def upload_many(files: list[UploadFile]):
    return {"filenames": [f.filename for f in files]}

File with form fields together:

@app.post("/submit")
async def submit(
    title: str = Form(),
    description: str = Form(default=""),
    file: UploadFile = File(),
):
    return {"title": title, "filename": file.filename}

UploadFile attributes and methods:

Attribute/Method Description
filename Original filename from the client
content_type MIME type (e.g., image/png)
size File size in bytes (if available)
headers Raw headers from the multipart section
read(size) Read bytes (async)
write(data) Write bytes (async)
seek(offset) Seek to position (async)
close() Close the file (async)

4.8 Dependency Injection

FastAPI's dependency injection system lets you declare reusable logic that runs before your endpoint:

from fastapi import Depends

async def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/users")
async def list_users(db: Session = Depends(get_db)):
    return db.query(User).all()

Class-based dependencies:

class Pagination:
    def __init__(self, skip: int = 0, limit: int = 100):
        self.skip = skip
        self.limit = limit

@app.get("/items")
async def list_items(pagination: Pagination = Depends()):
    return {"skip": pagination.skip, "limit": pagination.limit}

Nested dependencies:

async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = decode_token(token)
    return user

async def get_active_user(user: User = Depends(get_current_user)):
    if not user.is_active:
        raise HTTPException(status_code=400, detail="Inactive user")
    return user

@app.get("/me")
async def read_me(user: User = Depends(get_active_user)):
    return user

Global dependencies (applied to all routes):

app = FastAPI(dependencies=[Depends(verify_api_key)])

Router-level dependencies:

router = APIRouter(dependencies=[Depends(verify_admin)])

@router.get("/admin/stats")
async def admin_stats():
    return {"users": 1000}

Dependencies with yield (resource cleanup):

Dependencies using yield execute code before AND after the endpoint. The code after yield runs during cleanup, even if the endpoint raises an exception:

async def get_db_session():
    session = create_session()
    try:
        yield session
        session.commit()
    except Exception:
        session.rollback()
        raise
    finally:
        session.close()

4.9 Error Handling

Raising HTTP exceptions:

from fastapi import HTTPException

@app.get("/items/{item_id}")
async def get_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(
            status_code=404,
            detail="Item not found",
            headers={"X-Error": "Item lookup failed"},
        )
    return items_db[item_id]

Custom exception handlers:

from fastapi import Request
from fastapi.responses import JSONResponse

class ItemNotFoundError(Exception):
    def __init__(self, item_id: int):
        self.item_id = item_id

@app.exception_handler(ItemNotFoundError)
async def item_not_found_handler(request: Request, exc: ItemNotFoundError):
    return JSONResponse(
        status_code=404,
        content={"detail": f"Item {exc.item_id} does not exist"},
    )

@app.get("/items/{item_id}")
async def get_item(item_id: int):
    if item_id not in items_db:
        raise ItemNotFoundError(item_id)
    return items_db[item_id]

Overriding default validation error responses:

from fastapi.exceptions import RequestValidationError
from fastapi.responses import PlainTextResponse

@app.exception_handler(RequestValidationError)
async def validation_handler(request: Request, exc: RequestValidationError):
    return PlainTextResponse(str(exc), status_code=422)

Overriding the default HTTPException handler:

from starlette.exceptions import HTTPException as StarletteHTTPException

@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)

4.10 Middleware

Middleware runs code before every request and after every response:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Built-in middleware options:

Middleware Purpose Key Parameters
CORSMiddleware Cross-Origin Resource Sharing allow_origins, allow_methods, allow_headers, allow_credentials
GZipMiddleware Compress responses minimum_size (default 500 bytes)
HTTPSRedirectMiddleware Redirect HTTP to HTTPS (none)
TrustedHostMiddleware Validate Host header allowed_hosts

Custom middleware (function-based):

import time

@app.middleware("http")
async def add_timing_header(request: Request, call_next):
    start = time.perf_counter()
    response = await call_next(request)
    elapsed = time.perf_counter() - start
    response.headers["X-Process-Time"] = str(elapsed)
    return response

4.11 Security and Authentication

FastAPI provides security utilities that integrate with the OpenAPI schema so the interactive docs show authentication controls.

OAuth2 with Password Bearer:

from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")

@app.post("/token")
async def login(form: OAuth2PasswordRequestForm = Depends()):
    user = authenticate(form.username, form.password)
    if not user:
        raise HTTPException(status_code=401, detail="Invalid credentials")
    token = create_access_token(user)
    return {"access_token": token, "token_type": "bearer"}

@app.get("/users/me")
async def read_me(token: str = Depends(oauth2_scheme)):
    user = decode_token(token)
    return user

API Key authentication:

from fastapi.security import APIKeyHeader

api_key_header = APIKeyHeader(name="X-API-Key")

@app.get("/protected")
async def protected(api_key: str = Depends(api_key_header)):
    if api_key != "secret-key":
        raise HTTPException(status_code=403, detail="Invalid API key")
    return {"data": "protected"}

All available security schemes:

Class Location OpenAPI Type
OAuth2PasswordBearer Authorization: Bearer <token> OAuth2
OAuth2AuthorizationCodeBearer Authorization: Bearer <token> OAuth2 (auth code flow)
HTTPBasic Authorization: Basic <b64> HTTP
HTTPBearer Authorization: Bearer <token> HTTP
HTTPDigest Authorization: Digest <params> HTTP
APIKeyQuery Query parameter API Key
APIKeyHeader Request header API Key
APIKeyCookie Cookie API Key
OpenIdConnect OpenID Connect discovery OpenID Connect

Using Security() with scopes:

from fastapi import Security
from fastapi.security import OAuth2PasswordBearer, SecurityScopes

oauth2_scheme = OAuth2PasswordBearer(
    tokenUrl="/token",
    scopes={"items:read": "Read items", "items:write": "Write items"},
)

async def get_current_user(
    security_scopes: SecurityScopes,
    token: str = Depends(oauth2_scheme),
):
    # Verify token has required scopes
    ...

@app.get("/items")
async def read_items(
    user: User = Security(get_current_user, scopes=["items:read"])
):
    return []

4.12 Background Tasks

Execute tasks after returning the response to the client:

from fastapi import BackgroundTasks

def send_notification(email: str, message: str):
    # This runs in the background after response is sent
    send_email(email, message)

@app.post("/orders")
async def create_order(order: Order, background_tasks: BackgroundTasks):
    result = process_order(order)
    background_tasks.add_task(send_notification, order.email, "Order received")
    return result

Multiple background tasks run sequentially in the order they were added. They execute in the same process, so they share memory with the app.

Caution

Background tasks are not suitable for heavy, long-running computations. They run in the same event loop (for async tasks) or thread pool (for sync tasks). For heavy work, use a proper task queue like Celery, Dramatiq, or ARQ.

4.13 WebSockets

from fastapi import WebSocket, WebSocketDisconnect

@app.websocket("/ws")
async def websocket_endpoint(ws: WebSocket):
    await ws.accept()
    try:
        while True:
            data = await ws.receive_text()
            await ws.send_text(f"Echo: {data}")
    except WebSocketDisconnect:
        print("Client disconnected")

WebSocket with path and query parameters:

@app.websocket("/ws/{room_id}")
async def chat(ws: WebSocket, room_id: int, token: str | None = None):
    if not verify_token(token):
        await ws.close(code=1008)
        return
    await ws.accept()
    ...

WebSocket with dependencies:

@app.websocket("/ws")
async def ws_endpoint(ws: WebSocket, db: Session = Depends(get_db)):
    await ws.accept()
    ...

WebSocket methods:

Method Direction Description
accept() Server Accept the connection
close(code) Server Close the connection
send_text(data) Server -> Client Send text message
send_bytes(data) Server -> Client Send binary message
send_json(data) Server -> Client Send JSON message
receive_text() Client -> Server Receive text message
receive_bytes() Client -> Server Receive binary message
receive_json() Client -> Server Receive JSON message

4.14 Server-Sent Events (SSE)

FastAPI supports SSE through EventSourceResponse:

from fastapi.responses import EventSourceResponse, ServerSentEvent
import asyncio

@app.get("/events")
async def events():
    async def event_generator():
        for i in range(10):
            yield ServerSentEvent(
                data=f"Message {i}",
                event="update",
                id=str(i),
            )
            await asyncio.sleep(1)

    return EventSourceResponse(event_generator())

4.15 Modular Applications with APIRouter

Organize large applications into separate files using APIRouter:

# routers/users.py
from fastapi import APIRouter

router = APIRouter(prefix="/users", tags=["users"])

@router.get("/")
async def list_users():
    return []

@router.get("/{user_id}")
async def get_user(user_id: int):
    return {"id": user_id}
# main.py
from fastapi import FastAPI
from routers import users, items

app = FastAPI()
app.include_router(users.router)
app.include_router(items.router, prefix="/api/v1")

APIRouter supports all the same parameters as FastAPI for organizing endpoints:

Parameter Purpose
prefix URL prefix for all routes in this router
tags OpenAPI tags for documentation grouping
dependencies Dependencies applied to all routes in this router
responses Additional OpenAPI responses
default_response_class Default response class for routes

4.16 Sub-Applications

Mount independent FastAPI applications under a path:

main_app = FastAPI()
admin_app = FastAPI()

@admin_app.get("/dashboard")
async def dashboard():
    return {"admin": True}

main_app.mount("/admin", admin_app)

The mounted app at /admin has its own independent OpenAPI docs at /admin/docs.

4.17 Static Files

from fastapi.staticfiles import StaticFiles

app.mount("/static", StaticFiles(directory="static"), name="static")

4.18 Templates

from fastapi import Request
from fastapi.templating import Jinja2Templates

templates = Jinja2Templates(directory="templates")

@app.get("/page", response_class=HTMLResponse)
async def page(request: Request):
    return templates.TemplateResponse(
        request=request,
        name="page.html",
        context={"title": "My Page"},
    )

4.19 Dataclass Support

FastAPI supports Python dataclasses as request and response models:

from dataclasses import dataclass, field

@dataclass
class Item:
    name: str
    price: float
    tags: list[str] = field(default_factory=list)

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

4.20 OpenAPI Customization

Tag metadata for documentation grouping:

tags_metadata = [
    {"name": "users", "description": "Operations with users"},
    {"name": "items", "description": "Manage items", "externalDocs": {
        "description": "Items external docs",
        "url": "https://example.com/items",
    }},
]

app = FastAPI(openapi_tags=tags_metadata)

@app.get("/users", tags=["users"])
async def get_users():
    return []

Webhooks:

webhooks = APIRouter()

@webhooks.post("new-subscription")
async def new_subscription(body: SubscriptionPayload):
    """Called when a new subscription is created."""
    ...

app = FastAPI(webhooks=webhooks)

Webhooks appear in the OpenAPI schema for client code generation but are not routable endpoints in your app.

Custom OpenAPI schema:

from fastapi.openapi.utils import get_openapi

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    schema = get_openapi(
        title=app.title,
        version=app.version,
        routes=app.routes,
    )
    schema["info"]["x-logo"] = {"url": "https://example.com/logo.png"}
    app.openapi_schema = schema
    return schema

app.openapi = custom_openapi

5. Common Tasks

5.1 CRUD API Pattern

A complete CRUD implementation with proper status codes and models:

from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel

app = FastAPI()

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

class ItemUpdate(BaseModel):
    name: str | None = None
    price: float | None = None

class ItemOut(BaseModel):
    id: int
    name: str
    price: float

db: dict[int, dict] = {}
counter = 0

@app.post("/items", response_model=ItemOut, status_code=status.HTTP_201_CREATED)
async def create(item: ItemCreate):
    global counter
    counter += 1
    record = {"id": counter, **item.model_dump()}
    db[counter] = record
    return record

@app.get("/items", response_model=list[ItemOut])
async def list_all(skip: int = 0, limit: int = 20):
    return list(db.values())[skip : skip + limit]

@app.get("/items/{item_id}", response_model=ItemOut)
async def get_one(item_id: int):
    if item_id not in db:
        raise HTTPException(404, "Item not found")
    return db[item_id]

@app.patch("/items/{item_id}", response_model=ItemOut)
async def update(item_id: int, updates: ItemUpdate):
    if item_id not in db:
        raise HTTPException(404, "Item not found")
    stored = db[item_id]
    for key, val in updates.model_dump(exclude_unset=True).items():
        stored[key] = val
    return stored

@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete(item_id: int):
    if item_id not in db:
        raise HTTPException(404, "Item not found")
    del db[item_id]

5.2 Database Integration (SQLAlchemy)

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session, DeclarativeBase
from fastapi import Depends

engine = create_engine("sqlite:///./app.db", connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(bind=engine)

class Base(DeclarativeBase):
    pass

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/users")
def list_users(db: Session = Depends(get_db)):
    return db.query(UserModel).all()

5.3 Database Integration (SQLModel)

SQLModel combines SQLAlchemy and Pydantic in a single model:

from sqlmodel import SQLModel, Field, Session, create_engine, select

class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: int | None = None

engine = create_engine("sqlite:///heroes.db")
SQLModel.metadata.create_all(engine)

def get_session():
    with Session(engine) as session:
        yield session

@app.post("/heroes", response_model=Hero)
def create_hero(hero: Hero, session: Session = Depends(get_session)):
    session.add(hero)
    session.commit()
    session.refresh(hero)
    return hero

@app.get("/heroes", response_model=list[Hero])
def list_heroes(session: Session = Depends(get_session)):
    return session.exec(select(Hero)).all()

5.4 JWT Authentication

from datetime import datetime, timedelta
from jose import jwt, JWTError
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")

def create_access_token(data: dict):
    to_encode = data.copy()
    to_encode["exp"] = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

async def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise HTTPException(status_code=401, detail="Invalid token")
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")
    user = get_user_from_db(username)
    if user is None:
        raise HTTPException(status_code=401, detail="User not found")
    return user

@app.get("/protected")
async def protected_route(user: User = Depends(get_current_user)):
    return {"user": user.username}

5.5 CORS for Frontend Integration

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",
        "https://myapp.example.com",
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
    expose_headers=["X-Total-Count"],
    max_age=600,
)

5.6 Rate Limiting Pattern

FastAPI does not include built-in rate limiting, but you can implement it with middleware or dependencies:

from collections import defaultdict
import time
from fastapi import Request, HTTPException

request_counts: dict[str, list[float]] = defaultdict(list)

async def rate_limit(request: Request):
    client_ip = request.client.host
    now = time.time()
    window = 60  # seconds
    max_requests = 100

    # Remove old entries
    request_counts[client_ip] = [
        t for t in request_counts[client_ip] if now - t < window
    ]

    if len(request_counts[client_ip]) >= max_requests:
        raise HTTPException(status_code=429, detail="Rate limit exceeded")

    request_counts[client_ip].append(now)

app = FastAPI(dependencies=[Depends(rate_limit)])

5.7 Testing FastAPI Applications

FastAPI provides a TestClient built on httpx:

from fastapi.testclient import TestClient

client = TestClient(app)

def test_read_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello World"}

def test_create_item():
    response = client.post("/items", json={"name": "Widget", "price": 9.99})
    assert response.status_code == 201
    assert response.json()["name"] == "Widget"

def test_validation_error():
    response = client.post("/items", json={"name": "", "price": -1})
    assert response.status_code == 422

def test_not_found():
    response = client.get("/items/99999")
    assert response.status_code == 404

Async testing with pytest-asyncio and httpx:

import pytest
from httpx import AsyncClient, ASGITransport

@pytest.mark.anyio
async def test_async():
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as client:
        response = await client.get("/")
        assert response.status_code == 200

Overriding dependencies in tests:

def get_test_db():
    return test_database

app.dependency_overrides[get_db] = get_test_db

client = TestClient(app)
response = client.get("/users")

# Clean up
app.dependency_overrides.clear()

5.8 Pagination Pattern

from pydantic import BaseModel
from fastapi import Query

class PaginatedResponse(BaseModel):
    items: list
    total: int
    page: int
    size: int
    pages: int

@app.get("/items", response_model=PaginatedResponse)
async def list_items(
    page: int = Query(default=1, ge=1),
    size: int = Query(default=20, ge=1, le=100),
):
    total = len(all_items)
    start = (page - 1) * size
    items = all_items[start : start + size]
    return PaginatedResponse(
        items=items,
        total=total,
        page=page,
        size=size,
        pages=(total + size - 1) // size,
    )

5.9 Request Validation Patterns

Nested models:

class Address(BaseModel):
    street: str
    city: str
    zip_code: str = Field(pattern=r"^\d{5}(-\d{4})?$")

class UserCreate(BaseModel):
    name: str
    email: str
    addresses: list[Address] = []

Custom validators:

from pydantic import field_validator

class Order(BaseModel):
    quantity: int
    unit_price: float

    @field_validator("quantity")
    @classmethod
    def quantity_must_be_positive(cls, v):
        if v <= 0:
            raise ValueError("Quantity must be positive")
        return v

Model with examples for OpenAPI docs:

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

    model_config = {
        "json_schema_extra": {
            "examples": [
                {"name": "Widget", "price": 9.99},
                {"name": "Gadget", "price": 24.99},
            ]
        }
    }

5.10 Deploying Behind a Reverse Proxy

When deploying behind Nginx, Traefik, or similar:

app = FastAPI(root_path="/api/v1")

Or pass it at the ASGI server level:

uvicorn main:app --root-path /api/v1

This ensures the OpenAPI schema and documentation URLs correctly reflect the proxy prefix.

5.11 Multi-Worker Production Deployment

Using Gunicorn with Uvicorn workers:

pip install gunicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

Docker deployment:

FROM python:3.12-slim

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

CMD ["fastapi", "run", "main.py", "--port", "8000"]

Tip

For multi-worker deployments, avoid storing state in module-level variables (they are not shared between workers). Use a database, Redis, or similar shared store.

5.12 Structured Logging

import logging
from fastapi import Request

logger = logging.getLogger("myapp")

@app.middleware("http")
async def log_requests(request: Request, call_next):
    logger.info(f"{request.method} {request.url.path}")
    response = await call_next(request)
    logger.info(f"Response: {response.status_code}")
    return response

5.13 Health Check Endpoint

@app.get("/health")
async def health():
    return {"status": "healthy"}

@app.get("/ready")
async def readiness(db: Session = Depends(get_db)):
    try:
        db.execute(text("SELECT 1"))
        return {"status": "ready"}
    except Exception:
        raise HTTPException(503, "Database unavailable")

6. Troubleshooting

Installation Issues

# Problem Solution
1 RuntimeError: To use the fastapi command, please install "fastapi[standard]" Run pip install "fastapi[standard]" instead of pip install fastapi
2 ModuleNotFoundError: No module named 'pydantic' FastAPI requires Pydantic; reinstall with pip install fastapi to pull dependencies
3 pip install fastapi[standard] fails in zsh Quote the brackets: pip install "fastapi[standard]" (zsh interprets brackets as glob)
4 Conflicting Pydantic versions FastAPI requires Pydantic v2; run pip install "pydantic>=2.0" to upgrade
5 ImportError: cannot import name 'PydanticV1NotSupportedError' You are using Pydantic v1 which is no longer supported; upgrade to Pydantic v2

Server and Runtime Issues

# Problem Solution
6 Address already in use when starting Another process is using port 8000; kill it or use --port 8001
7 Server starts but no auto-reload Use fastapi dev (not fastapi run) or add --reload flag to uvicorn
8 asyncio.run() cannot be called from a running event loop You are calling sync code inside an async endpoint; use await or run in executor
9 Slow response with sync def endpoints Sync endpoints run in a thread pool (limited threads); switch to async def for I/O-bound work, or increase thread pool size
10 uvicorn not found after install Ensure your virtual environment is activated; pip install uvicorn[standard]

Request Handling Issues

# Problem Solution
11 422 Unprocessable Entity on POST requests Request body does not match the Pydantic model; check the detail array in the response for specific field errors
12 422 error when sending form data Ensure you are using Form() parameters, not a Pydantic body model. Also install python-multipart
13 Query parameters not received Parameters with default values of None are optional; required params have no default. Check parameter names match the URL query string
14 405 Method Not Allowed You are using the wrong HTTP method (e.g., GET instead of POST). Check the decorator
15 Path parameters received as strings despite int annotation This should not happen with FastAPI; verify the path parameter syntax is {param_name} and the annotation is correct
16 307 Temporary Redirect on POST FastAPI's redirect_slashes=True (default) redirects /items to /items/; on redirect, POST becomes GET. Define your route with a trailing slash or set redirect_slashes=False
17 Request body is empty/None Ensure Content-Type: application/json header is set. With strict_content_type=True (default), missing or wrong Content-Type causes rejection
18 File uploads fail silently Verify python-multipart is installed and the parameter uses UploadFile or File()
19 Large file upload times out Configure your ASGI server timeout; Uvicorn default is no timeout but reverse proxies may have limits
20 Duplicate query parameter values lost Use list[str] type annotation with Query() to receive all values

CORS and Security Issues

# Problem Solution
21 CORS errors in browser Add CORSMiddleware with the correct allow_origins. Wildcard ["*"] works for dev but specify exact origins for production
22 CORS preflight fails despite middleware Ensure allow_methods includes the method being used and allow_headers includes custom headers. If using credentials, allow_origins cannot be ["*"]
23 OAuth2 "Not authenticated" in Swagger UI Click the "Authorize" button in Swagger UI and enter your token before making requests
24 Cookies not sent in cross-origin requests Set allow_credentials=True in CORS middleware and use withCredentials: true on the client side

Response and Serialization Issues

# Problem Solution
25 datetime objects serialized as strings unexpectedly This is correct behavior; JSON does not have a datetime type. Pydantic serializes to ISO 8601 strings
26 Response includes extra fields not in response_model This should not happen; response_model filters output. Verify you are using response_model= in the decorator, not just the return type hint
27 response_model causes performance issues For large responses, use response_model_exclude_unset=True to skip unnecessary validation. Or return a Response directly
28 Binary data in JSON response Return binary content using StreamingResponse or FileResponse instead of JSONResponse
29 ORJSONResponse raises ImportError Install orjson: pip install orjson
30 Nested model fields show as null despite being set Check that nested Pydantic models use proper type annotations; Optional[Model] requires explicit None default

Testing Issues

# Problem Solution
31 TestClient not found Install httpx: pip install httpx (included with fastapi[standard])
32 Tests fail with dependency injection Use app.dependency_overrides[dependency_func] = mock_func to replace dependencies in tests
33 Async tests fail Use pytest-anyio and httpx.AsyncClient with ASGITransport for async test support
34 WebSocket tests hang Use with client.websocket_connect("/ws") as ws: context manager pattern
35 File upload tests fail Pass files as files={"file": ("name.txt", b"content", "text/plain")} in the TestClient call

Deployment Issues

# Problem Solution
36 OpenAPI docs show wrong URLs behind reverse proxy Set root_path in FastAPI() constructor or pass --root-path to uvicorn
37 Static files return 404 in production Ensure the directory path in StaticFiles() is absolute or correctly relative to the working directory
38 Gunicorn workers crash with [CRITICAL] WORKER TIMEOUT Increase --timeout (default 30s) or investigate if an endpoint is blocking too long
39 Memory grows unbounded with streaming Ensure you are using yield in streaming responses and not accumulating data in memory
40 Application does not shut down cleanly Use the lifespan context manager to properly close database connections, HTTP clients, and other resources

7. FAQ

Q1: What Python versions does FastAPI support? FastAPI requires Python 3.8 or higher. Type hint features used by FastAPI (like str | None) require Python 3.10+; for older Python versions use Optional[str] from typing.

Q2: Is FastAPI async or sync? Both. Endpoints declared with async def run on the async event loop. Endpoints declared with def run in an external thread pool automatically. You can mix both freely in the same application.

Q3: How does FastAPI compare to Flask in performance? FastAPI runs on ASGI (Starlette + Uvicorn), which supports async I/O natively. For I/O-bound workloads, FastAPI significantly outperforms Flask (WSGI). For CPU-bound work, both are limited by Python's GIL.

Q4: Can I use FastAPI without Pydantic models? Yes. You can use plain Python types for path, query, header, and cookie parameters. However, for request bodies, Pydantic models are the recommended approach. You can also use dataclasses.

Q5: How do I disable the docs endpoints in production? Set openapi_url=None in the FastAPI() constructor. This disables /openapi.json, /docs, and /redoc entirely.

Q6: Can I use SQLAlchemy / SQLModel / Tortoise ORM / MongoDB with FastAPI? Yes. FastAPI is ORM-agnostic. Use dependency injection to provide database sessions. SQLModel is particularly well-integrated since it combines SQLAlchemy and Pydantic.

Q7: How do I handle CORS? Add CORSMiddleware via app.add_middleware(). Specify allowed origins, methods, and headers. See section 5.5 for a complete example.

Q8: What is response_model vs return type annotation? response_model is a decorator parameter that filters and validates the response. Return type annotations (e.g., -> ItemOut) also work for the OpenAPI schema. If both are provided, response_model takes priority.

Q9: How do I version my API? Common approaches: (1) URL prefix versioning with APIRouter(prefix="/v1") or app.mount(), (2) header-based versioning with custom middleware, (3) separate FastAPI() instances mounted as sub-applications.

Q10: Can I serve HTML pages with FastAPI? Yes. Use Jinja2Templates for server-rendered HTML and HTMLResponse as the response class. You can also mount StaticFiles for CSS, JS, and images.

Q11: How do I add request/response logging? Use a custom middleware function (see section 5.12). The middleware receives every request and can inspect both the request and response.

Q12: What is the difference between fastapi dev and fastapi run? fastapi dev enables auto-reload and binds to 127.0.0.1 (localhost only). fastapi run disables auto-reload and binds to 0.0.0.0 (all interfaces). Use dev during development, run in production.

Q13: How do I handle file downloads? Return a FileResponse with the path parameter pointing to the file. Set filename for the download name and media_type for the Content-Type header.

Q14: Can I use WebSockets and HTTP endpoints in the same app? Yes. WebSocket endpoints use @app.websocket() and coexist with HTTP endpoints. They share the same dependency injection system.

Q15: How do I implement pagination? Use query parameters (page, size or skip, limit) with Query() for validation. Return a response model that includes total, page, size, and items. See section 5.8.

Q16: What is Depends() vs Security()? Depends() declares a dependency. Security() is identical but additionally accepts OAuth2 scopes and integrates with the OpenAPI security scheme display.

Q17: How do I run background tasks? Declare a BackgroundTasks parameter in your endpoint and call .add_task(). Tasks run after the response is sent. For heavy work, use Celery or a similar task queue.

Q18: How do I add custom headers to responses? Declare a Response parameter and set response.headers["X-Custom"] = "value". The response object is merged with the return value.

Q19: What is root_path and when do I need it? root_path tells FastAPI that it is served under a URL prefix (e.g., /api/v1). Set this when deploying behind a reverse proxy that strips the prefix. It ensures OpenAPI docs and redirect URLs are correct.

Q20: Can I use dependency injection in WebSocket endpoints? Yes. WebSocket endpoints support Depends() the same way HTTP endpoints do.

Q21: How do I validate query parameters as enums? Define a Python Enum class and use it as the type annotation. FastAPI validates that the value is one of the allowed options and generates the enum in OpenAPI.

Q22: How do I return different status codes from the same endpoint? Use Response parameter to set response.status_code dynamically, or raise HTTPException for error cases. Declare additional codes in responses={} for OpenAPI documentation.

Q23: What is separate_input_output_schemas? When True (default), FastAPI generates separate OpenAPI schemas for request bodies and response bodies even if they use the same Pydantic model. This prevents clients from seeing read-only fields in request schemas.

Q24: What does strict_content_type=True do? It enforces that the Content-Type header matches the expected media type. This provides CSRF protection by rejecting requests that claim to be JSON but are actually form-encoded (which browsers can send without CORS preflight).

Q25: How do I handle multiple file uploads with metadata? Combine UploadFile parameters with Form() parameters in the same endpoint. Each gets its own parameter declaration.

Q26: Can I generate client SDKs from my FastAPI app? Yes. FastAPI generates a full OpenAPI 3.1.0 schema at /openapi.json. Use any OpenAPI code generator (e.g., openapi-generator, swagger-codegen, openapi-typescript-codegen) to generate client libraries.

Q27: How do I test WebSocket endpoints? Use TestClient with client.websocket_connect("/ws") as a context manager. Inside the context, call ws.send_text() and ws.receive_text() to simulate communication.

Q28: How do I handle large request bodies? Uvicorn has no built-in body size limit. Add limits at the reverse proxy level (e.g., Nginx client_max_body_size) or implement a custom middleware that checks Content-Length.

Q29: What is an APIRouter and when should I use it? APIRouter is FastAPI's mechanism for organizing endpoints into modules. Use it when your application has multiple resource types or feature areas. Include routers in the main app with app.include_router().

Q30: How do I use Server-Sent Events (SSE)? Return an EventSourceResponse that yields ServerSentEvent objects. See section 4.14 for a complete example. Clients connect with the EventSource browser API or similar.

8. Quick Reference

Path Operation Decorator Parameters

Parameter Type Purpose
path str URL path (first positional argument)
response_model type Pydantic model for response filtering/validation
status_code int Default HTTP status code
tags list[str] OpenAPI tags for grouping
summary str Short endpoint summary
description str Detailed endpoint description
response_description str Description of the response
responses dict Additional OpenAPI response definitions
deprecated bool Mark as deprecated in OpenAPI
operation_id str Custom OpenAPI operation ID
include_in_schema bool Include in OpenAPI schema
response_model_include set Fields to include in response
response_model_exclude set Fields to exclude from response
response_model_exclude_unset bool Exclude unset fields from response
response_model_exclude_defaults bool Exclude default-valued fields
response_model_exclude_none bool Exclude None-valued fields
callbacks list OpenAPI callback definitions
openapi_extra dict Additional OpenAPI metadata

Parameter Types

Function Source Example
Path() URL path segment /items/{item_id}
Query() URL query string ?skip=0&limit=10
Header() HTTP headers Authorization: Bearer token
Cookie() HTTP cookies session_id=abc123
Body() Request body (JSON) {"name": "Widget"}
Form() Form-encoded body username=admin&password=secret
File() Multipart file upload Binary file content

Common Validation Parameters

These parameters work with Path(), Query(), Body(), Header(), Cookie(), Form():

Parameter Applies To Purpose
default All Default value
title All Schema title for docs
description All Schema description for docs
alias All Alternative field name in the request
min_length str Minimum string length
max_length str Maximum string length
pattern str Regex pattern
ge numeric Greater than or equal
gt numeric Greater than
le numeric Less than or equal
lt numeric Less than
multiple_of numeric Must be a multiple of this value
examples All Example values for OpenAPI docs
deprecated All Mark as deprecated
include_in_schema All Include in OpenAPI schema

HTTP Status Code Constants

FastAPI re-exports Starlette's status codes via fastapi.status:

Constant Code Typical Use
HTTP_200_OK 200 Successful GET/PUT/PATCH
HTTP_201_CREATED 201 Successful POST (resource created)
HTTP_204_NO_CONTENT 204 Successful DELETE (no body)
HTTP_301_MOVED_PERMANENTLY 301 Permanent redirect
HTTP_302_FOUND 302 Temporary redirect
HTTP_304_NOT_MODIFIED 304 Cache hit
HTTP_400_BAD_REQUEST 400 Client error
HTTP_401_UNAUTHORIZED 401 Authentication required
HTTP_403_FORBIDDEN 403 Insufficient permissions
HTTP_404_NOT_FOUND 404 Resource not found
HTTP_405_METHOD_NOT_ALLOWED 405 Wrong HTTP method
HTTP_409_CONFLICT 409 Resource conflict
HTTP_422_UNPROCESSABLE_ENTITY 422 Validation error
HTTP_429_TOO_MANY_REQUESTS 429 Rate limited
HTTP_500_INTERNAL_SERVER_ERROR 500 Server error
HTTP_502_BAD_GATEWAY 502 Upstream error
HTTP_503_SERVICE_UNAVAILABLE 503 Service down

Import Cheat Sheet

# Core
from fastapi import FastAPI, APIRouter, Request, Response

# Parameters
from fastapi import Path, Query, Header, Cookie, Body, Form, File, UploadFile

# Dependencies
from fastapi import Depends, Security

# Exceptions
from fastapi import HTTPException, WebSocketException
from fastapi.exceptions import RequestValidationError

# Responses
from fastapi.responses import (
    JSONResponse, HTMLResponse, PlainTextResponse,
    RedirectResponse, StreamingResponse, FileResponse,
    ORJSONResponse, UJSONResponse,
    EventSourceResponse,
)

# Security
from fastapi.security import (
    OAuth2PasswordBearer, OAuth2PasswordRequestForm,
    OAuth2AuthorizationCodeBearer,
    HTTPBasic, HTTPBasicCredentials,
    HTTPBearer, HTTPAuthorizationCredentials,
    APIKeyHeader, APIKeyQuery, APIKeyCookie,
)

# Middleware
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware

# Background tasks
from fastapi import BackgroundTasks

# WebSockets
from fastapi import WebSocket, WebSocketDisconnect

# Testing
from fastapi.testclient import TestClient

# Templates & Static
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles

# Encoding
from fastapi.encoders import jsonable_encoder

# Status codes
from fastapi import status

Tip

For architecture details, deployment configuration, security internals, and performance tuning, see the FastAPI Admin Guide (Admin Guide section).