Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 4 min read

FastAPI for AI Engineers - Part 4: Stop Bad Data Before It Breaks Your API (Pydantic and Data Validation)

In the previous article, we connected our FastAPI application to a database using SQLite and SQLAlchemy. We also used classes like: class StudentCreate(BaseModel): name: str department: str cgpa: float

FastAPI for AI Engineers - Part 4: Stop Bad Data Before It Breaks Your API (Pydantic and Data Validation)

In the previous article, we connected our FastAPI application to a database using SQLite and SQLAlchemy.

We also used classes like:

class StudentCreate(BaseModel):
    name: str
    department: str
    cgpa: float

without fully understanding what was happening behind the scenes.

Today, we'll fix that.

If you haven't read it check it out:

Why Do We Need Data Validation?

Imagine you're building a weather application.

A user asks:

What is the temperature in Chennai?

A valid response might be:

35

or

35Β°C

But what if the API returns:

Sunny

This is clearly wrong.

Temperature should be represented as a number.

Even if the value itself is inaccurate, we still know that temperature must be numeric.

This is where validation becomes important.

Validation allows us to define rules about what data is acceptable before it enters our application.

For example:

  • Temperature should be numeric
  • Age cannot be negative
  • CGPA should be between 0 and 10
  • Email addresses should follow a valid format

Without validation, applications can receive invalid data and behave unexpectedly.

The Problem Without Validation

Consider a student registration API.

@app.post("/student")
def create_student(student):
    return student

A user could send:

{
    "name": "Ananya",
    "cgpa": "Excellent"
}

The API would accept it.

But a CGPA should be a number, not text.

As applications grow, manually checking every field becomes difficult.

We need a better solution.

Enter Pydantic

Pydantic is a Python library used for data validation.

FastAPI uses Pydantic extensively behind the scenes.

Instead of manually validating data, we define a schema.

from pydantic import BaseModel

class Student(BaseModel):
    name: str
    cgpa: float

Now FastAPI knows:

  • name must be a string
  • cgpa must be a floating-point number

Whenever data arrives, FastAPI automatically validates it.

Your First Pydantic Model

from pydantic import BaseModel

class Student(BaseModel):
    name: str
    department: str
    cgpa: float

Think of this model as a blueprint.

Any incoming request must follow this structure.

Valid Request

{
    "name": "Ananya",
    "department": "CSE",
    "cgpa": 8.9
}

Invalid Request

{
    "name": "Ananya",
    "department": "CSE",
    "cgpa": "Excellent"
}

FastAPI will reject the request automatically.

Using Pydantic with FastAPI

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Student(BaseModel):
    name: str
    department: str
    cgpa: float

@app.post("/student")
def create_student(student: Student):
    return student

Notice this line:

student: Student

FastAPI now expects the incoming request body to match the Student schema.

Understanding Validation Errors

Suppose we send:

{
    "name": "Ananya",
    "department": "CSE",
    "cgpa": "Excellent"
}

FastAPI returns a validation error before the request reaches our route.

You'll see an error similar to:

{
    "detail": [
        {
            "type": "float_parsing",
            "msg": "Input should be a valid number"
        }
    ]
}

Instead of failing silently, FastAPI clearly tells us what went wrong.

Adding Constraints with Field()

Validating types is useful.

But sometimes we need stricter rules.

For example:

  • CGPA should be between 0 and 10
  • Name should have a minimum length
  • Age should always be positive

Pydantic provides Field() for this purpose.

from pydantic import BaseModel, Field

class Student(BaseModel):

    name: str = Field(
        min_length=2,
        max_length=50
    )

    cgpa: float = Field(
        gt=0,
        lt=10
    )

Understanding the Constraints

cgpa: float = Field(gt=0, lt=10)

This means:

CGPA > 0
CGPA < 10

Valid Request

{
    "name": "Ananya",
    "cgpa": 8.9
}

Invalid Request

{
    "name": "Ananya",
    "cgpa": 15
}

FastAPI immediately rejects the request.

Optional Fields

Sometimes fields are not mandatory.

For example, a student may not have a department assigned yet.

from typing import Optional
from pydantic import BaseModel

class Student(BaseModel):

    name: str
    department: Optional[str] = None

Now the department field becomes optional.

Valid Request

{
    "name": "Ananya"
}

Also Valid

{
    "name": "Ananya",
    "department": "CSE"
}

Request Models vs Database Models

One question many beginners ask is:

Why do we need both schemas.py and models.py?

Let's understand the difference.

SQLAlchemy Model

class Student(Base):

    __tablename__ = "students"

    id = Column(Integer, primary_key=True)
    name = Column(String)
    cgpa = Column(Float)

This defines how data is stored in the database.

Pydantic Model

class StudentCreate(BaseModel):
    name: str
    cgpa: float

This defines how data enters our API.

Think of it this way:

Database Structure
        β‰ 
API Structure

They may look similar, but they serve different purposes.

Response Models

Pydantic can also control what data is returned from an API.

class StudentResponse(BaseModel):
    id: int
    name: str
    cgpa: float
@app.get(
    "/student/{id}",
    response_model=StudentResponse
)
def get_student(id: int):
    ...

This ensures the response always follows a consistent structure.

Why Pydantic Matters for AI Applications

Suppose you're building an LLM API.

Expected request:

{
    "prompt": "Explain FastAPI",
    "temperature": 0.7,
    "max_tokens": 500
}

Without validation, a user could send:

{
    "prompt": "Explain FastAPI",
    "temperature": "very creative",
    "max_tokens": "a lot"
}

and your application would have to deal with invalid data.

Pydantic prevents invalid requests from ever reaching your business logic.

This becomes especially important when building:

  • AI chatbots
  • RAG applications
  • Agentic systems
  • Model inference APIs
  • Multi-agent workflows

How Validation Fits into the Request Lifecycle

Client Request
      β”‚
      β–Ό
Pydantic Validation
      β”‚
      β–Ό
FastAPI Route
      β”‚
      β–Ό
Business Logic
      β”‚
      β–Ό
Database / LLM

Pydantic acts as the first line of defense.

Only valid data reaches the rest of the application.

Conclusion

Pydantic is one of the reasons FastAPI has become so popular. It allows us to build APIs that are safer, more predictable, and easier to maintain.

In the next article, we'll move into Authentication and Authorization and learn how to protect our APIs from unauthorized access.

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.