Status codes are the API's primary vocabulary for outcomes, and using them precisely saves clients from parsing message bodies to understand what happened. The 2xx range covers success: 200 OK is the default response for a successful GET, 201 Created is the right answer after a POST that produced a new resource (ideally with a Location header pointing to it), and 204 No Content suits successful operations with no meaningful body, such as a DELETE or a PUT with no return value. Falling back to a generic 200 in all these cases is a common anti-pattern that hides semantic information from clients and pushes them to inspect bodies to distinguish success from failure.
The 4xx range covers client errors and benefits from clear distinctions. 400 Bad Request signals that the request itself is malformed—think invalid JSON syntax or a missing required field. 404 Not Found means the addressed resource does not exist, while 422 Unprocessable Entity is reserved for semantically invalid input that parsed cleanly, such as a syntactically valid but unusable email address. Using 422 for these validation failures keeps the meaning of 400 focused on transport-level problems and gives clients a reliable way to distinguish "I cannot read what you sent" from "I read it but it does not make sense." 429 Too Many Requests is the dedicated code for rate limiting, signaling that the client has exceeded its quota and should back off; it pairs naturally with headers such as Retry-After to guide the next attempt.
Whatever the code, the response body should make the error machine-readable and consistent across the API. The de facto standard is RFC 7807's Problem Details format, a JSON structure with fields like type, title, status, detail, and instance that describes what went wrong and where. A single shared error shape lets clients write one error-handling path instead of branching per endpoint, and it makes log aggregation and support tooling far more effective.