FastAPI HTTP Methods

HTTP methods tell your server what kind of action a client wants to perform. A client can read data, create new data, update existing data, or delete data. Each of these actions maps to a specific HTTP method. FastAPI provides a decorator for each one.

The Four Core HTTP Methods

HTTP Method    Action           Real-World Analogy
───────────────────────────────────────────────────
GET            Read data        Reading a book
POST           Create new data  Writing a new entry
PUT            Replace data     Rewriting a whole page
DELETE         Remove data      Tearing out a page

GET — Reading Data

GET requests read information. They never change anything on the server. GET is the default when you type a URL in a browser.

@app.get("/tasks")
def get_all_tasks():
    return [
        {"id": 1, "title": "Buy groceries"},
        {"id": 2, "title": "Write report"}
    ]

@app.get("/tasks/{task_id}")
def get_one_task(task_id: int):
    return {"id": task_id, "title": "Buy groceries"}

POST — Creating New Data

POST requests send a body payload to create a new resource. The server creates it and usually returns the newly created item.

from pydantic import BaseModel

class Task(BaseModel):
    title: str
    done: bool = False

@app.post("/tasks", status_code=201)
def create_task(task: Task):
    return {"id": 3, "title": task.title, "done": task.done}
Client sends:
POST /tasks
Body: {"title": "Read FastAPI docs"}

Server creates the task and returns:
{"id": 3, "title": "Read FastAPI docs", "done": false}

The status_code=201 tells FastAPI to return HTTP 201 Created instead of the default 200, which is the correct signal for a successful creation.

PUT — Replacing Existing Data

PUT replaces an entire resource. You send all fields, even those that have not changed.

@app.put("/tasks/{task_id}")
def update_task(task_id: int, task: Task):
    return {"id": task_id, "title": task.title, "done": task.done}
Client sends:
PUT /tasks/3
Body: {"title": "Read FastAPI docs", "done": true}

All fields replaced. Returns updated task.

PATCH — Partial Update

PATCH updates only the fields you send. Use it when you want to change one field without touching the rest:

from typing import Optional

class TaskUpdate(BaseModel):
    title: Optional[str] = None
    done: Optional[bool] = None

@app.patch("/tasks/{task_id}")
def partial_update(task_id: int, update: TaskUpdate):
    return {"id": task_id, "updated_fields": update.dict(exclude_none=True)}
PUT vs PATCH:
PUT:   send ALL fields       → replaces entire record
PATCH: send ONLY changed     → updates only those fields

DELETE — Removing Data

DELETE removes a resource. It usually returns a success message or no body at all.

@app.delete("/tasks/{task_id}", status_code=204)
def delete_task(task_id: int):
    return None

Status code 204 means "success, no content to return." The resource is gone.

All Four on One Resource — The CRUD Pattern

Most APIs follow the CRUD pattern. One resource gets four routes:

Resource: /tasks

GET    /tasks          → list all tasks
POST   /tasks          → create a new task
GET    /tasks/{id}     → get one task
PUT    /tasks/{id}     → replace a task
PATCH  /tasks/{id}     → update parts of a task
DELETE /tasks/{id}     → delete a task
URL Shape Decision Guide:
  No ID in path  → working on the whole collection
  ID in path     → working on a single item

Safe vs Unsafe Methods

Safe (read-only, no side effects):
  GET, HEAD, OPTIONS

Unsafe (modify server state):
  POST, PUT, PATCH, DELETE

Browsers cache GET responses. They never cache POST responses. This difference matters for performance and correctness.

Key Points

  • GET reads data, POST creates it, PUT replaces it, DELETE removes it.
  • PATCH partially updates a resource without needing all fields.
  • Use status_code=201 for POST creation and status_code=204 for DELETE.
  • Routes without an ID operate on the collection. Routes with an ID operate on one item.
  • The CRUD pattern (Create, Read, Update, Delete) is the foundation of REST APIs.

Leave a Comment

Your email address will not be published. Required fields are marked *