FastAPI Tutorial: Building Your First REST API in 30 Minutes
โก Quick Answer
A hands-on FastAPI tutorial for beginners: build a fully functional REST API in 30 minutes with CRUD endpoints, request validation, and automatic docs.
Editorial note: This page is educational. Time-sensitive claims, comparisons, and reviews should include the supporting sources and update information in the article.
Read our editorial policy โGet more content like this on Telegram!
Daily AI tips, notes & resources free
FastAPI Tutorial: Building Your First REST API in 30 Minutes
FastAPI is a Python framework that turns type-hinted functions into a fully validated, self-documenting REST API, no separate schema files, no manual request parsing. Write a function, annotate the types, and the framework does the rest.
This tutorial gets a real REST API running with full interactive documentation in 30 minutes. No prior API experience needed, just Python fundamentals.
What We're Building
A task management API with full CRUD operations:
GET /tasks, list all tasksPOST /tasks, create a taskGET /tasks/{id}, get one taskPUT /tasks/{id}, update a taskDELETE /tasks/{id}, delete a task
By the end, you'll have an API running with automatic documentation at /docs. You can test every endpoint without writing any frontend code.
Setup (5 Minutes)
1. Create a virtual environment
mkdir task-api
cd task-api
python -m venv venv
source venv/bin/activate # Mac/Linux
# OR
venv\Scripts\activate # Windows2. Install FastAPI
pip install fastapi uvicornThat's it. No database setup yet, we'll start with in-memory storage so nothing gets in the way of learning the API concepts.
3. Create main.py
Create a file called main.py in your project folder. This is where everything goes.
Your First FastAPI Endpoint (5 Minutes)
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Task API is running"}Run it:
uvicorn main:app --reloadOpen http://localhost:8000, you should see {"message": "Task API is running"}.
Open http://localhost:8000/docs, you'll see the Swagger UI showing your endpoint, completely automatically generated. This is one of FastAPI's best features.
What just happened: @app.get("/") is a decorator that registers the function as a GET endpoint at the "/" path. The function returns a Python dict; FastAPI converts it to JSON automatically.
Adding Data Models with Pydantic (5 Minutes)
FastAPI uses Pydantic for data validation, like a customs checkpoint that inspects every request before it's allowed into your code. You define the shape of your data as a class, and FastAPI validates all incoming requests against it automatically.
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
app = FastAPI()
class Task(BaseModel):
id: int
title: str
description: Optional[str] = None
completed: bool = False
created_at: datetime = datetime.now()
class TaskCreate(BaseModel):
title: str
description: Optional[str] = NoneTwo models:
Task, the full task object (what we return from the API)TaskCreate, what the client sends to create a task (no id, no created_at, those are generated server-side)
In-Memory Storage
For this tutorial, we'll store tasks in a Python list. In a real app, you'd use a database.
# Storage (in-memory โ resets when server restarts)
tasks_db: list[Task] = []
next_id = 1The CRUD Endpoints (10 Minutes)
GET /tasks, List All Tasks
@app.get("/tasks", response_model=list[Task])
def get_tasks():
return tasks_dbThe response_model=list[Task] tells FastAPI what the response shape looks like, it uses this for documentation and to filter any extra fields.
POST /tasks, Create a Task
@app.post("/tasks", response_model=Task, status_code=201)
def create_task(task_data: TaskCreate):
global next_id
task = Task(
id=next_id,
title=task_data.title,
description=task_data.description,
)
tasks_db.append(task)
next_id += 1
return taskFastAPI automatically validates that the request body matches TaskCreate. If the client sends invalid data (missing title, wrong types), FastAPI returns a 422 error with a clear explanation, no custom validation code required.
GET /tasks/, Get One Task
from fastapi import FastAPI, HTTPException
@app.get("/tasks/{task_id}", response_model=Task)
def get_task(task_id: int):
for task in tasks_db:
if task.id == task_id:
return task
raise HTTPException(status_code=404, detail="Task not found"){task_id} in the path is a path parameter. FastAPI automatically converts it to int and validates it.
PUT /tasks/, Update a Task
class TaskUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
completed: Optional[bool] = None
@app.put("/tasks/{task_id}", response_model=Task)
def update_task(task_id: int, updates: TaskUpdate):
for task in tasks_db:
if task.id == task_id:
if updates.title is not None:
task.title = updates.title
if updates.description is not None:
task.description = updates.description
if updates.completed is not None:
task.completed = updates.completed
return task
raise HTTPException(status_code=404, detail="Task not found")DELETE /tasks/, Delete a Task
@app.delete("/tasks/{task_id}", status_code=204)
def delete_task(task_id: int):
for i, task in enumerate(tasks_db):
if task.id == task_id:
tasks_db.pop(i)
return
raise HTTPException(status_code=404, detail="Task not found")The Complete main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
app = FastAPI(title="Task API", description="A simple task management API")
class TaskCreate(BaseModel):
title: str
description: Optional[str] = None
class TaskUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
completed: Optional[bool] = None
class Task(BaseModel):
id: int
title: str
description: Optional[str] = None
completed: bool = False
created_at: str = ""
tasks_db: list[Task] = []
next_id = 1
@app.get("/")
def read_root():
return {"message": "Task API", "docs": "/docs"}
@app.get("/tasks", response_model=list[Task])
def get_tasks():
return tasks_db
@app.post("/tasks", response_model=Task, status_code=201)
def create_task(task_data: TaskCreate):
global next_id
task = Task(
id=next_id,
title=task_data.title,
description=task_data.description,
created_at=datetime.now().isoformat(),
)
tasks_db.append(task)
next_id += 1
return task
@app.get("/tasks/{task_id}", response_model=Task)
def get_task(task_id: int):
for task in tasks_db:
if task.id == task_id:
return task
raise HTTPException(status_code=404, detail="Task not found")
@app.put("/tasks/{task_id}", response_model=Task)
def update_task(task_id: int, updates: TaskUpdate):
for task in tasks_db:
if task.id == task_id:
if updates.title is not None:
task.title = updates.title
if updates.description is not None:
task.description = updates.description
if updates.completed is not None:
task.completed = updates.completed
return task
raise HTTPException(status_code=404, detail="Task not found")
@app.delete("/tasks/{task_id}", status_code=204)
def delete_task(task_id: int):
for i, task in enumerate(tasks_db):
if task.id == task_id:
tasks_db.pop(i)
return
raise HTTPException(status_code=404, detail="Task not found")Testing Your API (5 Minutes)
Open http://localhost:8000/docs. You'll see the full Swagger UI. Click any endpoint, click "Try it out," fill in the form, and execute. No Postman required.
Testing sequence:
POST /taskswith{"title": "Learn FastAPI"}, should return the created taskGET /tasks, should show your task in a listPUT /tasks/1with{"completed": true}, should mark it doneDELETE /tasks/1, should remove itGET /tasks/1, should return 404
Next Steps After This Tutorial
Add a real database: Replace in-memory storage with SQLite + SQLAlchemy. The FastAPI documentation has an excellent SQL databases tutorial.
Add authentication: Add JWT token authentication so only logged-in users can manage their tasks, this turns the tutorial project into a portfolio piece.
Deploy it: Push to GitHub, connect to Railway or Render, and deploy for free. A live URL makes this a proper portfolio project, not just local-only code.
For the portfolio context and what to build next, see our guide on Python projects that get you a developer job.
For a comparison of FastAPI vs. Django for larger projects, our Django vs. Flask guide covers when to choose each framework.
Further Reading
- Python OOP Complete Guide 2026, Object-Oriented Programming Mastery
- Deploying Python Apps to AWS: A Complete Beginner's Guide
- Jupyter Notebook Guide: The Data Scientist's Favorite Tool
- FastAPI Tutorial 2026, Build Production-Ready REST APIs with Python
- Python for Beginners: Complete 2026 Roadmap, Step-by-Step Guide
- Deploy AI Model to Production: FastAPI, Docker, and Cloud Deployment Guide
- Terminal and Command Line Mastery: 30 Commands That Changed My Life
- Best Machine Learning Courses in 2025: Ranked After Taking Them All
Discussion
0Sign in with Google to comment, reply and manage your own comments.
Frequently Asked Questions
What is FastAPI and why is it popular?
Is FastAPI better than Django REST Framework?
How do I deploy a FastAPI app?
Does FastAPI support database integration?
Problem Solver and Cloud Expert
Cloud and infrastructure contributor supporting AiTechWorldsโ deployment, reliability, and platform operations.
Not sure yet? Ask AI about this article
Get an instant, unbiased AI summary of โFastAPI Tutorial: Building Your First REST API in 30 Minutesโ.
Related Articles
Async Python: Why Your Programs Are Slow and How to Fix Them
A practical Python async/await tutorial: understand why synchronous code is slow for I/O tasks and how asyncio, async def, and await make programs dramatically faster.
Python for Absolute Beginners: Your First 30 Days Roadmap (2026)
A structured 30-day Python learning roadmap for 2026: daily milestones, free resources, projects, and the exact path from zero to writing real Python programs.
The Python Developer's Guide to APIs: Requests Library Deep Dive
A deep dive into Python's requests library: making API calls, handling authentication, error handling, sessions, and advanced patterns every developer needs.
Web Scraping with Python: A Gentle Introduction for Beginners
A beginner-friendly Python web scraping guide using requests and BeautifulSoup: extract data from websites, handle pagination, and store results in 2026.