FastAPI Interactive Docs

Extra Data Types

In the last post, Declare Request Example Data, we made our docs friendlier with sample values. Every field we have used so far has been a str, int, float, or bool. Those cover a lot, but real blogs need more: a unique ID, a publish timestamp, maybe a "read time" duration. 🤔

Good news: FastAPI understands richer types out of the box, and you get the same perks as before, validation, conversion, and auto-docs. Let's meet a few.

The types you will reach for most

A quick tour of the handy ones:

  1. UUID: a universally unique identifier, common as a database ID. Sent and received as a string.

  2. datetime.datetime: a full timestamp. Represented as an ISO 8601 string like 2026-06-29T15:53:00.

  3. datetime.date: just a date, like 2026-06-29.

  4. datetime.time: just a time, like 14:23:55.

  5. datetime.timedelta: a duration. You send it as a number of seconds, and in current Pydantic it comes back in the response as an ISO 8601 duration string like PT5M.

There are more, like Decimal, bytes, and frozenset, but these five are the ones you will use day to day.

Putting them on the Blog model

Let's give our Blog a real ID and some date fields.

main.py
from datetime import date, timedeltafrom typing import Optionalfrom uuid import UUIDfrom fastapi import FastAPIfrom pydantic import BaseModelapp = FastAPI()class Blog(BaseModel):    id: UUID    title: str    content: str    published_on: date    read_time: Optional[timedelta] = None@app.post("/blog")async def create_blog(blog: Blog):    return blog

Let's review:

  1. id is a UUID. Send a malformed string and FastAPI rejects it before your code runs.

  2. published_on is a date. The client sends "2026-06-29" and you get a real Python date object back.

  3. read_time is an optional timedelta. The client sends a number of seconds, like 300, and you get a real timedelta inside your function.

So FastAPI happily accepts a body like this:

json

{    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",    "title": "My First Blog",    "content": "Hello FastAPI!",    "published_on": "2026-06-29",    "read_time": 300}

These are real objects, so you can do math

The best part: inside your function these are not strings, they are the actual Python types. That means you can do date math directly.

python

from datetime import datetime, timedeltafrom typing import Annotatedfrom fastapi import Body, FastAPIapp = FastAPI()@app.post("/blog/schedule")async def schedule_blog(    start: Annotated[datetime, Body()],    delay: Annotated[timedelta, Body()],):    publish_at = start + delay    return {"start": start, "delay": delay, "publish_at": publish_at}

Let's review:

  1. start is a datetime and delay is a timedelta, both pulled from the body with Body() since they are singular values.

  2. start + delay is normal Python date arithmetic. No parsing, no manual conversion.

  3. FastAPI converts the result back to JSON automatically when it returns.

Gotcha: you send a timedelta as a plain number of seconds, so read_time: 300 means five minutes. Heads up that the response renders it back as an ISO 8601 duration string like PT5M in current Pydantic, not as the number you sent. Same duration, different shape on the way out. 😁

Up next: Cookie Parameters. We have pulled data from the path, the query, and the body. Next we will read values straight from cookies, which is how things like session tokens usually ride along with a request. See you there. Byeeee.

Practice Lab: