In today’s software world, RESTful APIs are the backbone of most modern applications — from mobile apps and web frontends to microservices.
If you’re a Python developer, you can build a robust API fast with FastAPI and SQLAlchemy.
This post walks you through:
- What a RESTful API is
- How to build one in Python using FastAPI
- How to add a database layer with SQLAlchemy for real CRUD functionality
🚀 What Is a RESTful API?
REST (Representational State Transfer) defines how systems communicate over HTTP.
Each endpoint represents a resource (like users or posts) and uses standard HTTP methods:
| Method | Action | Example |
|---|---|---|
GET | Retrieve data | /posts |
POST | Create new data | /posts |
PUT | Update data | /posts/1 |
DELETE | Delete data | /posts/1 |
Responses are usually in JSON, making them easy to consume from frontend frameworks like React or mobile apps.
⚙️ Setting Up the Project
Create a virtual environment and install dependencies:
python -m venv venv
source venv/bin/activate # or venv\Scripts\activate on Windows
pip install fastapi uvicorn sqlalchemy🧱 Basic REST API with FastAPI
Here’s a simple version without a database:
# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
posts = []
class Post(BaseModel):
id: int
title: str
content: str
@app.get("/posts")
def get_posts():
return posts
@app.post("/posts", status_code=201)
def create_post(post: Post):
posts.append(post.dict())
return post
Run it:
uvicorn main:app --reload<br>Then go to http://127.0.0.1:8000/docs to test your endpoints in the interactive Swagger UI.
💾 Adding a Real Database with SQLAlchemy
Let’s upgrade this to a real database-backed API using SQLAlchemy.
Install dependencies:
pip install sqlalchemy1️⃣ Set up the Database Engine and Session
# database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./blog.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()2️⃣ Create the Model
# models.py
from sqlalchemy import Column, Integer, String
from database import Base
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
content = Column(String)3️⃣ Create Pydantic Schemas
# schemas.py
from pydantic import BaseModel
class PostBase(BaseModel):
title: str
content: str
class PostCreate(PostBase):
pass
class PostResponse(PostBase):
id: int
class Config:
orm_mode = True4️⃣ CRUD Operations and Routes
# main.py
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
import models, schemas
from database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
# Dependency to get DB session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/posts", response_model=schemas.PostResponse)
def create_post(post: schemas.PostCreate, db: Session = Depends(get_db)):
db_post = models.Post(title=post.title, content=post.content)
db.add(db_post)
db.commit()
db.refresh(db_post)
return db_post
@app.get("/posts", response_model=list[schemas.PostResponse])
def get_posts(db: Session = Depends(get_db)):
return db.query(models.Post).all()
@app.get("/posts/{post_id}", response_model=schemas.PostResponse)
def get_post(post_id: int, db: Session = Depends(get_db)):
post = db.query(models.Post).filter(models.Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
return post
@app.put("/posts/{post_id}", response_model=schemas.PostResponse)
def update_post(post_id: int, updated_post: schemas.PostCreate, db: Session = Depends(get_db)):
post = db.query(models.Post).filter(models.Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
post.title = updated_post.title
post.content = updated_post.content
db.commit()
db.refresh(post)
return post
@app.delete("/posts/{post_id}", status_code=204)
def delete_post(post_id: int, db: Session = Depends(get_db)):
post = db.query(models.Post).filter(models.Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
db.delete(post)
db.commit()5️⃣ Run the API
Start the server:
uvicorn main:app --reloadVisit:
- Docs:
http://127.0.0.1:8000/docs - DB:
blog.db(SQLite file created automatically)
🧩 Summary
You now have:
- ✅ A RESTful API with FastAPI
- ✅ Real CRUD operations using SQLAlchemy
- ✅ Auto-generated docs with Swagger
- ✅ A ready-to-extend structure (add authentication, pagination, etc.)
🔮 Next Steps
Once you have CRUD working, try adding:
- JWT authentication with
fastapi.security - Alembic for database migrations
- Docker to containerize your API
- React or Vue frontend to consume the API
💡 Takeaway
FastAPI + SQLAlchemy gives you everything you need for modern API development:
- Performance
- Type safety
- Automatic validation and documentation
- Clean, testable architecture
Build small, build clean, and iterate — your first production-grade Python API is just a few commands away.