Request & Response Models
FastAPI uses Pydantic 2 models to validate requests and shape responses at the HTTP boundary.
Search across all documentation pages
FastAPI uses Pydantic 2 models to validate requests and shape responses at the HTTP boundary.
Quick-reference recipe card - copy-paste ready.
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class ItemCreate(BaseModel):
name: str = Field(min_length=1)
price: float = Field(gt=0)
class ItemRead(BaseModel):
id: int
name: str
price: float
@app.post('/items', response_model=ItemRead, status_code=201)
def create_item(payload: ItemCreate) -> ItemRead:
return ItemRead(id=1, **payload.model_dump())When to reach for this:
from datetime import datetime
from fastapi import FastAPI, Query
from pydantic import BaseModel, ConfigDict, Field, field_validator
app = FastAPI()
class Page(BaseModel):
page: int = Field(1, ge=1)
size: int = Field(20, ge=1, le=100)
class ArticleIn(BaseModel):
title: str
tags: list[str] = Field(default_factory=list)
@field_validator('tags')
@classmethod
def norm(cls, v):
return sorted({t.strip().lower() for t in v})
class ArticleOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
title: str
tags: list[str]
created_at: datetime
@app.get('/articles', response_model=list[ArticleOut])
def list_articles(p: Page = Query()) -> list[ArticleOut]:
return [ArticleOut(id=1, title='Demo', tags=['api'], created_at=datetime.now())]What this demonstrates:
response_model filters output fields for clients and OpenAPI.model_dump(mode='json') for explicit serialization.# Reject unknown keys at the boundary
class StrictIn(BaseModel):
model_config = ConfigDict(extra='forbid')| Alternative | Use When | Don't Use When |
|---|---|---|
| Framework X native pattern | You are already standardized on that stack | You need OpenAPI-first async APIs |
| Serverless functions | Low traffic bursty workloads | Long-lived connections or WebSockets |
| GraphQL | Clients need flexible field selection | Simple CRUD with strong caching |
Reach for it when the patterns on this page match your integration or design constraint.
Skipping validation or error handling at the boundary and pushing complexity into handlers.
Use framework test clients with dependency overrides and assert status codes and JSON bodies.
Yes when you use async-compatible drivers and avoid blocking calls in async routes.
Models validate at the edge; services should trust typed objects inside.
Routes parse and authorize; services implement business rules and persistence.
Map domain errors to HTTP exceptions or a shared error schema.
Yes - lock FastAPI, Django, Flask, and drivers in production images.
Export OpenAPI and keep response models aligned with real payloads.
Follow the Related links at the bottom of this page.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026