We all know 200 means success and 404 means not found. But HTTP has dozens of status codes, each with specific meaning. Using the right ones makes your API clearer, more debuggable, and easier to integrate with. After years of building APIs, I've learned that proper status codes aren't optional – they're essential communication.
The difference between an okay API and a great API often comes down to proper status code usage. Clients can handle errors appropriately, implement retry logic intelligently, and debug issues faster.
The 2xx Family: Success with Nuance
Most developers return 200 for everything successful. But different success scenarios deserve different codes.
201 Created
Use this when a POST request successfully creates a new resource:
HTTP/1.1 201 Created
Location: /api/users/12345
{ "id": 12345, "name": "New User" }
204 No Content
Perfect for DELETE requests or updates where there's nothing meaningful to return:
HTTP/1.1 204 No Content
The 3xx Family: Redirection
301 vs 302: Permanent vs Temporary
301 Moved Permanently means the resource is gone forever. 302/307 means temporary.
304 Not Modified
Caching superpower. When the resource hasn't changed, return 304 with no body. Saves bandwidth.
The 4xx Family: Client Errors
401 vs 403: Authentication vs Authorization
401 Unauthorized means "who are you?" 403 Forbidden means "I know who you are, but you can't do this."
422 Unprocessable Entity
Valid JSON, correct types, but business logic rejects it.
The 5xx Family: Server Errors
503 Service Unavailable
Temporarily unable to handle requests. Include Retry-After header:
HTTP/1.1 503 Service Unavailable
Retry-After: 3600
HTTP status codes are free documentation. Use them correctly, and your API becomes clearer and more professional.