Welcome to Day 3 of our FastAPI journey! Yesterday, we explored how to use path parameters to handle dynamic URLs.
Today, we’re entering the world of Request Bodies and Pydantic — the backbone of data validation in FastAPI.
🧠 Why Do We Need Request Bodies?
Let’s imagine you're building an online registration form for a new user. You need details like name, email, and age. These details are not passed in the URL but rather sent in the body of a POST request.
This is where request bodies and Pydantic models come into play in FastAPI.
🧩 Real-World Analogy: Pydantic is the Bouncer at a Club
Think of your API like a nightclub. You can’t just let anyone in. The bouncer at the door checks if you're:
- Old enough (age)
- On the list (valid email)
- Actually a real person (non-empty name)
Just like that, Pydantic is your API’s gatekeeper — it checks if the incoming request body has the correct structure and data types.
🔧 Step-by-Step: Create a /user
POST Endpoint
We'll create a FastAPI app that accepts a JSON body with user details.
📁 Create a file called user.py
:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 🎯 Step 1: Define your request body schema using Pydantic
class User(BaseModel):
name: str
email: str
age: int
# 🎯 Step 2: Create a POST endpoint to accept the request body
@app.post("/user")
def create_user(user: User):
return {
"message": f"Welcome, {user.name}!",
"email": user.email,
"age": user.age
}
🚀 Test Your Endpoint
🖥️ Start the FastAPI server:
uvicorn user:app --host 0.0.0.0 --port 9002 --reload
🌐 Open your browser and visit the interactive docs:
http://localhost:9002/docs
📤 Try sending this sample JSON:
{
"name": "Utkarsh",
"email": "utkarsh@example.com",
"age": 28
}
Output:
✅ FastAPI will automatically validate the request and return a structured response or helpful error messages.
🧪 Add Validation with Pydantic
Let’s enhance the model with proper validation using EmailStr
, default values, and field constraints.
🔧 Prerequisite: Install email-validator
To use EmailStr
for validating emails, you must install the email-validator
package.
Run this command in your terminal:
pip install pydantic[email]
🔧 Step-by-Step: Create a /user
POST Endpoint
We'll create a FastAPI app that accepts a JSON body with user details.
📁 Create a file called user.py
:
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr, Field
from typing import Optional
app = FastAPI()
class User(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: EmailStr
age: Optional[int] = Field(None, ge=18, le=100)
@app.post("/user")
def create_user(user: User):
return {
"message": f"Welcome, {user.name}!",
"email": user.email,
"age": user.age
}
🔍 Explanation:
-
name
: Required string with a minimum length of 2 and a maximum of 50. -
email
: Must be a valid email address (EmailStr
from Pydantic). -
age
: Optional integer; if provided, it must be between 18 and 100.
🚀 Test Your Endpoint
🖥️ Start the FastAPI server:
uvicorn user:app --host 0.0.0.0 --port 9004 --reload
🌐 Open your browser and visit the interactive docs:
http://localhost:9004/docs
📤 Try sending this sample JSON:
{
"name": "Utkarsh",
"email": "utkarsh@example.com",
"age": 16
}
Output:
🌍 Real-World Example – Feedback API
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr, Field
app = FastAPI()
class Feedback(BaseModel):
name: str
email: EmailStr
message: str = Field(..., min_length=10)
@app.post("/feedback")
def submit_feedback(feedback: Feedback):
return {
"status": "received",
"from": feedback.name,
"email": feedback.email
}
Input:
{
"name": "Utkarsh",
"email": "Utkarsh@email.com",
"message": "Great job with the FastAPI series!"
}
Output:
📦 Nested Models Example – Customer with Address
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Address(BaseModel):
city: str
pincode: int
class Customer(BaseModel):
name: str
address: Address
@app.post("/customer")
def create_customer(customer: Customer):
return {"msg": f"{customer.name} from {customer.address.city} added."}
Input:
{
"name": "Utkarsh",
"address": {
"city": "Mumbai",
"pincode": 110
}
}
Output:
🧠 Recap
Concept | Purpose |
---|---|
BaseModel |
Define and validate data models |
EmailStr |
Validate email format |
Optional |
Make fields optional |
Field() |
Add constraints like min, max, default |
Nested Models | Model complex JSON structures |
🙏 Credits
Huge thanks to the FastAPI Official Documentation by Sebastián Ramírez (@tiangolo) — the best place to learn and explore everything about FastAPI.
👨💻 About Me
Hey there! I’m Utkarsh Rastogi, an AWS Community Builder and passionate cloud-native enthusiast who loves building scalable backend systems and sharing knowledge with the community.
🔗 Connect with me: Utkarsh Rastogi
💬 Share Your Thoughts – I'd Love Your Feedback!
If you enjoyed today's post or learned something new, I'd truly appreciate it if you leave a comment or share your thoughts 👇
Your feedback, questions, or even a quick “🔥 Loved this!” keeps me motivated to continue this journey and share more in the upcoming #FastAPIDaily posts.
✅ What did you find most helpful?
✅ Anything you'd like explained in the next part?
✅ Suggestions for improvement? I’m all ears! 🙌
Let’s grow and learn together — one FastAPI day at a time 🚀