Skip to content
Free workshop · 12 chapters · about 3 hours

Build a real API with FastAPI.

Step by step, you build Shelf, a small reading-list API that is ready for the real world: validation, a database, helpful errors, auth, tests, logs and a Docker image. No magic, just Python with type hints.

Meet Shelf.

Want to read it, reading it, done. Shelf keeps the list. Reads are open; writes need a key. Small enough for one afternoon, real enough to deploy.

  • GET/booksList books, with filters and pages
  • GET/books/{book_id}One book
  • POST/booksAdd a bookkey
  • PATCH/books/{book_id}Change only what you sendkey
  • DELETE/books/{book_id}Remove a bookkey
  • POST/books/{book_id}/finishMark done, rate, log itkey
  • GET/statsCounts and average rating
  • GET/activityWhat happened recently
  • GET/readyCan it serve traffic?
Request
POST /books
X-API-Key: dev-key-change-me

{ "title": "Piranesi", "author": "Susanna Clarke", "tags": ["Fantasy"] }
Response201 Created
{
  "id": 1,
  "title": "Piranesi",
  "author": "Susanna Clarke",
  "status": "want",
  "rating": null,
  "tags": ["fantasy"]
}

Real requests and responses from the API you will build, trimmed for space.

Everything a real API needs, nothing extra.

Twelve short chapters.

See them all
  1. 01Why FastAPI, and what we build10 minutes
  2. 02Set up and run it10 minutes
  3. 03Routes, path and query parameters15 minutes
  4. 04Pydantic models and validation20 minutes
  5. 05A real database with SQLAlchemy20 minutes
  6. 06Dependencies and settings15 minutes
  7. 07Errors that help15 minutes
  8. 08Protect writes with an API key15 minutes
  9. 09Test it with pytest20 minutes
  10. 10Middleware, request ids and logs15 minutes
  11. 11Background tasks and async15 minutes
  12. 12Ship it20 minutes

Running in a minute.

You need uv and git. uv installs Python 3.13 and the exact package versions for you. Then open the live docs and click around.

Full setup in chapter 02
bash
git clone https://github.com/jars-demo/fastapi-demo.git
cd fastapi-demo/api
uv sync
uv run uvicorn app.main:app --reload
# open http://127.0.0.1:8000/docs