REST APIs in Depth · REST Foundations
Status Codes That Clients Can Act On
Choose 2xx/3xx/4xx/5xx codes precisely and consistently.
Status codes are the first thing clients, SDKs, proxies and monitoring read. Use a small, consistent set and document it. Return 201 Created with a Location header for creations, 202 Accepted for async work, 204 No Content for successful deletes/updates without a body. Distinguish 401 (not authenticated) from 403 (authenticated but forbidden), 404 (not found or hidden), 409 (state conflict), 412 (precondition failed — stale ETag), 422 (semantic validation), 429 (rate limited, with Retry-After). Reserve 5xx for server faults; 503 with Retry-After for temporary unavailability.
Status code cheat sheet
| Situation | Code | Notes |
|---|---|---|
| Created a resource | 201 | Location: /orders/ord_1; return the representation |
| Accepted async job | 202 | Location of a status resource |
| Malformed JSON / bad syntax | 400 | Client must fix the request |
| Valid JSON, invalid values | 422 | Field-level errors in the body |
| Missing/invalid credentials | 401 | WWW-Authenticate header |
| Not allowed | 403 (or 404 to hide existence) | Be consistent per resource type |
| Duplicate / wrong state | 409 | e.g. cancel an already shipped order |
| Stale If-Match | 412 | Client reloads and retries |
| Too many requests | 429 | Retry-After + RateLimit headers |
| Dependency down / overload | 503 | Retry-After when known |
Common pitfalls
- 200 OK with {"error": ...} bodies (breaks retries, monitoring and SDKs).
- 500 for validation errors.
- Inventing non-standard codes.
Key points
- Small, documented, consistent set
- 401 vs 403 vs 404 deliberately
- Retry-After on 429/503
Further reading: RFC 9110: Status codes
Practice questions
When would you return 404 instead of 403 for a forbidden resource?
Answer
When revealing that the resource exists is itself a leak (e.g., another tenant's invoice). Returning 404 avoids enumeration; just be consistent.
What's the difference between 409 and 422?
Answer
422: the request is well-formed but semantically invalid (bad field values). 409: the request conflicts with the current state of the resource (duplicate, invalid state transition, version conflict).
Open in the app to mark lessons complete, take notes and track your progress.