FastAPI Cheatsheet

Responses and Status Codes

Use this FastAPI reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

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}]