SyntaxStudy
Sign Up
REST API 4xx Client Error Status Codes
REST API Beginner 1 min read

4xx Client Error Status Codes

The 4xx range indicates client errors—problems with the request that the client should fix. 400 Bad Request is the catch-all for malformed syntax; 401 Unauthorized means authentication is required or has failed; 403 Forbidden means the client is authenticated but lacks permission. The distinction matters: 401 tells the client to authenticate; 403 tells it to stop trying with current credentials. 404 Not Found is universally understood. 405 Method Not Allowed means the resource exists but does not support that HTTP verb. 409 Conflict is appropriate for optimistic locking failures or duplicate creation attempts. 422 Unprocessable Entity is the correct code for validation errors on well-formed requests.
Example
# 400 Bad Request — malformed JSON, missing required field
HTTP/1.1 400 Bad Request
{ "error": "MALFORMED_JSON", "message": "Unexpected token at position 42" }

# 401 Unauthorized — missing or invalid token
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token"
{ "error": "INVALID_TOKEN", "message": "Access token is expired or invalid" }

# 403 Forbidden — authenticated but not permitted
HTTP/1.1 403 Forbidden
{ "error": "FORBIDDEN", "message": "You do not have permission to delete this resource" }

# 404 Not Found
HTTP/1.1 404 Not Found
{ "error": "NOT_FOUND", "message": "Product with id 999 does not exist" }

# 405 Method Not Allowed
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST
{ "error": "METHOD_NOT_ALLOWED", "message": "DELETE is not supported on /products" }

# 409 Conflict — optimistic locking / duplicate
HTTP/1.1 409 Conflict
{ "error": "CONFLICT", "message": "Email already in use" }

# 422 Unprocessable Entity — validation error (well-formed but invalid data)
HTTP/1.1 422 Unprocessable Entity
{ "error": "VALIDATION_FAILED", "errors": [{ "field": "email", "message": "Invalid format" }] }

# 429 Too Many Requests — rate limit exceeded
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Reset: 1714560000
{ "error": "RATE_LIMITED", "message": "Limit of 1000 req/hour exceeded" }