HTTP Status Codes (2xx/4xx/5xx)
The three-digit verdict on every response: 2xx worked, 4xx the server won't take the request as sent, 5xx the server broke.
See it
What it is
Every HTTP response starts with a three-digit verdict, and the first digit is the whole story. 2xx: it worked (200 OK, 201 Created, 204 No Content). 3xx: it moved or has not changed (301, 304). 4xx: the server will not fulfill the request in the form you sent it (400 malformed, 401 not authenticated, 403 authenticated but not allowed, 404 no such thing, 409 conflict, 422 failed validation, 429 too fast). That is not always your mistake: the row may have been deleted, or someone else may have changed the state your request assumed. 5xx: the server broke (500 unhandled crash, 502 and 504 from a bad or slow upstream, 503 overloaded or in maintenance).
The split is a debugging shortcut: 4xx means change the request or the state it assumes, 5xx means fix or wait on the server. It also drives behavior in code. Retry only failures that look transient, and only when the operation is safe to repeat: 429, 500, 502, 503, and 504 all qualify when the call is idempotent or carries an idempotency key. Never blindly retry a 400 or a 422, because the same request will fail the same way forever.
The one that trips up beginners: 401 versus 403. 401 means 'I do not know who you are', so send credentials. 403 means 'I know exactly who you are and no', so more retries with the same key will not help. And the sin on the other side of the wire is returning 200 with { error: 'not found' } in the body: every client, proxy, monitor, and retry policy reads the status line, so lying in it makes failures invisible.
Ask AI for it
Audit and fix the status codes across this API. Return 200 for reads, 201 with a Location header for creates, 204 for deletes with no body, 400 for malformed syntax, 401 for missing or bad credentials, 403 for authenticated but forbidden, 404 for missing resources, 409 for conflicts, 422 for validation failures with per-field details, 429 for rate limits with Retry-After, and 500 only for genuinely unhandled errors. Never return 200 with an error body. Give every non-2xx a consistent JSON envelope with a stable code, a human message, and a request ID.