AiTechWorlds
AiTechWorlds
University learning companion
Python Complete Course 2026 · Building REST APIs with FastAPI
A small product team needs to apply “Building REST APIs with FastAPI” to a feature that real people depend on. Define the problem, state the assumptions, work through one concrete example, and decide how the team would test the result and recognise failure.
Use this course-level map to place “Building REST APIs with FastAPI” in the larger system. It complements—not replaces—a topic-specific worked diagram.
FastAPI is a Python web framework for building production ready REST APIs. Think of it as a restaurant order form that checks your handwriting before the kitchen ever sees it FastAPI validates every request against your Python type hints and rejects bad input automatically, before your code has to worry about it. It runs on async Python, and it generates interactive API documentation automatically. In benchmarks, it outperforms Flask and Django REST Framework.
# pip install fastapi uvicorn[standard] pydantic
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel, Field
from typing import Optional, List
import uvicorn
app = FastAPI(
title="My API",
description="A sample FastAPI application",
version="1.0.0"
)
# GET endpoint
@app.get("/")
async def root():
return {"message": "Hello, World!"}
@app.get("/health")
def health_check():
return {"status": "healthy"}
# Run the server
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
# Access at: http://localhost:8000
# Interactive docs: http://localhost:8000/docs
# Alternative docs: http://localhost:8000/redoc@app.get("/users/{user_id}")
async def get_user(user_id: int): # Type hint validates and converts
# FastAPI returns 422 if user_id isn't a valid integer
return {"user_id": user_id}
@app.get("/items/{item_id}")
async def get_item(
item_id: int,
q: Optional[str] = None, # Optional query param
limit: int = 10, # Default value
offset: int = 0
):
result = {"item_id": item_id, "limit": limit, "offset": offset}
if q:
result["query"] = q
return resultfrom pydantic import BaseModel, Field, EmailStr, validator
from typing import Optional
from datetime import datetime
class UserCreate(BaseModel):
username: str = Field(..., min_length=3, max_length=50, pattern="^[a-zA-Z0-9_]+$")
email: EmailStr # pip install email-validator
full_name: str = Field(..., min_length=2)
age: Optional[int] = Field(None, ge=0, le=150)
@validator('username')
def username_lowercase(cls, v):
return v.lower()
class UserResponse(BaseModel):
id: int
username: str
email: str
full_name: str
created_at: datetime
class Config:
from_attributes = True # Allow creating from ORM objects
# In-memory database (in production, use a real DB)
fake_db: dict[int, dict] = {}
next_id = 1
@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
global next_id
new_user = {
"id": next_id,
**user.model_dump(),
"created_at": datetime.utcnow()
}
fake_db[next_id] = new_user
next_id += 1
return new_user
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
if user_id not in fake_db:
raise HTTPException(status_code=404, detail=f"User {user_id} not found")
return fake_db[user_id]
@app.get("/users", response_model=List[UserResponse])
async def list_users(skip: int = 0, limit: int = 10):
users = list(fake_db.values())
return users[skip : skip + limit]
@app.delete("/users/{user_id}", status_code=204)
async def delete_user(user_id: int):
if user_id not in fake_db:
raise HTTPException(status_code=404, detail="User not found")
del fake_db[user_id]from fastapi import Depends
from functools import lru_cache
# Configuration dependency
class Settings:
app_name: str = "My App"
database_url: str = "sqlite:///./app.db"
api_key: str = "secret"
@lru_cache
def get_settings() -> Settings:
return Settings()
# Authentication dependency
async def get_current_user(
token: str,
settings: Settings = Depends(get_settings)
):
if token != settings.api_key:
raise HTTPException(
status_code=401,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"}
)
return {"username": "alice"}
# Use dependencies in endpoints
@app.get("/protected")
async def protected_route(current_user: dict = Depends(get_current_user)):
return {"message": f"Hello, {current_user['username']}!"}from fastapi import BackgroundTasks
import smtplib
from email.message import EmailMessage
def send_welcome_email(email: str, username: str):
"""Runs in background — doesn't block the response."""
# Simulate sending email
print(f"Sending welcome email to {email}...")
import time
time.sleep(2)
print(f"Email sent to {email}")
@app.post("/register")
async def register(user: UserCreate, background_tasks: BackgroundTasks):
# Create user immediately
new_user = create_user_in_db(user)
# Send email in background — response returns immediately
background_tasks.add_task(
send_welcome_email,
email=user.email,
username=user.username
)
return {"message": "User created", "user_id": new_user["id"]}from fastapi.middleware.cors import CORSMiddleware
import time
import logging
logger = logging.getLogger(__name__)
# CORS — allow frontend to call your API
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "https://yourdomain.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Request logging middleware
@app.middleware("http")
async def log_requests(request, call_next):
start = time.time()
response = await call_next(request)
duration = time.time() - start
logger.info(
f"{request.method} {request.url.path} "
f"→ {response.status_code} in {duration:.3f}s"
)
return responsefrom fastapi import Request
from fastapi.responses import JSONResponse
class DatabaseError(Exception):
pass
@app.exception_handler(DatabaseError)
async def database_error_handler(request: Request, exc: DatabaseError):
return JSONResponse(
status_code=503,
content={"detail": "Database unavailable", "error": str(exc)}
)
@app.exception_handler(404)
async def not_found_handler(request: Request, exc):
return JSONResponse(
status_code=404,
content={"detail": f"Route {request.url.path} not found"}
)# routers/users.py
from fastapi import APIRouter
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/")
async def list_users():
return []
@router.post("/")
async def create_user():
return {}
# main.py
from routers import users, products, orders
app.include_router(users.router)
app.include_router(products.router, prefix="/v1")
app.include_router(orders.router)Run your API: uvicorn main:app --reload FastAPI's auto generated /docs page gives you an interactive playground to test every endpoint instantly.
Next lesson: Web Scraping with BeautifulSoup extracting data from websites.
University learning companion
Python Complete Course 2026 · Building REST APIs with FastAPI
Complete the steps without looking at the answer first; record evidence rather than only a final result.
These are primary or established learning references for this subject. Check the relevant chapter or specification for the exact topic and version.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises