Last time, in Body - Nested Models, our Blog grew tags, an author, and comments. It is a rich model now. But open the /docs page and the example body is just empty placeholders. Anyone testing the endpoint has to guess what good input looks like. 🤔
FastAPI lets you ship sample data right alongside your model, so the docs show a ready-to-send example. Here are three ways to do it, shortest first.
Examples on the whole model
Add a model_config with json_schema_extra and drop in one or more example bodies.
from typing import Optionalfrom fastapi import FastAPIfrom pydantic import BaseModelapp = FastAPI()class Blog(BaseModel): title: str content: str rating: Optional[float] = None model_config = { "json_schema_extra": { "examples": [ { "title": "My First Blog", "content": "Hello FastAPI!", "rating": 4.5, } ] } }@app.post("/blog")async def create_blog(blog: Blog): return blogLet's review:
examplesis a list, so you can hand over more than one sample if you like.This is pure documentation. It does not validate anything, it just pre-fills the example in
/docs.The example lives inside the model, so every endpoint using
Bloggets it for free.
Examples per field
Prefer to attach a sample to each field? Use Field(examples=[...]), the same Field from the Body - Fields post.
from typing import Optionalfrom fastapi import FastAPIfrom pydantic import BaseModel, Fieldapp = FastAPI()class Blog(BaseModel): title: str = Field(examples=["My First Blog"]) content: str = Field(examples=["Hello FastAPI!"]) rating: Optional[float] = Field(default=None, examples=[4.5])@app.post("/blog")async def create_blog(blog: Blog): return blogLet's review:
Each field carries its own
exampleslist.FastAPI stitches them together into one example body in the docs.
Validation rules and examples can sit on the same
Field, side by side.
Examples on Body, with descriptions
Want richer examples that explain themselves in the docs UI? Use openapi_examples on Body(). Each entry gets a summary and a value.
from typing import Annotatedfrom fastapi import Body, FastAPIfrom pydantic import BaseModelapp = FastAPI()class Blog(BaseModel): title: str content: str@app.post("/blog")async def create_blog( blog: Annotated[ Blog, Body( openapi_examples={ "normal": { "summary": "A typical blog", "value": {"title": "My First Blog", "content": "Hello FastAPI!"}, }, "empty": { "summary": "Missing content fails validation", "value": {"title": "Oops"}, }, } ), ],): return blogLet's review:
openapi_examplesis a dict. Each key names an example the user can pick from a dropdown in/docs.summarylabels the example, andvalueis the actual body sent.This is the only option that lets the docs UI switch between several named examples cleanly.
Gotcha: Examples are for documentation, not validation. An example with bad data will still show up in /docs, but FastAPI validates the real request against your model, not against the example. So a pretty example does not let invalid input through. 😁
Up next: Extra Data Types. So far we have used str, int, float, and bool. But FastAPI also understands richer types like datetime, UUID, and timedelta, with validation and conversion built in. We will put those to work next. ⏭️⏭️
