
FastAPI
Understanding status codes deeply enables you to design better APIs and handle edge cases gracefully.
from fastapi import status
# 200 OK - Request succeeded, returning data
@app.get("/items/{item_id}")
async def get_item(item_id: int):
return {"id": item_id}
# 201 Created - New resource created
@app.post("/items", status_code=status.HTTP_201_CREATED)
async def create_item(item: Item):
new_item = db.create(item)
return new_item
# 202 Accepted - Request accepted but not complete
@app.post("/process", status_code=status.HTTP_202_ACCEPTED)
async def process_async(data: dict):
# Queue for background processing
queue.enqueue(process_task, data)
return {"status": "processing"}
# 204 No Content - Success but no data
@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(item_id: int):
db.delete(item_id)
return Nonefrom fastapi import HTTPException, status
# 400 Bad Request - Malformed request
@app.post("/validate")
async def validate_data(data: dict):
if not data.get("required_field"):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="required_field is missing"
)
return {"status": "valid"}
# 401 Unauthorized - Authentication missing
@app.get("/protected", dependencies=[Depends(get_current_user)])
async def protected_route():
return {"data": "secret"}
# 403 Forbidden - Authenticated but not authorized
@app.delete("/admin/users/{user_id}")
async def admin_delete(user_id: int, current_user = Depends(get_current_user)):
if current_user.role != "admin":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Only admins can delete"
)
db.delete_user(user_id)
return {"deleted": True}
# 404 Not Found - Resource doesn't exist
@app.get("/items/{item_id}")
async def get_item(item_id: int):
item = db.get(item_id)
if not item:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Item not found"
)
return item
# 409 Conflict - Request conflicts with current state
@app.post("/users")
async def create_user(user: User):
if db.user_exists(user.email):
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="User already exists"
)
return db.create_user(user)
# 422 Unprocessable Entity - Validation error
@app.post("/items")
async def create_item(item: Item):
# FastAPI automatically returns 422 for validation errors
return db.create(item)
# 429 Too Many Requests - Rate limiting
@app.get("/api/data")
async def get_data(client: str = Header(...)):
if rate_limit_exceeded(client):
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Too many requests, please try later"
)
return {"data": []}from typing import Union
@app.get("/items/{item_id}")
async def get_item(item_id: int):
try:
# Try to get item
item = db.get(item_id)
# Item doesn't exist
if not item:
raise HTTPException(status_code=404, detail="Not found")
# Success
return item
except DatabaseError:
# Server error
raise HTTPException(
status_code=500,
detail="Database error"
)
except Exception as e:
# Unexpected error
logger.error(f"Unexpected error: {e}")
raise HTTPException(
status_code=500,
detail="Internal server error"
)| Scenario | Code | Reason |
|---|---|---|
| GET succeeds | 200 | Standard success |
| POST creates | 201 | Created new resource |
| PUT/PATCH succeeds | 200 | Resource updated |
| DELETE succeeds | 204 | Success, no body |
| Missing auth | 401 | Not authenticated |
| No permission | 403 | Authenticated but denied |
| Resource missing | 404 | Not found |
| Invalid input | 400 or 422 | Bad/unparseable request |
| Async processing | 202 | Accepted, still processing |
| Rate limited | 429 | Too many requests |
| Server error | 500+ | Server problem |
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward