API Design Principles¶
Versioning¶
All routes are prefixed with /api/v1/. Include the version in the router:
Standardized Response Envelope¶
For list endpoints, use a consistent pagination wrapper:
from typing import Generic, TypeVar
from math import ceil
T = TypeVar("T")
class Page(BaseModel, Generic[T]):
items: list[T]
total: int
page: int
size: int
pages: int
@classmethod
def create(cls, items: list[T], total: int, page: int, size: int) -> "Page[T]":
return cls(items=items, total=total, page=page, size=size, pages=ceil(total / size))
Consistent Interfaces¶
POSTreturns201with the created resourceGETreturns200with the resource or listPATCHreturns200with the updated resourceDELETEreturns204with no body- Error responses always return
{"error": {"code": ..., "message": ..., "request_id": ...}}
Naming Conventions¶
| Resource | Endpoint | Method |
|---|---|---|
| List | /api/v1/users |
GET |
| Create | /api/v1/users |
POST |
| Get | /api/v1/users/{user_id} |
GET |
| Update | /api/v1/users/{user_id} |
PATCH |
| Delete | /api/v1/users/{user_id} |
DELETE |
| Action | /api/v1/users/{user_id}/deactivate |
POST |
See Also¶
- Error Contracts -- Standardized error response format and status codes
- API Versioning -- Strategies for evolving the API without breaking clients
- OpenAPI -- Automatic documentation and schema generation with FastAPI