Request Parameters and Headers
FastAPI provides a set of tools to define and validate data from different parts of the request: path parameters, query parameters, headers, and cookies. These are implemented using classes in fastapi.params that inherit from Pydantic's FieldInfo, allowing you to leverage Pydantic's validation rules while automatically generating OpenAPI documentation.
Parameter Types and Locations
FastAPI uses the Param class in fastapi.params.py as a base for all non-body request parameters. The specific location of a parameter is defined by the ParamTypes enum (and the corresponding ParameterInType in fastapi.openapi.models):
- Path: Parameters extracted from the URL path (e.g.,
/items/{item_id}). - Query: Parameters extracted from the URL query string (e.g.,
?q=search). - Header: Parameters extracted from HTTP headers.
- Cookie: Parameters extracted from request cookies.
Path Parameters
Path parameters are defined in the path of your operation decorator. Because they are part of the URL structure, they are always required and cannot have a default value. FastAPI enforces this in the Path class constructor in fastapi/params.py:
class Path(Param):
def __init__(self, default: Any = ..., **kwargs):
assert default is ..., "Path parameters cannot have a default value"
super().__init__(default=default, **kwargs)
In your application, you use Path to add metadata or validation:
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)]
):
return {"item_id": item_id}
Query Parameters
Query parameters are the default for any function parameters that are scalar types (like str, int, bool) and are not found in the path. You can use the Query class to add explicit validation:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(max_length=50, pattern="^fixedquery$")] = None
):
return {"q": q}
Header Parameters and Automatic Conversion
HTTP headers are often case-insensitive and use hyphens (e.g., User-Agent), but Python variable names cannot contain hyphens. By default, the Header class in fastapi.params converts underscores to hyphens.
This behavior is controlled by the convert_underscores parameter in the Header constructor:
# fastapi/params.py
class Header(Param):
def __init__(self, ..., convert_underscores: bool = True, **kwargs):
self.convert_underscores = convert_underscores
super().__init__(..., **kwargs)
When FastAPI processes the request in fastapi/dependencies/utils.py, it performs this conversion:
# fastapi/dependencies/utils.py
if not field_info.alias and getattr(field_info, "convert_underscores", None):
alias = param_name.replace("_", "-")
This allows you to define a parameter as user_agent and have FastAPI automatically look for the User-Agent header:
from typing import Annotated
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
async def read_items(user_agent: Annotated[str | None, Header()] = None):
return {"User-Agent": user_agent}
Grouping Parameters with Pydantic Models
For endpoints with many parameters, you can group them into a single Pydantic model. FastAPI will extract the fields from the model based on the parameter function you use (e.g., Header(), Query()).
from typing import Annotated
from fastapi import FastAPI, Header
from pydantic import BaseModel
app = FastAPI()
class CommonHeaders(BaseModel):
host: str
save_data: bool
if_modified_since: str | None = None
x_tag: list[str] = []
@app.get("/items/")
async def read_items(headers: Annotated[CommonHeaders, Header()]):
return headers
Internally, fastapi/dependencies/utils.py uses _get_flat_fields_from_params to expand these models into individual fields for validation and documentation.
OpenAPI Documentation and Examples
FastAPI maps your parameter definitions to the OpenAPI Parameter model defined in fastapi/openapi/models.py. This model includes fields like name, in, description, required, and deprecated.
Multiple Examples
You can provide multiple examples for a parameter using the openapi_examples argument. This is distinct from the JSON Schema examples field.
from fastapi import FastAPI, Header
from fastapi.openapi.models import Example
app = FastAPI()
@app.get("/header_examples/")
def header_examples(
data: str | None = Header(
default=None,
openapi_examples={
"Example One": {
"summary": "A simple example",
"value": "header1",
},
"Example Two": {
"summary": "Another example",
"value": "header2",
},
},
),
):
return data
FastAPI's OpenAPI utility (fastapi/openapi/utils.py) processes these examples when generating the final schema:
# fastapi/openapi/utils.py
openapi_examples = getattr(field_info, "openapi_examples", None)
if openapi_examples:
parameter["examples"] = jsonable_encoder(openapi_examples)
Deprecation
To mark a parameter as deprecated in the OpenAPI UI, pass deprecated=True to the parameter function. This sets the deprecated field in the underlying Parameter model:
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(deprecated=True)] = None):
return {"q": q}
Security Parameters
For security schemes like API keys, FastAPI provides specialized classes in fastapi.security that use the APIKeyIn enum from fastapi.openapi.models. This enum defines valid locations for API keys: query, header, or cookie.
# fastapi/openapi/models.py
class APIKeyIn(Enum):
query = "query"
header = "header"
cookie = "cookie"
When you use APIKeyHeader(name="x-api-key"), FastAPI creates an internal APIKey model that specifies the location, ensuring the security scheme is correctly documented in the OpenAPI components/securitySchemes section.