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=201for POST creation andstatus_code=204for 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.
