FastAPI cheat sheet

A scannable FastAPI reference: 13 short snippets across 10 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Your first FastAPI appPath operations, type-driven validation, automatic OpenAPI docs, and the route-ordering trap that silently returns 422lesson
Pydantic request and response modelsDefine the wire contract with Pydantic: validation, custom validators, and response models that stop internal fieldslesson
Path, query and body parameters in depthA parameter in the route string is a path parameter. FastAPI converts it using the type annotation, and a value thatlesson
Routers, project layout and API versioningThe rule that keeps this maintainable: routers translate HTTP to function calls, services hold the logic, and serviceslesson
Databases with SQLAlchemy and session dependenciesThe yield dependency guarantees the session closes even when the endpoint raises. Without it, a failing request leaks alesson
Authentication with OAuth2, JWT and password hashingA JWT is signed, not encrypted: anyone can read the payload. Put only an identifier and authorisation claims in itlesson
Error handling, middleware and CORSHandlers registered for specific exception classes replace the default response entirely. Raising HTTPException stayslesson
File uploads, streaming and WebSocketsA generator response starts sending headers immediately, so an error after the first chunk cannot become a 500lesson
Testing FastAPI apps with TestClient and pytestExercise endpoints without a running server, swap the database per test, write async tests with httpx, and assert thelesson
Deployment: uvicorn workers, Docker and reverse proxiesEach worker is a separate process with its own memory. Module-level caches, in-memory rate limits and BackgroundTaskslesson

Quick snippets

Your first FastAPI app

The smallest app

pip install "fastapi[standard]"
fastapi dev main.py            # reload on save, http://127.0.0.1:8000
uvicorn main:app --reload      # equivalent, explicit ASGI server

curl http://127.0.0.1:8000/notes/1
curl "http://127.0.0.1:8000/notes/1?q=milk"

Full lesson: Your first FastAPI app →

Pydantic request and response models

Request models

from fastapi import FastAPI
from schemas import NoteIn

app = FastAPI()

@app.post("/notes", status_code=201)
def create_note(note: NoteIn) -> dict[str, object]:
    return {"stored": note.title, "tags": note.tags}

Full lesson: Pydantic request and response models →

Path, query and body parameters in depth

Query parameters

from fastapi import Query

@app.get("/search")
def search(
    q: Annotated[str, Query(min_length=2, max_length=80)],
    page: Annotated[int, Query(ge=1)] = 1,
    size: Annotated[int, Query(ge=1, le=100)] = 20,
    sort: Annotated[str, Query(alias="order-by")] = "created_at",
    tags: Annotated[list[str] | None, Query()] = None,
):
    return {"q": q, "page": page, "size": size, "sort": sort, "tags": tags or []}

Query parameters

# repeated keys fill a list
curl "http://127.0.0.1:8000/search?q=hello&size=5&order-by=name&tags=a&tags=b"

Full lesson: Path, query and body parameters in depth →

Routers, project layout and API versioning

APIRouter

# app/main.py
from fastapi import FastAPI
from .routers import items, users

app = FastAPI(title="Shop API", version="1.0.0")
app.include_router(items.router, prefix="/api/v1")
app.include_router(users.router, prefix="/api/v1")

Full lesson: Routers, project layout and API versioning →

Databases with SQLAlchemy and session dependencies

Eager loading and transactions

from sqlalchemy.orm import selectinload

# N+1 avoided: one query for users, one for their items
users = db.scalars(
    select(User).options(selectinload(User.items)).order_by(User.id).limit(50)
).all()

# a transaction block: roll back everything on error
with db.begin():
    db.add(User(email="[email protected]"))
    db.add(Item(name="widget", owner_id=1))

Full lesson: Databases with SQLAlchemy and session dependencies →

Authentication with OAuth2, JWT and password hashing

Storing passwords

pip install "passlib[bcrypt]" "python-jose[cryptography]"

Full lesson: Authentication with OAuth2, JWT and password hashing →

Error handling, middleware and CORS

CORS for browser clients

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://app.example.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
)

Full lesson: Error handling, middleware and CORS →

File uploads, streaming and WebSockets

WebSockets

from fastapi import WebSocket, WebSocketDisconnect

@app.websocket("/ws/echo")
async def echo(ws: WebSocket):
    await ws.accept()
    try:
        while True:
            message = await ws.receive_text()
            await ws.send_text(f"echo: {message}")
    except WebSocketDisconnect:
        logger.info("client disconnected")

Full lesson: File uploads, streaming and WebSockets →

Testing FastAPI apps with TestClient and pytest

TestClient basics

def test_create_and_read(client):
    created = client.post("/api/v1/items", json={"name": "widget", "price": 9.99})
    assert created.status_code == 201
    body = created.json()
    assert body["name"] == "widget"

    fetched = client.get(f"/api/v1/items/{body['id']}")
    assert fetched.status_code == 200
    assert fetched.json()["price"] == 9.99

Async tests with httpx

pip install pytest pytest-asyncio httpx

Async tests with httpx

import pytest
from httpx import ASGITransport, AsyncClient
from app.main import app

@pytest.mark.anyio
async def test_health():
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as ac:
        r = await ac.get("/health")
    assert r.status_code == 200
    assert r.json() == {"status": "ok"}

Full lesson: Testing FastAPI apps with TestClient and pytest →

Deployment: uvicorn workers, Docker and reverse proxies

Workers

# development: one process, reload on change
uvicorn app.main:app --reload --port 8000

# production: several processes, no reload
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4 --no-access-log

# or a process manager around uvicorn
gunicorn app.main:app -k uvicorn.workers.UvicornWorker -w 4 --timeout 60 --graceful-timeout 30

Full lesson: Deployment: uvicorn workers, Docker and reverse proxies →

FAQ

Is this FastAPI cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 10 lessons of the FastAPI course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full FastAPI course — it carries the worked explanations, the edge cases and the exercises behind every line here.

Python 3 NumPy pandas Matplotlib Jupyter Notebook Flask

Last refreshed 2026-09-27.