Request Body
FastAPI uses Pydantic models to define the structure of request bodies. When you declare a Pydantic model as a parameter in a path operation function, FastAPI automatically interprets it as a JSON request body, parses the incoming data, and validates it against the model's schema.
For more complex scenarios—such as receiving multiple objects in one request, adding validation to singular values in the body, or forcing a specific JSON structure—FastAPI provides the Body class in fastapi.params.
Singular Values in the Body
If you declare a parameter with a simple type (like int or str) in your path operation, FastAPI normally assumes it is a query parameter. If you want that value to be part of the JSON request body instead, you must explicitly use Body.
In docs_src/body_multiple_params/tutorial003_an_py310.py, the importance parameter is defined as a body value:
from typing import Annotated
from fastapi import Body, FastAPI
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
importance: Annotated[int, Body()]
):
return {"item_id": item_id, "importance": importance}
Without Annotated[int, Body()], FastAPI would look for importance in the URL query string (e.g., ?importance=5). With Body(), it expects a JSON body like {"importance": 5}.
Multiple Body Parameters
FastAPI allows you to define multiple Pydantic models and singular values as body parameters. When you do this, FastAPI expects a JSON object where each key matches the name of the parameter in your function.
Consider this example from docs_src/body_multiple_params/tutorial003_an_py310.py:
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Item,
user: User,
importance: Annotated[int, Body()]
):
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
return results
In this case, FastAPI will expect a JSON body structured like this:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
},
"importance": 5
}
FastAPI automatically performs the "merging" logic: it sees multiple body-related parameters and creates a composite schema where each parameter is a top-level key in the JSON object.
Embedding Single Parameters
By default, if you only have one Pydantic model as a parameter, FastAPI expects the JSON body to be the model's data directly. For example, if you have item: Item, the body should be {"name": "Foo", ...}.
If you want FastAPI to expect the model inside a specific key (matching the parameter name), use the embed=True parameter of the Body class. This is demonstrated in docs_src/body_fields/tutorial001_an_py310.py:
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
results = {"item_id": item_id, "item": item}
return results
With embed=True, the expected JSON body changes to:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
}
Validation and Metadata
The Body class inherits from Pydantic's FieldInfo, allowing you to apply the same validation constraints and metadata you would use in a Pydantic Field.
Constraints
You can enforce numeric or string constraints directly on body parameters:
- Numeric:
gt(greater than),ge(greater than or equal),lt,le. - Strings:
min_length,max_length,pattern(replaces the deprecatedregex).
Documentation Metadata
You can provide information for the generated OpenAPI schema:
title: A human-readable name for the parameter.description: A detailed explanation of what the parameter does.examples: A list of example values to show in the Swagger UI.
In docs_src/schema_extra_example/tutorial004_an_py310.py, multiple examples are provided for an Item body:
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
],
),
],
):
return {"item_id": item_id, "item": item}
[!WARNING] The
exampleparameter is deprecated in favor ofexamplesto align with OpenAPI 3.1.0. Similarly, usepatterninstead of the deprecatedregexparameter.
Custom Media Types
While the default media_type for Body is application/json, you can customize it if your endpoint expects a different format. The Body class constructor accepts a media_type string:
# Internal implementation in fastapi/params.py
class Body(FieldInfo):
def __init__(
self,
# ...
media_type: str = "application/json",
# ...
):
self.media_type = media_type
This is useful for specialized APIs that use custom vendor media types (e.g., application/vnd.api+json). FastAPI will use this value when generating the OpenAPI documentation for the request body.