Building Your First REST API with FastAPI: A Practical Guide

Published: (January 13, 2026 at 11:06 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Why FastAPI?

FastAPI stands out for several reasons:

  • Performance: One of the fastest Python frameworks available, comparable to Node.js and Go.
  • Type Safety: Built on Python type hints for better code quality and editor support.
  • Auto Documentation: Swagger UI and ReDoc documentation generated automatically.
  • Modern Python: Uses async/await for handling concurrent requests efficiently.

Setting Up

First, install FastAPI and uvicorn (an ASGI server):

pip install fastapi uvicorn

Creating a Simple API

Here’s a basic FastAPI application that manages a list of tasks:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional

app = FastAPI()

# Pydantic model for data validation
class Task(BaseModel):
    id: int
    title: str
    description: Optional[str] = None
    completed: bool = False

# In-memory storage
tasks_db: List[Task] = []

@app.get("/")
def read_root():
    return {"message": "Welcome to the Task API"}

@app.get("/tasks", response_model=List[Task])
def get_tasks():
    return tasks_db

@app.get("/tasks/{task_id}", response_model=Task)
def get_task(task_id: int):
    task = next((t for t in tasks_db if t.id == task_id), None)
    if not task:
        raise HTTPException(status_code=404, detail="Task not found")
    return task

@app.post("/tasks", response_model=Task, status_code=201)
def create_task(task: Task):
    tasks_db.append(task)
    return task

@app.put("/tasks/{task_id}", response_model=Task)
def update_task(task_id: int, updated_task: Task):
    for index, task in enumerate(tasks_db):
        if task.id == task_id:
            tasks_db[index] = updated_task
            return updated_task
    raise HTTPException(status_code=404, detail="Task not found")

@app.delete("/tasks/{task_id}")
def delete_task(task_id: int):
    for index, task in enumerate(tasks_db):
        if task.id == task_id:
            tasks_db.pop(index)
            return {"message": "Task deleted successfully"}
    raise HTTPException(status_code=404, detail="Task not found")

Running Your API

Start the development server:

uvicorn main:app --reload

Your API is now running at http://localhost:8000.

Automatic Documentation

FastAPI provides interactive documentation out of the box:

  • Swagger UI: http://localhost:8000/docs
  • ReDoc: http://localhost:8000/redoc

You can test all your endpoints directly from the browser.

Key Features Demonstrated

  • Pydantic Models: The Task class uses Pydantic for automatic data validation. Invalid data triggers clear error responses.
  • Type Hints: Python type hints throughout the code enable better IDE support and early error detection.
  • Path Parameters: The {task_id} syntax in routes automatically extracts and validates URL parameters.
  • HTTP Status Codes: Proper status codes (e.g., 201 for creation) follow REST best practices.
  • Exception Handling: HTTPException provides clean error responses with appropriate status codes.

Adding Async Support

FastAPI shines with async operations. Below is an example with a simulated asynchronous database call:

import asyncio
from fastapi import HTTPException

@app.get("/tasks/async/{task_id}")
async def get_task_async(task_id: int):
    # Simulate async database call
    await asyncio.sleep(0.1)
    task = next((t for t in tasks_db if t.id == task_id), None)
    if not task:
        raise HTTPException(status_code=404, detail="Task not found")
    return task

Next Steps

To build production‑ready APIs, consider:

  • Connecting to a real database (PostgreSQL, MongoDB)
  • Adding authentication and authorization
  • Implementing comprehensive request validation and error handling
  • Setting up CORS for frontend integration
  • Writing tests using pytest
  • Containerizing with Docker

Conclusion

FastAPI makes building APIs in Python straightforward and enjoyable. Automatic validation, documentation, and modern Python features reduce boilerplate and let you focus on business logic. Its performance and developer experience make it an excellent choice for both small projects and large‑scale applications.

Back to Blog

Related posts

Read more »