40 API Design Rules (FastAPI/Django/Flask)
Forty rules for Python web APIs that are consistent, secure, observable, and maintainable across FastAPI, Django REST Framework, and Flask.
Search across all documentation pages
Forty rules for Python web APIs that are consistent, secure, observable, and maintainable across FastAPI, Django REST Framework, and Flask.
Apply during API design review before implementation. Map rules to OpenAPI schema and CI contract tests.
When to reach for this:
| # | Area | Rules |
|---|---|---|
| 1-10 | URLs & versioning | Resource design |
| 11-20 | Request/response | Models & validation |
| 21-30 | Errors & security | Client experience |
| 31-40 | Ops & docs | Production readiness |
/invoices, not /invoice or /getInvoices./api/v1/invoices for breaking changes./customers/{id}/invoices, not deeper nesting./invoices/{id}/send for non-CRUD operations.?limit=50&cursor=abc or offset with max cap.?status=paid&since=2026-01-01, not new endpoints.APPEND_SLASH).Idempotency-Key header for payment and create operations.Z suffix: 2026-07-09T14:30:00Z.float for currency fields.drf-spectacular; Flask with flask-smorest.If-None-Match returns 304 when unchanged.{"type", "title", "status", "detail", "instance"}.code field: INVOICE_NOT_FOUND.429 with Retry-After header.* in production with credentials.securitySchemes./health (liveness), /ready (dependencies ok).X-Request-ID in and out./docs in dev; exported spec in CI artifact.Deprecation: true and Sunset: RFC 8594 date.async def with async DB drivers.0.1 + 0.2 != 0.3. Fix: Decimal everywhere money touches JSON.| Alternative | Use When | Don't Use When |
|---|---|---|
| GraphQL | Diverse clients, complex graphs | Simple CRUD microservice |
| gRPC | Internal service mesh | Public browser clients |
| Webhooks only | Event-driven integration | Request/response needed |
FastAPI for async microservices. Django for admin-heavy apps with ORM and auth built in.
snake_case default for Python APIs. camelCase only if frontend contract requires it (use alias).
URL path /v1/ for breaking changes. Additive changes within same version.
REST for resources. POST actions for operations that do not map to CRUD.
OpenAPI responses section per endpoint with example Problem Details.
async for I/O-bound with async drivers. sync def ok with thread pool for blocking ORMs.
Multipart with size limits. Store in object storage; return URL, not file bytes in JSON.
JWT for user sessions. API keys for service-to-service. Document scopes for both.
pytest + TestClient/httpx. Contract tests from OpenAPI. Integration tests on test DB.
Valid for small services and extensions. FastAPI preferred for new async APIs.
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026