HTTP Status Codes — The Complete Guide
Every HTTP response includes a three-digit status code. These codes are the contract between your API and its consumers — they tell clients what happened to their request. Choosing the wrong code breaks API clients, monitoring systems, and SEO crawlers that interpret these codes automatically.
The Five Categories
- 1xx Informational — request received, continuing process
- 2xx Success — request was successfully received, understood, and accepted
- 3xx Redirection — further action needs to be taken
- 4xx Client Error — the request contains bad syntax or cannot be fulfilled
- 5xx Server Error — the server failed to fulfill an apparently valid request
2xx — Success Codes
200 OK The most common success code. Use for GET, PUT, and PATCH responses that return a body.
GET /users/123
→ 200 OK
{ "id": 123, "name": "Ravi Mehta" }201 Created Use for POST requests that create a new resource. Always include a `Location` header pointing to the new resource.
POST /users
→ 201 Created
Location: /users/124
{ "id": 124, "name": "New User" }204 No Content Use for DELETE (and some PUT/PATCH) when there is nothing meaningful to return. No response body.
DELETE /users/123
→ 204 No Content202 Accepted The request was accepted but processing is not complete. Use for async operations (job queues, webhooks).
4xx — Client Error Codes
400 Bad Request Invalid request syntax: malformed JSON, missing required headers, incorrect content type, or unparseable body.
401 Unauthorized The client is not authenticated. Missing or invalid API key, token, or session. Return a `WWW-Authenticate` header.
403 Forbidden The client is authenticated but lacks permission for this resource. Do not reveal whether the resource exists.
404 Not Found The requested resource does not exist. Safe to reveal — not a security issue for GET requests.
409 Conflict Duplicate resource: a user with this email already exists, or an optimistic lock conflict occurred.
422 Unprocessable Entity The JSON is syntactically valid but fails business validation. Use this when the input is well-formed but semantically wrong (e.g., a date in the past when a future date is required).
POST /appointments
Body: { "date": "2020-01-01" }
→ 422 Unprocessable Entity
{
"error": "validation_error",
"field": "date",
"message": "Appointment date must be in the future"
}429 Too Many Requests Rate limit exceeded. Include `Retry-After` and `X-RateLimit-*` headers.
5xx — Server Error Codes
500 Internal Server Error An unhandled exception. Log it with a correlation ID, return a generic message — never expose stack traces.
502 Bad Gateway Your server is a proxy and the upstream service returned an invalid response.
503 Service Unavailable Server overloaded or down for maintenance. Include `Retry-After` header.
504 Gateway Timeout Upstream service timed out. Check dependencies.
REST API Status Code Cheat Sheet
| Method | Success | Not Found | Validation Error |
|---|---|---|---|
| GET | 200 | 404 | — |
| POST | 201 | — | 400 / 422 |
| PUT | 200 | 404 | 400 / 422 |
| PATCH | 200 | 404 | 400 / 422 |
| DELETE | 204 | 404 | — |
Common Mistakes
Using 200 for errors — never return 200 OK with an error body. Clients check the status code, not the body, to determine success.
Using 400 instead of 422 — 400 means the request is malformed (invalid JSON). 422 means the JSON is valid but the data fails business rules. Using the wrong code confuses API consumers.
Using 403 when you mean 401 — 401 means "authenticate first", 403 means "authenticated but not permitted". A client getting 403 on login should know the credentials are valid but access is denied — not retry with different credentials.
Reference Tool
Use JSONKit's HTTP Status Codes reference at /http-status-codes for a searchable table of all standard codes with REST API context for each one.