Course Content
FastAPI Essentials
1 sections · 32 lessons
Can you give me an example of how to use HTTP methods with routes in FastAPI?
What you need to know
| Method | Purpose | Safe (no change)? | Idempotent? | Typical status |
|---|---|---|---|---|
| GET | Read | Yes | Yes | 200 |
| POST | Create, or run an action | No | No | 201 or 200 |
| PUT | Replace the whole resource | No | Yes | 200 |
| PATCH | Change some fields | No | Not guaranteed | 200 |
| DELETE | Remove | No | Yes | 204 |
A prompt-template service built on one router:
1from fastapi import APIRouter, FastAPI, HTTPException23router = APIRouter(prefix="/templates", tags=["prompts"])45@router.get("")6def list_templates(limit: int = 20) -> list[Template]:7 return list(DB.values())[:limit]89@router.post("", status_code=201)10def create_template(body: TemplateIn) -> Template:11 t = Template(id=len(DB) + 1, **body.model_dump())12 DB[t.id] = t13 return t1415@router.put("/{tid}")16def replace_template(tid: int, body: TemplateIn) -> Template:17 DB[tid] = Template(id=tid, **body.model_dump())18 return DB[tid]1920@router.patch("/{tid}")21def update_template(tid: int, body: TemplatePatch) -> Template:22 if tid not in DB:23 raise HTTPException(404, "Template not found")24 changes = body.model_dump(exclude_unset=True) # only the fields the client sent25 DB[tid] = DB[tid].model_copy(update=changes)26 return DB[tid]2728@router.delete("/{tid}", status_code=204)29def delete_template(tid: int) -> None:30 DB.pop(tid, None)3132app = FastAPI()33app.include_router(router)TemplateIn has name, text and temperature (default 0.2). TemplatePatch has the same fields, all optional. Real responses:
POST /templates {"name": "refund", "text": "..."} -> 201 {... 'temperature': 0.2, 'id': 1}PATCH /templates/1 {"temperature": 0.7} -> 200 {'name': 'refund', ..., 'temperature': 0.7}PUT /templates/1 {"name": "refund-v2", "text": "Be brief."} -> 200 {..., 'temperature': 0.2}DELETE /templates/1 -> 204 b''DELETE /templates/1 (again) -> 204PUT /templates -> 405Look at PUT: the client did not send temperature, so it went back to the default 0.2. PUT replaces. PATCH with exclude_unset=True changed only the field that was sent. The second DELETE also returned 204 — idempotent. A method the path does not support returns 405.
A real-life example
A marketing team edits prompt templates from an internal tool. A developer implemented "edit" as PUT but the front end sent only the changed field. Every edit silently reset temperature and max_tokens to defaults, and product descriptions became noticeably more random for a week before anyone connected the two.
The fix was to use PATCH with exclude_unset=True for partial edits and keep PUT for "save the whole form". A second fix came from the idempotency rule: the tool retried failed POSTs automatically, which created duplicate templates. The team added an Idempotency-Key header, stored with each created template, so a retried POST returns the first result instead of creating another.
Follow-up questions to expect
- "Why is
/predicta POST, not a GET?" — The input is large and often private; URLs have length limits and are written to access logs and browser history. POST puts the input in the body. - "What status code for a successful DELETE?" — 204 No Content, with an empty body. FastAPI sends no body when you set
status_code=204. - "How do you make a POST safe to retry?" — Accept an idempotency key from the client, store it with the result, and return the stored result for a repeated key.