Day 3: Request Body & Pydantic Explained with Real-World Context
Utkarsh Rastogi

Utkarsh Rastogi @awslearnerdaily

About: Cloud Developer | AWS Community Builder | I write about AI, serverless, DevOps & real-world cloud projects using AWS, Bedrock, LangChain & more to help others learn and build smarter solutions.

Location:
India
Joined:
Mar 22, 2025

Day 3: Request Body & Pydantic Explained with Real-World Context

Publish Date: Jun 5
2 2

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
    }
Enter fullscreen mode Exit fullscreen mode

🚀 Test Your Endpoint

🖥️ Start the FastAPI server:

uvicorn user:app --host 0.0.0.0 --port 9002 --reload
Enter fullscreen mode Exit fullscreen mode

🌐 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
}
Enter fullscreen mode Exit fullscreen mode

Input

Output:

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]
Enter fullscreen mode Exit fullscreen mode

🔧 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
    }
Enter fullscreen mode Exit fullscreen mode

🔍 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
Enter fullscreen mode Exit fullscreen mode

🌐 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
}
Enter fullscreen mode Exit fullscreen mode

Input Age

Output:

Output Error


🌍 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
    }
Enter fullscreen mode Exit fullscreen mode

Input:

{
  "name": "Utkarsh",
  "email": "Utkarsh@email.com",
  "message": "Great job with the FastAPI series!"
}

Enter fullscreen mode Exit fullscreen mode

Output:

Job


📦 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."}

Enter fullscreen mode Exit fullscreen mode

Input:

{
  "name": "Utkarsh",
  "address": {
    "city": "Mumbai",
    "pincode": 110
  }
}

Enter fullscreen mode Exit fullscreen mode

Output:

Feefdback


🧠 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 🚀


Comments 2 total

Add comment