Understanding HTTP Status Codes in REST APIs
Understanding HTTP Status Codes in REST APIs
HTTP status codes tell clients what happened with their request. Using them correctly makes your API predictable, debuggable, and self-documenting. Misusing them creates confusion and brittle integrations.
The Five Classes
Essential 2xx Codes
200 OK
The standard success response. Use for successful GET, PUT, and PATCH requests that return data.
201 Created
Use after a successful POST that creates a resource. Include a Location header pointing to the new resource.
POST /api/users
Content-Type: application/json
{"name": "Ada", "email": "[email protected]"}
HTTP/1.1 201 Created
Location: /api/users/42
204 No Content
Use for successful DELETE requests or PUT/PATCH when there is no response body to return.
Essential 4xx Codes
400 Bad Request
The request body is malformed or fails validation. Include details about what is wrong.
{
"error": "validation_error",
"details": [
{"field": "email", "message": "Invalid email format"},
{"field": "age", "message": "Must be a positive integer"}
]
}
401 Unauthorized
Authentication is missing or invalid. The client needs to provide valid credentials. Despite the name, this is about authentication, not authorization.
403 Forbidden
Authentication succeeded but the user lacks permission. This is about authorization. The client is authenticated but not allowed to access this resource.
404 Not Found
The resource does not exist. Also commonly used when you do not want to reveal whether a resource exists (instead of 403).
409 Conflict
The request conflicts with the current state of the server. Common for duplicate creation attempts or concurrent edit conflicts.
{
"error": "conflict",
"message": "A user with this email already exists"
}
422 Unprocessable Entity
The request syntax is valid but the content is semantically wrong. Many APIs use this instead of 400 for validation errors, especially in the Rails ecosystem.
429 Too Many Requests
Rate limit exceeded. Include Retry-After header to tell the client when to try again.
Essential 5xx Codes
500 Internal Server Error
Something went wrong on the server. Never expose stack traces or internal details in production — log them server-side and return a generic error.
502 Bad Gateway
Your server received an invalid response from an upstream server. Common with reverse proxies and microservices.
503 Service Unavailable
The server is temporarily unable to handle requests (maintenance, overload). Include Retry-After if possible.
Common Mistakes
Using 200 for everything: Some APIs return 200 with{"success": false} in the body. This breaks HTTP semantics and makes monitoring, caching, and error handling harder.
Using 500 for client errors: If the user sent invalid data, that is a 4xx, not a 5xx. Reserve 5xx for genuine server failures.
Confusing 401 and 403: 401 means "who are you?" (authentication). 403 means "I know who you are but you cannot do this" (authorization).
Conclusion
Use status codes as designed. Clients, proxies, monitoring tools, and browsers all rely on correct codes to behave properly. A well-coded API is easier to debug, monitor, and integrate with.