FastAPI Cheatsheet

Responses and Status Codes

Use this FastAPI reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Default Behavior

Return any dict, list, Pydantic model, or primitive — FastAPI serializes it to JSON with Content-Type: application/json and 200 OK.

@app.get("/items/{id}")
def get_item(id: int):
    return {"id": id, "name": "Widget"}   # → 200 JSON

Setting Status Codes

from fastapi import status

@app.post("/items", status_code=201)
def create_item(item: Item):
    return item

# Using the status constants (preferred for readability):
@app.post("/items", status_code=status.HTTP_201_CREATED)
def create_item(item: Item):
    return item

@app.delete("/items/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_item(id: int):
    return None   # body must be empty for 204

Common Status Code Constants

ConstantCodeMeaning
HTTP_200_OK200Default success
HTTP_201_CREATED201Resource created
HTTP_202_ACCEPTED202Accepted (async)
HTTP_204_NO_CONTENT204Success, no body
HTTP_301_MOVED_PERMANENTLY301Redirect permanent
HTTP_302_FOUND302Redirect temporary
HTTP_304_NOT_MODIFIED304Cache valid
HTTP_400_BAD_REQUEST400Client error
HTTP_401_UNAUTHORIZED401Auth required
HTTP_403_FORBIDDEN403Not allowed
HTTP_404_NOT_FOUND404Not found
HTTP_405_METHOD_NOT_ALLOWED405Wrong method
HTTP_409_CONFLICT409State conflict
HTTP_422_UNPROCESSABLE_ENTITY422Validation error
HTTP_429_TOO_MANY_REQUESTS429Rate limited
HTTP_500_INTERNAL_SERVER_ERROR500Server error

Dynamic Status Codes (Response parameter)

from fastapi import Response

@app.get("/items/{id}")
def get_or_create(id: int, response: Response):
    if db.exists(id):
        return db.get(id)
    else:
        response.status_code = 201
        return db.create(id)

Response Model

from pydantic import BaseModel

class ItemIn(BaseModel):
    name: str
    price: float
    secret_key: str

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

@app.post("/items", response_model=ItemOut, status_code=201)
def create(item: ItemIn):
    return item   # secret_key is stripped — only ItemOut fields returned

response_model Options

@app.get("/items/{id}",
    response_model=ItemOut,
    response_model_exclude_unset=True,   # skip fields not explicitly set
    response_model_exclude_none=True,    # skip None fields
    response_model_exclude_defaults=True, # skip fields at their default value
    response_model_include={"name", "price"},  # whitelist
    response_model_exclude={"secret"},         # blacklist
)
def get_item(id: int): ...

Response Classes

from fastapi.responses import (
    JSONResponse,
    HTMLResponse,
    PlainTextResponse,
    RedirectResponse,
    StreamingResponse,
    FileResponse,
    Response,
)

JSONResponse

from fastapi.responses import JSONResponse

@app.get("/custom")
def custom():
    return JSONResponse(
        content={"message": "OK"},
        status_code=200,
        headers={"X-Custom": "value"},
        media_type="application/json",
    )

HTMLResponse

@app.get("/page", response_class=HTMLResponse)
def page():
    return "<html><body><h1>Hello</h1></body></html>"

PlainTextResponse

@app.get("/text", response_class=PlainTextResponse)
def text():
    return "plain string"

RedirectResponse

from fastapi.responses import RedirectResponse

@app.get("/old-path")
def redirect():
    return RedirectResponse(url="/new-path", status_code=301)

StreamingResponse

from fastapi.responses import StreamingResponse

def csv_generator():
    yield "id,name\n"
    for item in db.iter_all():
        yield f"{item.id},{item.name}\n"

@app.get("/export.csv")
def export():
    return StreamingResponse(
        csv_generator(),
        media_type="text/csv",
        headers={"Content-Disposition": "attachment; filename=export.csv"},
    )

# Async generator:
async def async_gen():
    for chunk in large_dataset:
        yield chunk

@app.get("/stream")
async def stream():
    return StreamingResponse(async_gen(), media_type="application/octet-stream")

FileResponse

from fastapi.responses import FileResponse

@app.get("/download")
def download():
    return FileResponse(
        path="report.pdf",
        filename="report.pdf",        # Content-Disposition filename
        media_type="application/pdf",
        background=None,              # optional BackgroundTask
    )

Raw Response (no serialization)

from fastapi import Response

@app.get("/raw")
def raw():
    return Response(
        content=b"binary data",
        media_type="application/octet-stream",
        status_code=200,
        headers={"X-Custom": "val"},
    )

Setting Response Headers

from fastapi import Response

@app.get("/items/{id}")
def get_item(id: int, response: Response):
    response.headers["X-Item-ID"] = str(id)
    response.headers["Cache-Control"] = "max-age=3600"
    return {"id": id}

Setting Cookies

from fastapi import Response

@app.post("/login")
def login(response: Response):
    response.set_cookie(
        key="session",
        value="abc123",
        max_age=3600,           # seconds
        expires=None,           # datetime or None
        path="/",
        domain=None,
        secure=True,
        httponly=True,
        samesite="lax",         # "strict" | "lax" | "none"
    )
    return {"status": "logged in"}

@app.post("/logout")
def logout(response: Response):
    response.delete_cookie("session")
    return {"status": "logged out"}

Background Tasks

from fastapi import BackgroundTasks

def send_email(email: str, message: str):
    ...  # runs after response is sent

@app.post("/notify")
def notify(email: str, bg: BackgroundTasks):
    bg.add_task(send_email, email=email, message="Welcome!")
    return {"status": "queued"}

# Multiple tasks:
bg.add_task(task_one, arg1)
bg.add_task(task_two, arg1, kwarg=val)

Documenting Multiple Responses

@app.get(
    "/items/{id}",
    response_model=ItemOut,
    responses={
        200: {"description": "Item found", "model": ItemOut},
        404: {"description": "Item not found"},
        403: {
            "description": "Forbidden",
            "content": {
                "application/json": {
                    "example": {"detail": "Not enough permissions"}
                }
            },
        },
    },
)
def get_item(id: int): ...

ORJSONResponse (faster JSON)

# pip install orjson
from fastapi.responses import ORJSONResponse

app = FastAPI(default_response_class=ORJSONResponse)

# or per-route:
@app.get("/items", response_class=ORJSONResponse)
def list_items():
    return [{"id": 1}]