Status codes are your API's communication language. Use the right code — don't return 200 for errors.
200
OK
GET success
201
Created
POST success. Include Location header.
202
Accepted
Async processing — not yet done
204
No content
DELETE / PATCH success — no body
301
Moved permanently
Resource URL changed forever
304
Not modified
Cache valid — use cached version
400
Bad request
Invalid params, malformed JSON — client's fault
401
Unauthorized
Not authenticated — send valid credentials
403
Forbidden
Authenticated but not authorized
404
Not found
Resource doesn't exist
409
Conflict
Duplicate resource or optimistic lock failed
422
Unprocessable entity
Valid syntax but semantic validation failed
429
Too many requests
Rate limit exceeded. Include Retry-After.
500
Internal server error
Unexpected server failure
503
Service unavailable
Overloaded or down for maintenance
Good error response shape
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid product ID",
"field": "productId",
"request_id": "req_abc123"
}
}