Course
FastAPI
50 lessons across 10 modules · 13 classic
Build web APIs with Python, from your first endpoint to production. Each lesson explains one idea in simple steps, with code you can run and the real output. The course is being rewritten module by module; the earlier lessons stay below as “classic” until their new version is ready.
Getting Started
What an API is, why FastAPI, and your first endpoints - running on your own machine
What is an API, and Why FastAPI?
1.1Learn what an API is, how a request and a response look, and why FastAPI is a good way to build one in Python. We build the same small API twice - by hand and with FastAPI - and send both the same requests.
Setup and Your First App
1.2Install FastAPI in a virtual environment, write a five-line app, run it with fastapi dev, and open the automatic docs. Then see auto-reload work - and the four errors almost every beginner meets on day one.
Path Operations and HTTP Methods
1.3Build a small to-do API with all five common HTTP methods - GET, POST, PUT, PATCH and DELETE - and the right status codes. Then test the mistakes: a wrong method, a trailing slash, routes in the wrong order, and a route defined twice.
Path Parameters
1.4Read values from the URL itself - /books/2, /shirts/large, /files/docs/report.pdf - with types, limits and fixed choices. Tested with 26 real requests, including the surprising ones: "007", "+2" and "1_000" all become numbers, and "../" passes straight through.
Query Parameters
1.5Use the part of the URL after the ? - /books?skip=2&limit=2, /search?q=web&genre=web - for options, filters and paging. Make them optional or required, add limits, accept lists, and see what FastAPI silently ignores.
Request Body with Pydantic
1.6Receive JSON from the client and get a checked Python object back: describe the shape once with a Pydantic model, and FastAPI does the rest. Tested with 20 requests - including a typo that silently set a price to 0.0, and the one-line fix.
The Interactive Docs
1.7Turn the automatic docs into clear docs: a title and description, groups (tags), summaries, docstrings, field examples, documented errors and deprecated endpoints. Then use "Try it out" in a real browser - and learn the safe way to hide the docs.
Pydantic & Validation
Describe your data once, and let FastAPI check every request and response
Pydantic Models in Depth
2.1Use Pydantic on its own, outside FastAPI: field types (dates, enums, literals, lists), required vs optional, turning dicts and JSON into models and back, and the error object. Then two surprises: changing a field after creation is not checked - and the two settings that fix it.
Field Rules
2.2Add rules to fields: number limits, text length and patterns, exact money with Decimal, list sizes, cleaned-up text, emails and URLs, defaults made at creation time, and JSON names that differ from Python names. Plus a real bug: a default that broke its own rule and caused a 500 error.
Custom Validators
2.3When Field rules are not enough, write your own checks: clean and check one field with @field_validator, compare fields with @model_validator, and add values computed from other fields. Tested in FastAPI - including a validator that forgot "return" and silently turned a username into None.
Nested Models and Lists
2.4Real data has structure: an order has an address, many order lines and one of several payment types. Build it from models inside models, lists and dicts, read errors that point deep inside ("lines.1.qty"), and let one field choose the right model with a discriminated union.
Response Models
2.5Control what leaves your API: a response model filters out everything else - like the password hash our "leaky" endpoint sent. Use a return type or response_model=, separate In and Out models, drop empty fields, and see what happens when you return data that does not fit.
Responses & Errors
Status codes, clear errors, and every kind of response - JSON, files, forms and cookies
Status Codes
3.1Every response starts with a three-digit number that tells the client what happened. Learn the few codes you need every day - 200, 201, 204, 400, 404, 409, 422 - set them with status_code= or the Response object, and see which ones FastAPI already sends for you.
Errors and HTTPException
3.2Stop a request with HTTPException - from an endpoint or any helper - add headers or a dict detail, raise your own business errors, and write exception handlers so every error in the API has one format. Tested before and after the handlers, including a real bug that gives 500.
Response types
3.3JSON, HTML, plain text, redirects, files and streams
A CSV download
Headers and cookies
3.4Reading and setting headers and cookies
A "remember language" cookie
Forms and file uploads
3.5Form fields and UploadFile
Upload a profile photo
Dependencies
Share code between endpoints with Depends - the most important FastAPI idea after models
What is dependency injection?
4.1Asking for what you need instead of creating it
Pagination used by many endpoints
Depends in practice
4.2Function, class and sub-dependencies
Current user and a database session
Dependencies with yield
4.3Setup and cleanup around a request
Open and close a database session
Router and app dependencies
4.4Running a dependency for many routes at once
An API key check for /admin
Databases
Store data in a real database with SQLModel and SQLAlchemy
Databases and ORMs in 15 minutes
5.1Tables, rows, SQL, and what an ORM does for you
The to-do list as a table
SQLModel setup
5.2Models that are both tables and Pydantic models
A Todo table in SQLite
CRUD with sessions
5.3Create, read, update, delete through a session dependency
The to-do API, now saved to disk
Relationships
5.4One-to-many and many-to-many
Users and their todos
Migrations with Alembic
5.5Changing tables without losing data
Add a due_date column
Async database access
5.6When async sessions help, and how to use them
An async engine with SQLite or Postgres
Auth & Security
Passwords, tokens and permissions - who is calling, and what they may do
Authentication vs authorization
6.1Who you are vs what you may do
A user, an admin and a guest
Login with OAuth2 and JWT
6.3The password flow and signed tokens
POST /token and Bearer tokens
Protecting routes
6.4A current-user dependency, and roles
Only the owner can delete a todo
CORS and security basics
6.5Browsers, origins and safe defaults
Letting your React app call the API
Async, Background Tasks & Middleware
async and await, work after the response, and code that runs around every request
async def or def?
7.1What async really changes, measured
Slow endpoints with and without await
Calling other APIs
7.2httpx, timeouts and retries
A weather API behind your API
Background tasks
7.3Work that runs after the response is sent
Send a welcome email
Lifespan: startup and shutdown
7.5Opening and closing shared resources
Load a model once at startup
WebSockets and streaming
7.6Two-way connections and streamed responses
A live chat
Bigger Apps
Split an app into routers and files, and configure it with settings
APIRouter and project layout
8.1One file per area, with prefixes and tags
users, todos and admin routers
Settings and environment variables
8.2pydantic-settings and .env files
Database URL and secret key
Logging
8.3Useful logs for every request
A request id in every log line
API versioning
8.4Changing an API without breaking clients
/v1 and /v2 side by side
Testing
Prove your API works - and keeps working - with pytest
Testing with TestClient
9.1Requests without a server, checked with pytest
Tests for the to-do API
Overriding dependencies
9.2Fake users and fake databases in tests
Test a protected route
Testing with a database
9.3A fresh test database for each test
SQLite in memory
Async tests
9.4httpx.AsyncClient and pytest-asyncio
Testing an async endpoint
Production & Deployment
Run it for real users: workers, Docker, HTTPS and monitoring
fastapi run and workers
10.1Production mode, processes and ports
4 workers on one machine
Docker
10.2A small, safe image for your API
A Dockerfile for the to-do API
Behind a proxy with HTTPS
10.3Nginx or a cloud load balancer in front
Forwarded headers and root_path
Health checks and monitoring
10.4Knowing your API is up and fast
/health and request timing
The earlier version of this course
Shorter reference-style lessons. Each one stays here until the new course covers its topic.
Responses
Using response_model to drop fields you do not want to send, setting the status code, and picking a response type.
Classic · HTTP layerHeaders & cookies
Read the headers and cookies the caller sent, and set your own on the reply.
Classic · HTTP layerFiles & forms
Receiving uploaded files, checking them before you keep them, and reading normal form fields.
Classic · HTTP layerDependencies
Depends() for shared setup, yield when something must be cleaned up afterwards, and where to attach each one.
Classic · ArchitectureMiddleware
CORS so a browser app can call you, your own logging and timing wrappers, and the security ones that ship with FastAPI.
Classic · ArchitectureLifecycle
Open shared resources at startup and close them at shutdown.
Classic · ArchitectureAuth & security
Logging in with a JWT token, a dependency that hands you the current user, role checks, and API keys.
Classic · AdvancedDatabase
Talking to PostgreSQL without blocking: the engine, sessions, and create/read/update/delete.
Classic · AdvancedAsync patterns
When to write async def and when plain def, work done after the reply, task queues, WebSockets, and server-sent events.
Classic · AdvancedRouters
Split your routes into separate APIRouter files and keep old versions working.
Classic · AdvancedTesting
TestClient for quick tests, httpx for async ones, and swapping a dependency for a fake.
Classic · AdvancedProduction
Settings read from the environment, limits on how often someone can call you, and health check endpoints.
Classic · AdvancedCheatsheet
Commands to install and run, the route decorators, and the parameter types.
Classic · Reference