status-codes.md 4.9 KB

HTTP Status Codes Reference

Complete reference for HTTP status codes in REST APIs.

Success (2xx)

Code Name When to Use
200 OK Success GET, PUT, PATCH, DELETE success with body
201 Created Created POST success (include Location header)
202 Accepted Accepted Request queued for async processing
204 No Content No Content Success with no response body
206 Partial Content Partial Range request fulfilled

Usage Examples

# 200 OK - Successful GET
GET /users/123
→ 200 OK
→ {"id": 123, "name": "Alice"}

# 201 Created - Successful POST
POST /users
→ 201 Created
→ Location: /users/456
→ {"id": 456, "name": "Bob"}

# 202 Accepted - Async operation
POST /jobs
→ 202 Accepted
→ {"job_id": "abc123", "status": "pending"}

# 204 No Content - Successful DELETE
DELETE /users/123
→ 204 No Content

Redirection (3xx)

Code Name When to Use
301 Moved Permanently Moved Resource permanently relocated
302 Found Found Temporary redirect (avoid in APIs)
304 Not Modified Not Modified Client cache is valid (ETag match)
307 Temporary Redirect Temp Redirect Redirect preserving HTTP method
308 Permanent Redirect Perm Redirect Like 301, preserves method

301 vs 308

  • 301: Browser may change POST to GET on redirect
  • 308: Guarantees method is preserved

304 Workflow

# First request
GET /users/123
→ 200 OK
→ ETag: "abc123"

# Subsequent request with validation
GET /users/123
If-None-Match: "abc123"
→ 304 Not Modified (use cached version)

Client Errors (4xx)

Code Name When to Use
400 Bad Request Bad Request Invalid syntax, malformed JSON
401 Unauthorized Unauthorized Missing or invalid authentication
403 Forbidden Forbidden Authenticated but not authorized
404 Not Found Not Found Resource doesn't exist
405 Method Not Allowed Not Allowed HTTP method not supported
406 Not Acceptable Not Acceptable Can't produce requested content type
409 Conflict Conflict State conflict (duplicate, version mismatch)
410 Gone Gone Resource permanently removed
412 Precondition Failed Precondition If-Match header condition failed
413 Payload Too Large Too Large Request body exceeds limit
415 Unsupported Media Type Bad Media Content-Type not supported
422 Unprocessable Entity Unprocessable Valid syntax, invalid semantics
429 Too Many Requests Rate Limited Rate limit exceeded

400 vs 422

  • 400: Malformed request (invalid JSON, wrong types)
  • 422: Valid request, but business logic rejects it
# 400 - Syntax error
POST /users
{"name": "Alice", age: 30}  # Missing quotes around age
→ 400 Bad Request
→ {"error": "Invalid JSON"}

# 422 - Validation error
POST /users
{"name": "Alice", "age": -5}  # Age can't be negative
→ 422 Unprocessable Entity
→ {"error": {"field": "age", "message": "Must be positive"}}

401 vs 403

  • 401: "Who are you?" (not authenticated)
  • 403: "I know who you are, but no" (not authorized)
# 401 - Missing token
GET /admin/users
→ 401 Unauthorized
→ {"error": "Authentication required"}

# 403 - Valid token, wrong permissions
GET /admin/users
Authorization: Bearer <user_token>
→ 403 Forbidden
→ {"error": "Admin access required"}

409 Conflict Examples

# Duplicate resource
POST /users
{"email": "existing@example.com"}
→ 409 Conflict
→ {"error": "Email already exists"}

# Version mismatch (optimistic locking)
PATCH /users/123
If-Match: "old-version"
→ 409 Conflict
→ {"error": "Resource was modified"}

Server Errors (5xx)

Code Name When to Use
500 Internal Server Error Server Error Generic server failure
501 Not Implemented Not Implemented Feature not available
502 Bad Gateway Bad Gateway Upstream returned invalid response
503 Service Unavailable Unavailable Temporarily unavailable
504 Gateway Timeout Timeout Upstream timeout

503 with Retry-After

GET /api/resource
→ 503 Service Unavailable
→ Retry-After: 300
→ {"error": "Service temporarily unavailable", "retry_after": 300}

Decision Tree

Is the request valid?
├─ No → Is it syntax? → 400 Bad Request
│       Is it validation? → 422 Unprocessable Entity
│
└─ Yes → Is auth provided?
         ├─ No → 401 Unauthorized
         └─ Yes → Is authorized?
                  ├─ No → 403 Forbidden
                  └─ Yes → Does resource exist?
                           ├─ No → 404 Not Found
                           └─ Yes → Success! 2xx