Skip to content
Back to blog

HTTP Status Codes: Build Predictable API Contracts

2 min read
HTTP Status Codes: Build Predictable API Contracts

HTTP status codes are part of an API contract, not just diagnostic text for browser developer tools. Clients branch on them, caches interpret them, gateways retry some of them, and monitoring uses them to distinguish a bad request from a failing dependency.

Start with the outcome

For a conventional resource endpoint, keep the happy paths boring:

  • 201 Created after creating a resource, ideally with a Location header;
  • 200 OK when a read or update returns a representation;
  • 204 No Content when an update or delete has no useful body to return.

Avoid returning 200 for every operation with an error object hidden in JSON. That makes HTTP-aware clients, caches, observability, and generic integrations less useful.

Separate request failure from domain failure

400 Bad Request is for malformed syntax: invalid JSON, an impossible header, or a request that cannot be parsed. 422 Unprocessable Content is for a correctly parsed request whose fields or business rules are invalid. A duplicate unique value, an outdated version, or another conflict with the current resource state is a better fit for 409 Conflict.

Authentication also has a useful split. Return 401 Unauthorized when credentials are missing or invalid; return 403 Forbidden after identifying the caller but refusing the action. Keeping those meanings stable prevents clients from prompting for a new login when the real issue is a missing role.

Make temporary conditions actionable

Clients can respond safely to a temporary condition only if the server states it clearly. 429 Too Many Requests and 503 Service Unavailable should include Retry-After whenever you know the delay. A reverse proxy that receives an invalid upstream reply should use 502 Bad Gateway; one that waits too long should use 504 Gateway Timeout.

For conditional writes, require an If-Match header and answer 428 Precondition Required when it is absent. If the supplied ETag no longer matches, return 412 Precondition Failed. This turns accidental last-write-wins behavior into an explicit, recoverable conflict.

Keep a shared reference close

Use the HTTP Status Codes tool to search the registered codes, review related responses, copy handling patterns for six languages, and inspect a response from a CORS-enabled endpoint directly in the browser.

Frequently asked questions

Should validation errors be 400 or 422?

Use 400 when the request cannot be parsed or is malformed. Use 422 when its syntax is valid but individual values or business rules fail validation.

What is the difference between 401 and 403?

401 means the request lacks valid credentials. 403 means the credentials are valid but do not grant permission for the requested action.

Related Articles