Core Decorator and Parameter Reference
Quick-lookup reference for FastAPI route decorators, path/query/body parameters, APIRouter configuration, and response types.
Learning Focus
By the end of this reference you can: quickly recall the syntax and options for every FastAPI decorator, parameter type, and response class.
Route Decorators
@app.get(path, **kwargs)
@app.post(path, **kwargs)
@app.put(path, **kwargs)
@app.patch(path, **kwargs)
@app.delete(path, **kwargs)
@app.options(path, **kwargs)
@app.head(path, **kwargs)
@app.websocket(path)
Decorator Keyword Arguments
status_code=200 HTTP status code for success
response_model=Model Pydantic model for response filtering
tags=["tag"] OpenAPI tag grouping
summary="Short summary" Short description for docs
description="Markdown" Full description for docs
deprecated=False Mark route as deprecated
include_in_schema=True Show/hide in OpenAPI docs
response_description="" Description of the response
operation_id="unique_id" Unique ID for client SDK generation
responses={404: {...}} Additional response codes in schema
dependencies=[...] Route-level dependencies
Path Parameters
# Basic
@app.get("/{item_id}")
async def f(item_id: int): ...
# With constraints
from typing import Annotated
from fastapi import Path
@app.get("/{item_id}")
async def f(item_id: Annotated[int, Path(ge=1, le=1000)]): ...
# Enum
class Color(str, Enum):
red = "red"
blue = "blue"
@app.get("/{color}")
async def f(color: Color): ...
# Path-catching (allows slashes)
@app.get("/{file_path:path}")
async def f(file_path: str): ...
Query Parameters
# Optional with default
async def f(skip: int = 0, limit: int = 10): ...
# Required (no default)
async def f(q: str): ...
# Optional (no default, can be None)
async def f(q: str | None = None): ...
# With constraints
from fastapi import Query
async def f(
q: Annotated[str | None, Query(min_length=2, max_length=50)] = None
): ...
# Multi-value
async def f(tag: Annotated[list[str], Query()] = []): ...
Request Body
# Pydantic model body
async def f(item: ItemCreate): ...
# Multiple bodies
async def f(item: Item, user: User): ...
# Scalar in body
from fastapi import Body
async def f(price: Annotated[float, Body(gt=0, embed=True)]): ...
# Form data
from fastapi import Form
async def f(username: str = Form(...), password: str = Form(...)): ...
# File upload
from fastapi import UploadFile, File
async def f(file: UploadFile = File(...)): ...
Headers and Cookies
from fastapi import Header, Cookie
async def f(
x_token: Annotated[str | None, Header()] = None,
session_id: Annotated[str | None, Cookie()] = None,
): ...
APIRouter
from fastapi import APIRouter
router = APIRouter(
prefix="/items",
tags=["items"],
dependencies=[Depends(auth)],
responses={404: {"description": "Not found"}},
)
app.include_router(
router,
prefix="/api/v1", # Override prefix
tags=["items-v1"], # Override tags
dependencies=[...], # Add extra deps
)
Response Options
from fastapi.responses import (
JSONResponse, # Default JSON
HTMLResponse, # HTML content
PlainTextResponse, # Plain text
FileResponse, # File from disk
StreamingResponse, # Generator/stream
RedirectResponse, # HTTP redirect
Response, # Raw response
)
# Custom headers
@app.get("/")
async def f(response: Response) -> dict:
response.headers["X-Custom"] = "value"
return {}
Common Pitfalls
| Pitfall | Cause / Symptom | Fix |
|---|---|---|
| Route not matched | Declaring /{item_id} after a fixed path like /me | Put fixed paths before parameterized paths |
422 on query param | Using int type hint on a string parameter sent by client | Use str for non-numeric identifiers; add Path/Query constraints |
| Request body not parsed | Using Form(...) where Body(...) is needed (or vice versa) | Match the parameter type to the Content-Type header |
Hands-On Practice
quick-routing-test.py
from fastapi import FastAPI, APIRouter, Query
from typing import Annotated
app = FastAPI()
router = APIRouter(prefix="/api/v1", tags=["v1"])
@router.get("/items/{item_id}", summary="Get item by ID")
async def get_item(
item_id: int,
q: Annotated[str | None, Query(min_length=2)] = None,
) -> dict:
return {"item_id": item_id, "q": q}
app.include_router(router)
# Run: uvicorn quick-routing-test:app --reload
# Test: curl "http://localhost:8000/api/v1/items/42?q=test"