📖 Scenario: You are building a simple API to receive user information for a newsletter subscription.The API should accept user data in the request body and process it.
🎯 Goal: Build a FastAPI endpoint that declares a request body using a Pydantic model to receive user data.
📋 What You'll Learn
Create a Pydantic model named User with fields name (string) and email (string).
Create a FastAPI app instance named app.
Create a POST endpoint at /subscribe that accepts a User object as the request body.
Return the received user data as JSON in the response.
💡 Why This Matters
🌍 Real World
APIs often need to receive structured data from clients. Declaring request bodies clearly helps validate and process this data safely.
💼 Career
Knowing how to declare request bodies with Pydantic models in FastAPI is essential for backend developers building modern web APIs.
Progress0 / 4 steps
1
Create the User model
Create a Pydantic model called User with two fields: name of type str and email of type str.
FastAPI
Hint
Use class User(BaseModel): and define name and email as string fields.
2
Create the FastAPI app instance
Import FastAPI and create an app instance named app.
FastAPI
Hint
Use app = FastAPI() to create the app instance.
3
Create the POST endpoint with request body
Create a POST endpoint at /subscribe using @app.post("/subscribe"). Define a function subscribe that takes a parameter user of type User to receive the request body.
FastAPI
Hint
Use @app.post("/subscribe") decorator and define subscribe(user: User) function that returns user.
4
Complete the FastAPI app
Ensure the full code includes the User model, the app instance, and the /subscribe POST endpoint returning the user data.
FastAPI
Hint
Make sure all parts are included and correctly indented.
Practice
(1/5)
1. What is the main purpose of declaring a request body in FastAPI using a Pydantic model?
easy
A. To define the URL path for the API endpoint
B. To tell FastAPI what data structure to expect and validate from the client
C. To specify the HTTP method like GET or POST
D. To set the response status code
Solution
Step 1: Understand request body role
The request body contains data sent by the client to the server, usually in POST or PUT requests.
Step 2: Role of Pydantic model in FastAPI
Using a Pydantic model tells FastAPI the expected data shape and automatically validates it.
Final Answer:
To tell FastAPI what data structure to expect and validate from the client -> Option B
Quick Check:
Request body declaration = Data validation [OK]
Hint: Request body = data shape + validation [OK]
Common Mistakes:
Confusing request body with URL path
Thinking request body sets HTTP method
Assuming request body controls response code
2. Which of the following is the correct way to declare a request body parameter in a FastAPI endpoint?
easy
A. def create_item(item: dict):
B. def create_item(item: BaseModel):
C. def create_item(item: Item):
D. def create_item(item: str):
Solution
Step 1: Recognize Pydantic model usage
FastAPI expects a Pydantic model class (like Item) to declare request body parameters.
Step 2: Check each option
def create_item(item: dict): uses dict which works but is not recommended; def create_item(item: BaseModel): uses BaseModel directly which is abstract; def create_item(item: Item): uses a user-defined model Item which is correct; def create_item(item: str): uses str which is not a model.
Final Answer:
def create_item(item: Item): -> Option C
Quick Check:
Use Pydantic model class for request body [OK]
Hint: Use your Pydantic model class as parameter type [OK]
Common Mistakes:
Using dict instead of a Pydantic model
Using BaseModel directly instead of subclass
Using primitive types like str for complex data
3. Given this FastAPI code snippet, what will be the output if the client sends JSON {"name": "apple", "price": 5}?
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
async def create_item(item: Item):
return {"item_name": item.name, "item_price": item.price}
medium
A. {"item_name": "apple", "item_price": "5"}
B. 500 Internal Server Error
C. ValidationError because price is int, not float
D. {"item_name": "apple", "item_price": 5.0}
Solution
Step 1: Understand Pydantic type conversion
Pydantic automatically converts compatible types, so int 5 converts to float 5.0.
Step 2: Check returned dictionary
The function returns a dict with keys "item_name" and "item_price" using the values from the item object.
Final Answer:
{"item_name": "apple", "item_price": 5.0} -> Option D
Quick Check:
Int converts to float automatically in Pydantic [OK]
Hint: Pydantic converts int to float automatically [OK]
Common Mistakes:
Thinking int and float types cause validation error
Expecting string instead of float for price
Assuming server error on type mismatch
4. Identify the error in this FastAPI endpoint declaration:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
username: str
age: int
@app.post("/users/")
def create_user(user: User = None):
return {"username": user.username, "age": user.age}
medium
A. Request body parameter cannot have a default value None
B. Missing async keyword in endpoint function
C. User class must inherit from object, not BaseModel
D. Return statement must be inside an async function
Solution
Step 1: Check request body parameter declaration
In FastAPI, request body parameters cannot have a default value of None because the body is required by default.
Step 2: Review other options
Async is optional for FastAPI endpoints; BaseModel inheritance is correct; return works in sync functions.
Final Answer:
Request body parameter cannot have a default value None -> Option A
Quick Check:
Request body params must not default to None [OK]
Hint: Request body params must be required unless explicitly optional [OK]
Common Mistakes:
Adding default None to request body param
Thinking async is mandatory
Misunderstanding BaseModel inheritance
5. You want to declare a request body in FastAPI that accepts an optional field description which can be missing or null. How should you declare the Pydantic model to handle this correctly?
hard
A. from pydantic import BaseModel
from typing import Optional
class Item(BaseModel):
name: str
description: Optional[str] = None
B. from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str
C. from pydantic import BaseModel
from typing import Union
class Item(BaseModel):
name: str
description: Union[str, None] = None
D. from pydantic import BaseModel
class Item(BaseModel):
name: str
description: None
Solution
Step 1: Understand optional fields in Pydantic
To allow a field to be optional or null, use Optional[type] with a default value None.
Step 2: Analyze each option
from pydantic import BaseModel
from typing import Optional
class Item(BaseModel):
name: str
description: Optional[str] = None correctly uses Optional[str] with default None; from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str requires description always; from pydantic import BaseModel
from typing import Union
class Item(BaseModel):
name: str
description: Union[str, None] = None uses Union[str, None] with default None; from pydantic import BaseModel
class Item(BaseModel):
name: str
description: None sets description to None type which is invalid.
Final Answer:
Use Optional[str] with default None for optional nullable field -> Option A
Quick Check:
Optional field = Optional[type] + default None [OK]
Hint: Use Optional[type] and default None for optional fields [OK]
Common Mistakes:
Forgetting to set default None for optional fields
Using plain type without Optional for nullable fields
Assigning None as a type instead of a value
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.