Getting Started with FastAPI
Learn how to install FastAPI, create your first API, and understand the basic concepts that make FastAPI powerful and easy to use.
Installation
Prerequisites
- Python 3.7 or higher
- pip (Python package installer)
- Virtual environment (recommended)
Basic Installation
Install FastAPI and an ASGI server (Uvicorn) to run your application:
pip install fastapi
pip install "uvicorn[standard]"
Optional Dependencies
For specific features, you may want to install additional packages:
# For email validation and other Pydantic features
pip install "pydantic[email]"
# For serving static files and templating
pip install jinja2 python-multipart
# For testing
pip install httpx pytest
Complete Installation
For a full development setup with all optional dependencies:
pip install "fastapi[all]"
This includes Uvicorn with all features, Pydantic with validation, and testing dependencies.
Your First FastAPI Application
Hello World
Create a file called main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
Running the Application
Start the development server:
uvicorn main:app --reload
Parameters explained:
main: the Python file (main.py)app: the FastAPI instance in main.py--reload: auto-restart on code changes (development only)
Testing Your API
Open your browser and navigate to:
- API endpoint: http://127.0.0.1:8000
- Interactive docs (Swagger UI): http://127.0.0.1:8000/docs
- Alternative docs (ReDoc): http://127.0.0.1:8000/redoc
Path Operations
Multiple Endpoints
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
@app.post("/items")
def create_item(name: str, price: float):
return {"name": name, "price": price}
HTTP Methods
FastAPI supports all standard HTTP methods:
@app.get("/items") # Read items
@app.post("/items") # Create item
@app.put("/items/{id}") # Update entire item
@app.patch("/items/{id}") # Partial update
@app.delete("/items/{id}") # Delete item
Path Parameters
Define variable parts of the URL path:
@app.get("/users/{user_id}")
def read_user(user_id: int):
return {"user_id": user_id}
@app.get("/users/{user_id}/items/{item_id}")
def read_user_item(user_id: int, item_id: str):
return {"user_id": user_id, "item_id": item_id}
Type Validation
FastAPI automatically validates path parameter types:
@app.get("/items/{item_id}")
def read_item(item_id: int):
# If item_id is not an integer, FastAPI returns 422 error
return {"item_id": item_id}
Predefined Values (Enums)
Use Python Enums for predefined path values:
from enum import Enum
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model": model_name, "message": "LeCNN all the images"}
return {"model": model_name, "message": "Have some residuals"}
Query Parameters
Add optional or required query parameters:
from typing import Optional
@app.get("/items")
def read_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
@app.get("/search")
def search(q: Optional[str] = None, page: int = 1):
if q:
return {"query": q, "page": page}
return {"message": "No query provided", "page": page}
Multiple Path and Query Parameters
@app.get("/users/{user_id}/items")
def read_user_items(
user_id: int,
skip: int = 0,
limit: int = 10,
q: Optional[str] = None
):
results = {"user_id": user_id, "skip": skip, "limit": limit}
if q:
results["q"] = q
return results
Request Body
Use Pydantic models for request bodies:
from pydantic import BaseModel
from typing import Optional
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.post("/items")
def create_item(item: Item):
item_dict = item.dict()
if item.tax:
price_with_tax = item.price + item.tax
item_dict["price_with_tax"] = price_with_tax
return item_dict
Request + Path + Query Parameters
Combine all parameter types:
@app.put("/items/{item_id}")
def update_item(
item_id: int, # Path parameter
item: Item, # Request body
q: Optional[str] = None # Query parameter
):
result = {"item_id": item_id, **item.dict()}
if q:
result["q"] = q
return result
Automatic Documentation
FastAPI automatically generates interactive API documentation:
Swagger UI
Access at /docs - provides:
- Interactive API testing
- Request/response examples
- Parameter descriptions
- Model schemas
ReDoc
Access at /redoc - provides:
- Clean, organized documentation
- Searchable API reference
- Detailed model documentation
- Three-panel layout
OpenAPI Schema
Raw OpenAPI schema available at /openapi.json:
# Access programmatically
import requests
response = requests.get("http://localhost:8000/openapi.json")
schema = response.json()
Application Configuration
Metadata and Documentation
Configure your API metadata:
from fastapi import FastAPI
app = FastAPI(
title="My API",
description="A comprehensive API for managing items",
version="1.0.0",
terms_of_service="http://example.com/terms/",
contact={
"name": "API Support",
"email": "support@example.com",
},
license_info={
"name": "MIT",
"url": "https://opensource.org/licenses/MIT",
},
)
Tags for Organization
Group related endpoints with tags:
@app.get("/users/", tags=["users"])
def read_users():
return [{"name": "Alice"}, {"name": "Bob"}]
@app.get("/items/", tags=["items"])
def read_items():
return [{"name": "Item 1"}, {"name": "Item 2"}]
Response Handling
Custom Status Codes
from fastapi import status
@app.post("/items", status_code=status.HTTP_201_CREATED)
def create_item(item: Item):
return item
@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_item(item_id: int):
return None
Response Models
Define the structure of responses:
class ItemResponse(BaseModel):
name: str
price: float
@app.post("/items", response_model=ItemResponse)
def create_item(item: Item):
# Even if Item has more fields, only ItemResponse fields are returned
return item
Error Handling
HTTP Exceptions
from fastapi import HTTPException
@app.get("/items/{item_id}")
def read_item(item_id: int):
if item_id not in items_db:
raise HTTPException(
status_code=404,
detail="Item not found"
)
return items_db[item_id]
Custom Exception Handlers
from fastapi import Request
from fastapi.responses import JSONResponse
class CustomException(Exception):
def __init__(self, name: str):
self.name = name
@app.exception_handler(CustomException)
def custom_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
status_code=418,
content={"message": f"Oops! {exc.name} did something wrong."}
)
Project Structure
For larger applications, organize your code:
myapp/
├── main.py
├── models/
│ ├── __init__.py
│ └── item.py
├── routers/
│ ├── __init__.py
│ ├── users.py
│ └── items.py
└── dependencies.py
Using Routers
routers/items.py:
from fastapi import APIRouter
router = APIRouter(
prefix="/items",
tags=["items"]
)
@router.get("/")
def read_items():
return [{"name": "Item 1"}]
@router.get("/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
main.py:
from fastapi import FastAPI
from routers import items, users
app = FastAPI()
app.include_router(items.router)
app.include_router(users.router)
Development Tips
Hot Reload
Use --reload during development for automatic reloading:
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Debug Mode
Enable debug logging:
import logging
logging.basicConfig(level=logging.DEBUG)
IDE Support
FastAPI works great with:
- VS Code: Python extension + Pylance for type checking
- PyCharm: Professional edition has excellent FastAPI support
- Vim/Neovim: with Python LSP (pyright or pylsp)
Next Steps
Now that you understand the basics:
- Request Handling: Learn advanced request validation and parsing
- Response Models: Master response schemas and serialization
- Dependencies: Understand FastAPI's powerful dependency injection
- Database Integration: Connect to databases with SQLAlchemy
- Authentication: Implement OAuth2, JWT, and security features
- Testing: Write comprehensive tests for your API
- Deployment: Deploy to production with proper configuration
Common Patterns
Health Check Endpoint
@app.get("/health")
def health_check():
return {"status": "healthy"}
Versioned API
@app.get("/v1/items")
def read_items_v1():
return [{"name": "Item 1"}]
@app.get("/v2/items")
def read_items_v2():
return [{"id": 1, "name": "Item 1", "new_field": "value"}]
CORS Configuration
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
You're now ready to build FastAPI applications! Start with simple endpoints and gradually add more features as you become comfortable with the framework.