Request Body¶
When you need to send data from a client (let's say, a browser) to your API, you send it as arequest body.
Arequest body is data sent by the client to your API. Aresponse body is the data your API sends to the client.
Your API almost always has to send aresponse body. But clients don't necessarily need to sendrequest bodies all the time, sometimes they only request a path, maybe with some query parameters, but don't send a body.
To declare arequest body, you usePydantic models with all their power and benefits.
Info
To send data, you should use one of:POST (the more common),PUT,DELETE orPATCH.
Sending a body with aGET request has an undefined behavior in the specifications, nevertheless, it is supported by FastAPI, only for very complex/extreme use cases.
As it is discouraged, the interactive docs with Swagger UI won't show the documentation for the body when usingGET, and proxies in the middle might not support it.
Import Pydantic'sBaseModel¶
First, you need to importBaseModel frompydantic:
fromfastapiimportFastAPIfrompydanticimportBaseModelclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Noneapp=FastAPI()@app.post("/items/")asyncdefcreate_item(item:Item):returnitemCreate your data model¶
Then you declare your data model as a class that inherits fromBaseModel.
Use standard Python types for all the attributes:
fromfastapiimportFastAPIfrompydanticimportBaseModelclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Noneapp=FastAPI()@app.post("/items/")asyncdefcreate_item(item:Item):returnitemThe same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. UseNone to make it just optional.
For example, this model above declares a JSON "object" (or Pythondict) like:
{"name":"Foo","description":"An optional description","price":45.2,"tax":3.5}...asdescription andtax are optional (with a default value ofNone), this JSON "object" would also be valid:
{"name":"Foo","price":45.2}Declare it as a parameter¶
To add it to yourpath operation, declare it the same way you declared path and query parameters:
fromfastapiimportFastAPIfrompydanticimportBaseModelclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Noneapp=FastAPI()@app.post("/items/")asyncdefcreate_item(item:Item):returnitem...and declare its type as the model you created,Item.
Results¶
With just that Python type declaration,FastAPI will:
- Read the body of the request as JSON.
- Convert the corresponding types (if needed).
- Validate the data.
- If the data is invalid, it will return a nice and clear error, indicating exactly where and what was the incorrect data.
- Give you the received data in the parameter
item.- As you declared it in the function to be of type
Item, you will also have all the editor support (completion, etc) for all of the attributes and their types.
- As you declared it in the function to be of type
- GenerateJSON Schema definitions for your model, you can also use them anywhere else you like if it makes sense for your project.
- Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentationUIs.
Automatic docs¶
The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs:

And will also be used in the API docs inside eachpath operation that needs them:

Editor support¶
In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received adict instead of a Pydantic model):

You also get error checks for incorrect type operations:

This is not by chance, the whole framework was built around that design.
And it was thoroughly tested at the design phase, before any implementation, to ensure it would work with all the editors.
There were even some changes to Pydantic itself to support this.
The previous screenshots were taken withVisual Studio Code.
But you would get the same editor support withPyCharm and most of the other Python editors:

Tip
If you usePyCharm as your editor, you can use thePydantic PyCharm Plugin.
It improves editor support for Pydantic models, with:
- auto-completion
- type checks
- refactoring
- searching
- inspections
Use the model¶
Inside of the function, you can access all the attributes of the model object directly:
fromfastapiimportFastAPIfrompydanticimportBaseModelclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Noneapp=FastAPI()@app.post("/items/")asyncdefcreate_item(item:Item):item_dict=item.model_dump()ifitem.taxisnotNone:price_with_tax=item.price+item.taxitem_dict.update({"price_with_tax":price_with_tax})returnitem_dictRequest body + path parameters¶
You can declare path parameters and request body at the same time.
FastAPI will recognize that the function parameters that match path parameters should betaken from the path, and that function parameters that are declared to be Pydantic models should betaken from the request body.
fromfastapiimportFastAPIfrompydanticimportBaseModelclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Noneapp=FastAPI()@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):return{"item_id":item_id,**item.model_dump()}Request body + path + query parameters¶
You can also declarebody,path andquery parameters, all at the same time.
FastAPI will recognize each of them and take the data from the correct place.
fromfastapiimportFastAPIfrompydanticimportBaseModelclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Noneapp=FastAPI()@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item,q:str|None=None):result={"item_id":item_id,**item.model_dump()}ifq:result.update({"q":q})returnresultThe function parameters will be recognized as follows:
- If the parameter is also declared in thepath, it will be used as a path parameter.
- If the parameter is of asingular type (like
int,float,str,bool, etc) it will be interpreted as aquery parameter. - If the parameter is declared to be of the type of aPydantic model, it will be interpreted as a requestbody.
Note
FastAPI will know that the value ofq is not required because of the default value= None.
Thestr | None is not used by FastAPI to determine that the value is not required, it will know it's not required because it has a default value of= None.
But adding the type annotations will allow your editor to give you better support and detect errors.
Without Pydantic¶
If you don't want to use Pydantic models, you can also useBody parameters. See the docs forBody - Multiple Parameters: Singular values in body.







