FastAPI Interactive Docs

Declare Request Example Data

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.

main.py
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 blog

Let's review:

  1. examples is a list, so you can hand over more than one sample if you like.

  2. This is pure documentation. It does not validate anything, it just pre-fills the example in /docs.

  3. The example lives inside the model, so every endpoint using Blog gets 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.

main.py
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 blog

Let's review:

  1. Each field carries its own examples list.

  2. FastAPI stitches them together into one example body in the docs.

  3. 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.

main.py
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 blog

Let's review:

  1. openapi_examples is a dict. Each key names an example the user can pick from a dropdown in /docs.

  2. summary labels the example, and value is the actual body sent.

  3. 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. ⏭️⏭️

Practice Lab: