How to Build a REST API in 10 Minutes with FastAPI (2025 Guide)
If you've been putting off building that backend API because you thought it would take days β think again. With FastAPI, you can go from zero to a fully functional REST API in under 10 minutes.
I've built dozens of APIs, and FastAPI is hands-down the fastest way to get a production-ready backend running. Here's exactly how to do it.
Why FastAPI (Not Flask or Django)?
- Automatic docs β Swagger UI and ReDoc are built-in. No extra setup.
- Type hints = validation β Pydantic handles request/response validation automatically.
- Async by default β Built on Starlette, it handles async like a champ.
- Fast performance β One of the fastest Python frameworks (comparable to Go's net/http).
Step 1: Install & Setup
mkdir my-api && cd my-api
python -m venv venv
source venv/bin/activate # or venv\Scripts\activate on Windows
pip install fastapi uvicorn
Step 2: Write the Code
Create a file called main.py:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional, List
app = FastAPI(title="My Awesome API", version="1.0.0")
# Data model
class Item(BaseModel):
name: str
price: float
description: Optional[str] = None
in_stock: bool = True
# In-memory database (for demo)
db: List[Item] = []
@app.get("/")
async def root():
return {"message": "π API is running!", "docs": "/docs"}
@app.get("/items", response_model=List[Item])
async def list_items():
return db
@app.post("/items", response_model=Item, status_code=201)
async def create_item(item: Item):
db.append(item)
return item
@app.get("/items/{item_id}")
async def get_item(item_id: int):
if item_id < len(db):
return db[item_id]
return {"error": "Item not found"}, 404
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
if item_id < len(db):
removed = db.pop(item_id)
return {"deleted": removed.name}
return {"error": "Item not found"}, 404
Step 3: Run It
uvicorn main:app --reload --port 8000
That's it. Open http://localhost:8000/docs and you'll see a beautiful, interactive API documentation page where you can test every endpoint right in your browser.
Step 4: Add Error Handling
Let's make it production-ready with proper error handling:
from fastapi import HTTPException
@app.get("/items/{item_id}")
async def get_item(item_id: int):
if item_id < 0 or item_id >= len(db):
raise HTTPException(
status_code=404,
detail=f"Item {item_id} not found"
)
return db[item_id]
Step 5: Add Query Parameters
FastAPI makes filtering effortless:
@app.get("/items")
async def list_items(
skip: int = 0,
limit: int = 10,
in_stock: Optional[bool] = None
):
items = db[skip : skip + limit]
if in_stock is not None:
items = [i for i in items if i.in_stock == in_stock]
return items
Now /items?in_stock=true&limit=5 just works. No manual parsing.
Step 6: Connect a Real Database (SQLite Example)
from databases import Database
import sqlalchemy
DATABASE_URL = "sqlite:///./test.db"
database = Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()
items_table = sqlalchemy.Table(
"items", metadata,
sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column("name", sqlalchemy.String(50)),
sqlalchemy.Column("price", sqlalchemy.Float),
sqlalchemy.Column("description", sqlalchemy.String(255)),
sqlalchemy.Column("in_stock", sqlalchemy.Boolean, default=True),
)
@app.on_event("startup")
async def startup():
await database.connect()
engine = sqlalchemy.create_engine(DATABASE_URL)
metadata.create_all(engine)
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
@app.get("/items")
async def list_items():
query = items_table.select()
return await database.fetch_all(query)
Pro Tips I Wish I Knew Earlier
1. Use Depends for Clean Dependency Injection
from fastapi import Depends
async def get_db():
# Return your DB session
return database
@app.post("/items")
async def create_item(item: Item, db=Depends(get_db)):
# db is automatically injected
query = items_table.insert().values(**item.dict())
await db.execute(query)
return item
2. Environment Variables with Pydantic Settings
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "My API"
database_url: str
secret_key: str
class Config:
env_file = ".env"
settings = Settings()
3. CORS for Frontend Integration
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["*"],
allow_headers=["*"],
)
File Structure for a Real Project
my-api/
βββ main.py
βββ models.py # Pydantic models
βββ database.py # DB connection
βββ crud.py # CRUD operations
βββ routers/
β βββ items.py # Item endpoints
β βββ users.py # User endpoints
βββ tests/
β βββ test_items.py
βββ requirements.txt
βββ .env
When to Use FastAPI (and When Not To)
β Great for:
- REST APIs and microservices
- ML model serving
- Quick MVP backends
- Webhook handlers
β Maybe not for:
- Full-stack apps with complex auth (consider Django)
- Simple scripts (overkill)
- Real-time WebSocket-only apps (consider aiohttp)
Benchmark: How Fast Is It Really?
In my tests with a simple GET endpoint returning JSON:
| Framework | Requests/sec |
|---|---|
| FastAPI | ~15,000 |
| Flask | ~3,000 |
| Django REST | ~1,500 |
| Express.js | ~12,000 |
Your mileage may vary depending on hardware and payload size.
Get Started Right Now
pip install fastapi uvicorn
# Copy the code above into main.py
uvicorn main:app --reload
Open http://localhost:8000/docs and start building. You'll have a working API in less time than it takes to finish your coffee.
What are you building with FastAPI? Drop a comment β I'd love to hear about your projects!
If you found this useful, follow me for more Python and backend tutorials.
United States
NORTH AMERICA
Related News
What Does "Building in Public" Actually Mean in 2026?
20h ago
The Agentic Headless Backend: What Vibe Coders Still Need After the UI Is Done
20h ago
Why Iβm Still Learning to Code Even With AI
22h ago
Students Boo Commencement Speaker After She Calls AI the 'Next Industrial Revolution'
5h ago

Testing for βBad Cholesterolβ Doesnβt Tell the Whole Story
5h ago