
As modern web applications increasingly rely on fast and scalable APIs, developers need frameworks that simplify development without compromising on performance. FastAPI is one such modern Python web framework that’s rapidly gaining popularity for building robust, high-performance REST APIs.
In this comprehensive guide, you’ll learn how to create REST APIs using FastAPI, from basic setup to advanced endpoints, including best practices and real-world use cases.
What is FastAPI?
FastAPI is a modern, asynchronous web framework built on Starlette for the web parts and Pydantic for data validation. It is known for:
- High performance (on par with Node.js and Go)
- Easy-to-use syntax based on Python 3.6+ type hints
- Automatic generation of interactive API docs (Swagger UI & Redoc)
- Built-in request validation and serialization
Why Use FastAPI?
- Speed: Asynchronous support via
async/await
boosts performance. - Type Safety: Type hints are used to auto-generate docs and validate inputs.
- Ease of Use: Minimal boilerplate code compared to Flask or Django.
- Documentation: Built-in OpenAPI and Swagger UI support.
Prerequisites
Before you start, ensure you have the following:
- Python 3.7 or higher installed
- Basic knowledge of Python and REST principles
Install FastAPI and Uvicorn (ASGI server):
pip install fastapi uvicorn
Step 1: Creating Your First FastAPI Application
Let’s begin with a basic “Hello World” example.
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Welcome to FastAPI"}
Run the app with Uvicorn:
uvicorn main:app --reload
Open your browser and visit:
- http://127.0.0.1:8000/ → Main endpoint
- http://127.0.0.1:8000/docs → Swagger UI (Interactive API)
- http://127.0.0.1:8000/redoc → Redoc documentation
Step 2: Creating RESTful Endpoints
Let’s define endpoints for a basic CRUD system managing “items.”
Example Data Model
from pydantic import BaseModel
class Item(BaseModel):
id: int
name: str
description: str = None
price: float
in_stock: bool = True
CRUD Endpoints
from typing import List
items = []
@app.post("/items/", response_model=Item)
def create_item(item: Item):
items.append(item)
return item
@app.get("/items/", response_model=List[Item])
def get_items():
return items
@app.get("/items/{item_id}", response_model=Item)
def get_item(item_id: int):
for item in items:
if item.id == item_id:
return item
return {"error": "Item not found"}
@app.put("/items/{item_id}", response_model=Item)
def update_item(item_id: int, updated_item: Item):
for index, item in enumerate(items):
if item.id == item_id:
items[index] = updated_item
return updated_item
return {"error": "Item not found"}
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
for index, item in enumerate(items):
if item.id == item_id:
del items[index]
return {"message": "Item deleted"}
return {"error": "Item not found"}
Step 3: Validating Query Parameters and Request Data
You can use type hints and Pydantic models to validate inputs.
Query Parameters
@app.get("/search/")
def search_items(keyword: str, max_price: float = None):
results = [item for item in items if keyword.lower() in item.name.lower()]
if max_price:
results = [item for item in results if item.price <= max_price]
return results
Request Body with Validation
Add constraints with Pydantic:
from pydantic import BaseModel, Field
class Item(BaseModel):
id: int
name: str = Field(..., min_length=3, max_length=50)
description: str = Field(default=None, max_length=300)
price: float = Field(..., gt=0)
in_stock: bool = True
Step 4: Dependency Injection
FastAPI supports dependency injection out of the box.
from fastapi import Depends
def common_parameters(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
@app.get("/paginated-items/")
def paginated_items(params: dict = Depends(common_parameters)):
return items[params["skip"]:params["skip"] + params["limit"]]
Step 5: Error Handling
FastAPI makes error handling simple and expressive.
from fastapi import HTTPException
@app.get("/items/{item_id}", response_model=Item)
def get_item(item_id: int):
for item in items:
if item.id == item_id:
return item
raise HTTPException(status_code=404, detail="Item not found")
Step 6: Middleware and CORS Support
Add middleware for logging, headers, etc.
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
Step 7: Organizing the Project Structure
As your app grows, structure it like this:
project/
│
├── app/
│ ├── main.py
│ ├── models.py
│ ├── routes/
│ │ └── items.py
│ └── schemas/
│ └── item.py
│
├── requirements.txt
└── README.md
Use APIRouter
to modularize routes:
# items.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/items/")
def get_items():
return [{"name": "example"}]
Then include it in main.py
:
from app.routes import items
app.include_router(items.router)
Step 8: Testing Your API
Use pytest
and TestClient
from fastapi.testclient
.
from fastapi.testclient import TestClient
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Welcome to FastAPI"}
Step 9: Deploying FastAPI
You can deploy FastAPI apps using:
- Uvicorn with Gunicorn for production: bashCopyEdit
gunicorn -k uvicorn.workers.UvicornWorker app.main:app
- Docker for containerized deployment
- Cloud platforms like AWS Lambda, Azure, GCP, or Heroku
Best Practices
- Use environment variables and
.env
files for secrets - Separate business logic and API routes
- Document your API with Swagger and Redoc
- Handle exceptions with custom error handlers
- Use async functions for non-blocking operations
Final Thoughts
FastAPI makes it incredibly easy to build production-grade REST APIs with minimal code and maximum performance. With its type safety, interactive docs, and built-in async support, it’s quickly becoming the go-to choice for modern API development in Python.
Whether you’re building a small internal tool or a large-scale backend service, FastAPI offers the speed and developer experience to help you move fast and scale confidently.

I’m Shreyash Mhashilkar, an IT professional who loves building user-friendly, scalable digital solutions. Outside of coding, I enjoy researching new places, learning about different cultures, and exploring how technology shapes the way we live and travel. I share my experiences and discoveries to help others explore new places, cultures, and ideas with curiosity and enthusiasm.