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:
UUID: a universally unique identifier, common as a database ID. Sent and received as a string.datetime.datetime: a full timestamp. Represented as an ISO 8601 string like2026-06-29T15:53:00.datetime.date: just a date, like2026-06-29.datetime.time: just a time, like14:23:55.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 likePT5M.
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.
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 blogLet's review:
idis aUUID. Send a malformed string and FastAPI rejects it before your code runs.published_onis adate. The client sends"2026-06-29"and you get a real Pythondateobject back.read_timeis an optionaltimedelta. The client sends a number of seconds, like300, and you get a realtimedeltainside 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:
startis adatetimeanddelayis atimedelta, both pulled from the body withBody()since they are singular values.start + delayis normal Python date arithmetic. No parsing, no manual conversion.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.
