Best Practices Recap
You now have the full toolkit. Here is the whole course as one checklist you can apply to any API you design or review.
The map
Section titled “The map”flowchart TD Start[Design a REST API] --> R[Resources & URIs] Start --> M[Methods & idempotency] Start --> E[Status & errors] Start --> Q[Querying collections] Start --> VC[Versioning & caching] Start --> Sec[Security] Start --> Ship[Docs, tests, build]
The checklist
Section titled “The checklist”Resources & URIs — model nouns, not actions; plural collections (/articles); lowercase-hyphenated paths; IDs in the path; nest only for ownership, otherwise link. See Resource & URI Design.
Methods & idempotency — map CRUD to GET/POST/PUT/PATCH/DELETE; never mutate on GET; make writes idempotent where you can; protect non-idempotent creates with idempotency keys. See Methods, CRUD & Idempotency.
Status & errors — pick the precise status code; never return 200 for a failure; use one consistent problem+json error shape; return all validation errors at once. See Status Codes & Errors.
Querying collections — always paginate (prefer cursor for large/changing data); allowlist filter/sort fields; offer sparse fieldsets and a consistent envelope. See Querying Collections.
Versioning & caching — favor additive, non-breaking changes; version coarsely when you must; set Cache-Control and ETags; use conditional requests for concurrency. See Versioning & Caching.
Security — HTTPS only; never put secrets in URLs; distinguish 401/403; verify tokens (do not just decode); tight CORS allowlist; rate-limit and validate all input. See Security.
Ship it — describe the API with OpenAPI; test unit/integration/contract layers; keep handlers thin and services HTTP-free. See OpenAPI.
Common mistakes
Section titled “Common mistakes”No API design review before implementing Symptom:
- Developers implement the endpoint first and write docs afterward
- Consumers use the API and find the design inconsistent
- Do an API design review (an OpenAPI spec or design doc) before implementing, every time
Breaking change without a version bump Symptom:
- Renaming a response field:
userId→user_idin/v1/ - Consumers using
userIdbreak immediately - Only additive changes go into an existing version; breaking changes require a version bump
💡 Real-world examples
Stripe API:
- Versions each request via the dated
Stripe-Versionheader, not the URL path —/v1/has stayed the same since launch- Monthly releases stay backward compatible; only major releases can break existing code, and each account defaults to a version it can pin
GitHub API:
- Supports a REST API version for at least 24 months after a newer version ships
DeprecationandSunsetresponse headers warn consumers before a version stops being supported