API Design

REST API Status Codes Explained

Understand the HTTP status codes backend developers use most often in REST APIs, including 200, 201, 400, 401, 404, 409, and 500.

Quick answer

HTTP status codes are part of a REST API contract. They tell clients whether a request succeeded, created something, failed validation, lacked authentication, hit a permission rule, targeted a missing resource, conflicted with current state, or failed because of the server.

For most backend APIs, a small set of status codes covers most cases: 200, 201, 204, 400, 401, 403, 404, 409, 422, 429, 500, and 503. Use the HTTP Status Code Lookup when you need a quick searchable reference.

Why status codes matter

Status codes give client applications, SDKs, observability tools, and other services a first signal about what happened. A clear code helps clients decide whether to retry, ask the user to fix input, refresh authentication, or show a failure message.

Status codes should not carry every detail. The response body can include application-specific error codes and messages. But the HTTP status code should still match the broad outcome.

2xx success codes

CodeMeaningCommon REST API use
200 OKThe request succeeded.Reading a resource or returning a response body after an update.
201 CreatedA resource was created.Successful POST /users or POST /orders.
202 AcceptedThe request was accepted for async processing.Jobs, exports, imports, or long-running tasks.
204 No ContentThe request succeeded with no response body.Delete operations or updates that intentionally return no payload.

Use 201 Created when the API creates a resource immediately. If possible, include a Location header pointing to the new resource.

3xx redirect codes

REST APIs usually use redirects less often than browser-facing websites, but they can still matter.

CodeMeaningCommon REST API use
301 Moved PermanentlyThe resource has a permanent new URL.Rare for APIs; useful during endpoint migration.
302 FoundTemporary redirect.Usually avoided in JSON APIs unless clients explicitly support it.
304 Not ModifiedCached representation is still valid.Conditional requests with ETag or If-None-Match.

If you control API clients, versioned migration responses and documentation are often clearer than relying heavily on redirects.

4xx client error codes

4xx codes mean the client can usually change something about the request.

CodeMeaningCommon REST API use
400 Bad RequestThe request is malformed or invalid at a general level.Invalid JSON, missing required fields, unsupported query shape.
401 UnauthorizedAuthentication is missing or invalid.Missing token, expired token, invalid credentials.
403 ForbiddenThe caller is authenticated but not allowed.User lacks permission for the resource or action.
404 Not FoundThe resource does not exist or should not be revealed.Unknown ID, deleted resource, hidden resource.
409 ConflictThe request conflicts with current state.Duplicate unique value, version conflict, invalid state transition.
422 Unprocessable EntityThe body is syntactically valid but semantically invalid.Domain validation errors, field-level validation failures.
429 Too Many RequestsThe client is rate limited.Too many requests in a time window.

The distinction between 400 and 422 is a design choice. Many teams use only 400 for validation errors. That is acceptable if it is consistent and documented.

5xx server error codes

5xx codes mean the server failed to fulfill a valid request.

CodeMeaningCommon REST API use
500 Internal Server ErrorUnexpected server failure.Unhandled exception, bug, unexpected dependency behavior.
502 Bad GatewayUpstream service returned an invalid response.API gateway or proxy received a bad upstream response.
503 Service UnavailableService is temporarily unavailable.Maintenance, overload, dependency outage.
504 Gateway TimeoutUpstream service timed out.Gateway or proxy waited too long for another service.

Do not return 500 for validation errors, missing authentication, or normal business-rule failures. If the client can fix the request, a 4xx code is usually more accurate.

Common examples

Use 201 Created for a successful create request:

POST /api/articles
201 Created
Location: /api/articles/hashmap-load-factor-explained

Use 400 Bad Request when the request cannot be parsed:

{
  "error": "invalid_json",
  "message": "Request body must be valid JSON."
}

Use 401 Unauthorized when authentication is missing or invalid:

{
  "error": "authentication_required",
  "message": "Sign in before calling this endpoint."
}

Use 409 Conflict when the requested change conflicts with current state:

{
  "error": "email_already_registered",
  "message": "An account already exists for this email address."
}

A practical error response shape

A useful error body is predictable and stable:

{
  "error": "validation_failed",
  "message": "One or more fields are invalid.",
  "fields": {
    "email": "Enter a valid email address."
  },
  "requestId": "req_123"
}

Keep error stable for machines. Keep message readable for humans. Include requestId if clients may need to report an issue to support or engineering. Use the UUID Generator for local request ID examples and test fixtures.

Status code anti-patterns

Avoid returning 200 OK for every response and hiding failure details inside the JSON body. Clients, logs, and monitors lose useful signal.

Avoid using 404 Not Found for every auth problem. Sometimes hiding resource existence is correct, but if the main issue is missing authentication, 401 is clearer.

Avoid changing status codes casually after clients depend on them. Status code behavior is part of the API contract.

Read REST vs RPC for API style tradeoffs. Use the HTTP Status Code Lookup as the searchable tool version of this guide, the UUID Generator for request ID examples, and the Unix Timestamp Converter when checking log timestamps around API failures, retries, or rate limits. You can also browse the API Design topic cluster when planning related backend API articles.