FastAPI

Lesson 03

Response models as contracts

Return response models that expose the public API shape and filter internal fields.

Good Code

api/reviews.py
from fastapi import APIRouter
from pydantic import BaseModel

router = APIRouter()


class ReviewResponse(BaseModel):
    id: int
    title: str
    status: str


@router.get("/reviews/{review_id}", response_model=ReviewResponse)
async def get_review(review_id: int):
    review = await reviews.find(review_id)
    return review

Bad Code

api/reviews.py
from fastapi import APIRouter

router = APIRouter()


@router.get("/reviews/{review_id}")
async def get_review(review_id: int):
    review = await reviews.find(review_id)
    return review.__dict__

Review Notes

What to review

Good Code

The good version declares the public response shape and lets FastAPI serialize only the fields that belong in the contract.

Bad Code

The bad version returns object internals. Private fields, database state, or unexpected attributes can leak into the API.

Takeaways

  • A response model is both documentation and a guardrail for data leaving the service.