Skip to content

03 Path Operations

DodaTech 4 min read

title: Path Operations in FastAPI REST APIs weight: 13 date: 2026-06-28 lastmod: 2026-06-28 description: Master FastAPI path operations including decorators, route ordering, HTTP method mapping, path parameters with types, and automatic request validation. tags: [api-development, fastapi]


FastAPI path operations use Python decorators like @app.get and @app.post to map HTTP methods to handler functions, with automatic parameter extraction and validation from function signatures.

```mermaid
flowchart TD
  A[Path Operation] --> B[Decorator]
  A --> C[Handler Function]
  A --> D[Parameters]
  B --> E[@app.get('/users')]
  B --> F[@app.post('/users')]
  D --> G[Path params]
  D --> H[Query params]
  D --> I[Request body]
  style A fill:#e1f5fe
  style B fill:#c8e6c9
  style D fill:#fff9c4

Each path operation consists of a decorator (HTTP method + path), a handler function (async def or def), and optional path/query/body parameters. FastAPI inspects the function signature and automatically validates and injects parameters.

Think of path operations like a restaurant menu. The decorator is the menu section (Appetizers = GET). The path is the dish name (/users). The handler function is the recipe. The parameters are the ingredients the customer specifies.

Example: Basic Path Operations

from fastapi import FastAPI, HTTPException
from typing import List

app = FastAPI()

# In-memory database
items = [
    {"id": 1, "name": "Laptop", "price": 999.99},
    {"id": 2, "name": "Mouse", "price": 29.99}
]

@app.get("/api/items")
def list_items():
    """GET - List all items."""
    return {"status": "success", "data": items}

@app.get("/api/items/{item_id}")
def get_item(item_id: int):
    """GET - Get a single item by ID."""
    item = next((i for i in items if i["id"] == item_id), None)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"status": "success", "data": item}

@app.post("/api/items", status_code=201)
def create_item(name: str, price: float):
    """POST - Create a new item."""
    item = {"id": len(items) + 1, "name": name, "price": price}
    items.append(item)
    return {"status": "success", "data": item}

Example: Route Order Matters

from fastapi import FastAPI

app = FastAPI()

# Static routes must come before parameterized routes
@app.get("/api/users/me")
def get_current_user():
    """Returns current authenticated user."""
    return {"user_id": 123, "name": "Current User"}

@app.get("/api/users/{user_id}")
def get_user(user_id: int):
    """Returns user by ID."""
    return {"user_id": user_id}

# Wrong order - /users/me would match /users/{user_id} first
# @app.get("/api/users/{user_id}")  # Wrong
# def get_user(user_id: int): ...
# @app.get("/api/users/me")  # Never reached
# def get_current_user(): ...

Example: Multiple HTTP Methods on Same Path

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()
items_db = {}

class Item(BaseModel):
    name: str
    price: float

@app.get("/api/items/{item_id}")
def read_item(item_id: str):
    if item_id not in items_db:
        raise HTTPException(404, "Item not found")
    return items_db[item_id]

@app.put("/api/items/{item_id}")
def update_item(item_id: str, item: Item):
    items_db[item_id] = item.model_dump()
    return {"message": "Updated", "item": items_db[item_id]}

@app.delete("/api/items/{item_id}", status_code=204)
def delete_item(item_id: str):
    if item_id in items_db:
        del items_db[item_id]

Common Mistakes

  1. Parameterized route before static route — /users/{id} catches /users/me before the static route matches. Define static routes first.
  2. Not specifying status_code — POST defaults to 200. Use status_code=201 for creation. DELETE should return 204.
  3. Using wrong HTTP method — Use GET for retrieval, POST for creation, PUT for full replacement, PATCH for partial update, DELETE for removal.
  4. Path parameter type mismatch — If a parameter is typed as int but receives a string, FastAPI returns a 422 validation error.
  5. Forgetting to raise HTTPException — Returning None when a resource is not found does not automatically return 404. Raise HTTPException explicitly.

Practice Questions

  1. What decorator would you use for a PUT endpoint?
  2. Why should static routes be defined before parameterized routes?
  3. What status code should a successful POST return?
  4. How does FastAPI know whether a parameter is a path or query parameter?
  5. Challenge: Create a complete CRUD API for books using path operations. Include GET /books, GET /books/{id}, POST /books, PUT /books/{id}, and DELETE /books/{id}. Use in-memory storage and proper status codes.

FAQ

What is the difference between @app.get and @app.post?

@app.get maps to HTTP GET (retrieve). @app.post maps to HTTP POST (create). FastAPI supports all HTTP methods: get, post, put, patch, delete, options, head.

How do I set a custom status code?

Use the status_code parameter in the decorator: @app.post('/items', status_code=201). You can also return a Response object with a custom status code.

Can I have multiple handlers for the same path?

Yes, as long as they use different HTTP methods. You can have GET /items and POST /items on the same path.

What happens if no route matches?

FastAPI returns a 404 Not Found response with an automatic error message.

How do I organize path operations across files?

Use APIRouter to define routes in separate files. Include routers in the main app with app.include_router().

Mini Project

Create a FastAPI application with 7 endpoints for a music library: GET /songs, GET /songs/{id}, POST /songs, PUT /songs/{id}, DELETE /songs/{id}, GET /artists/{artist_id}/songs (nested), and GET /songs/search (query params). Use in-memory storage and proper status codes.

What's Next

Now learn about path parameters in Building REST APIs with FastAPI.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro