An API response does more than deliver data: its HTTP status code tells clients whether a request succeeded, needs another step, failed because of the request, or encountered a server problem. Choosing the wrong code can make integrations harder to debug and lead clients to retry when they should correct their request—or stop when they should retry.
This guide explains common HTTP status codes for REST API responses, when to use them, and which choices are protocol semantics versus API design conventions.
Key takeaways
- Choose a status code based on what happened to the HTTP request, not just on whether your application has a result to return.
- Use
2xxfor successful or accepted work,3xxfor redirection or cache validation,4xxfor request or client-context problems, and5xxfor server-side failures. - Some protocol details matter: for example,
401requires aWWW-Authenticatechallenge, and405requires anAllowheader. - Many decisions—such as using
400or422for validation errors—are API design conventions. Document them and apply them consistently.
Start with what happened to the request
Before selecting a code, answer three questions:
- Did the server fulfill the request? If so, choose a success response that accurately describes the result.
- Does the client need to do something different? A corrected request, authentication, or a different method may be required.
- Did the server fail while processing a request it could otherwise handle? If so, a server-error response may be appropriate.
The status code is part of HTTP semantics. Your API’s JSON error format, field names, and validation conventions are design choices layered on top of those semantics. For example, two APIs might both use 400 for invalid input while returning different documented error bodies.
Common 2xx success codes
A successful response does not always mean that a resource was created or that a response body is present.
| Code | Use it when | Practical note |
|---|---|---|
200 OK | The request succeeded and the response contains a result. | Common for reads and successful updates that return a representation. |
201 Created | The request created one or more resources. | A Location header can identify the primary created resource. |
202 Accepted | The request was accepted for processing, but processing is not complete. | Do not imply that the work has already succeeded. Explain how clients can check its progress when relevant. |
204 No Content | The request succeeded and there is no response content to return. | Do not include a response body. Useful for deletes or updates where no representation is needed. |
206 Partial Content | The server is returning part of a representation in response to a range request. | This is for HTTP range handling, not a general-purpose “partial success” code. |
For example, an API that creates a task could return 201 Created with the new task representation and a Location header. An API that queues a long-running export might return 202 Accepted; the response should make clear that the export is still pending.
A common design convention is to return 200 after a successful update even if the resource did not change. Another valid approach is to use 204 when there is no response body. Pick the behavior that best communicates the result, then document it.
Common 3xx redirection and cache responses
Not every 3xx response means “send the client to a new URL.” 304 Not Modified, for example, supports conditional requests and tells a client with a cached representation that it can reuse that representation. It is not a normal response with a JSON body.
For redirects, distinguish whether the request method should be preserved:
301 Moved Permanentlyand302 Founddescribe redirects, but clients may change aPOSTinto aGETwhen following them.303 See Otherdirects the client to retrieve another resource, typically withGETorHEAD.307 Temporary Redirectand308 Permanent Redirectpreserve the request method when followed.
These distinctions matter for APIs, especially when a request has a body or causes a change. Do not use a redirect code as a substitute for returning the result of an API operation. If your API does redirect, make sure clients can safely follow it and understand the destination.
Common 4xx client and request errors
A 4xx response indicates that the request cannot be fulfilled as received. It does not necessarily mean the user personally made a mistake: the cause might be missing credentials, a stale version, or an application rule.
| Code | Typical use | Important detail |
|---|---|---|
400 Bad Request | The request is malformed or cannot be processed because of invalid request syntax or framing. | Often used by APIs as a broad invalid-request response; document the exact conditions. |
401 Unauthorized | Valid authentication credentials are missing or not accepted. | Despite its name, this is about authentication. Include a WWW-Authenticate challenge. |
403 Forbidden | The server understood the request but refuses to fulfill it. | Use when authentication does not change the outcome, such as when an authenticated caller lacks permission. |
404 Not Found | The target resource was not found, or the server is not willing to disclose that it exists. | A common choice for an unknown resource; it can also avoid revealing protected-resource existence. |
405 Method Not Allowed | The method is known but not supported for the target resource. | Include an Allow header listing the methods that are supported. |
409 Conflict | The request conflicts with the current state of the target resource. | Useful for state conflicts, such as attempting an operation that cannot be applied to the resource’s current state. |
410 Gone | The resource is no longer available and that condition is expected to be permanent. | Use only when you can make that distinction; otherwise 404 is often more suitable. |
412 Precondition Failed | A request condition, such as one expressed with a conditional header, was not met. | Useful for preventing changes based on a stale representation. |
415 Unsupported Media Type | The request content format is not supported for this method or resource. | Check the request’s Content-Type and the formats your endpoint accepts. |
422 Unprocessable Content | The content type and syntax are understood, but the instructions in the request content cannot be processed. | Often used for semantic validation errors; whether an API uses 422 or 400 for validation is a design convention. |
429 Too Many Requests | The client has sent too many requests in a given period. | A Retry-After header can tell clients when to try again. |
A useful distinction is 401 versus 403: use 401 when authentication is absent or invalid, and 403 when the request is understood but access is refused. In practice, systems sometimes use 404 instead of 403 to avoid disclosing that a protected resource exists; document that behavior so clients are not surprised.
For a validation failure, return details that help the caller fix the request without exposing internal implementation data. For example, identify the invalid field and expected format. The status code alone rarely provides enough context.
If you are unsure what a particular code means, use the HTTP status checker as a quick reference, then confirm that the code matches the behavior of your endpoint.
Common 5xx server errors
A 5xx response indicates that the server failed to fulfill an otherwise valid request. Avoid using these codes for ordinary validation failures or permission denials.
| Code | Typical use |
|---|---|
500 Internal Server Error | An unexpected server condition prevented the request from completing. |
501 Not Implemented | The server does not support the functionality required to fulfill the request. It is not a general code for an endpoint that returned an error. |
502 Bad Gateway | A server acting as a gateway or proxy received an invalid response from an upstream server. |
503 Service Unavailable | The server is temporarily unable to handle the request, such as during overload or maintenance. A Retry-After header can communicate when to retry. |
504 Gateway Timeout | A gateway or proxy did not receive a timely response from an upstream server. |
Clients may retry some server errors, but retrying is not always safe. A request that creates a payment or resource might have completed even if the client did not receive the response. Design retry behavior with idempotency and duplicate-request handling in mind; a status code alone cannot resolve uncertainty about whether an operation took effect.
A practical decision workflow
Use this sequence when designing an endpoint:
- Identify the outcome. Was the request completed, accepted for later work, redirected, or rejected?
- Choose the broad class. Use
2xxfor success or acceptance,3xxfor applicable redirection or cache behavior,4xxfor request or client-context problems, and5xxfor server failures. - Select the most specific accurate code. For example, distinguish
401from403, and409from a generic validation failure. - Check required headers and body behavior. Examples include
WWW-Authenticatewith401,Allowwith405, and no response content with204. - Define the error representation. Return stable, documented fields and useful messages. Do not expose stack traces, secrets, or internal infrastructure details.
- Document and test the contract. Ensure the API specification, implementation, and client expectations agree.
An illustrative response for a missing authentication challenge might look like this:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
Content-Type: application/json
{"error":"authentication_required"}
The JSON shape is an API design choice; the status code and authentication challenge carry the HTTP-level meaning. Adapt the challenge to the authentication scheme your service actually supports.
Common mistakes and pitfalls
- Returning
200for every outcome. Clients then have to inspect custom fields to learn whether the request succeeded, and generic HTTP tooling cannot interpret the result correctly. - Treating
401and403as interchangeable. Authentication and permission refusal are distinct conditions, and401has a protocol requirement for a challenge. - Using
404for every failure. It can be appropriate to conceal resource existence, but it obscures other cases such as invalid input or a state conflict. - Using
206to mean “some items succeeded.”206has range-response semantics. Use a documented application-level result for partial batch outcomes instead. - Returning a body with
204. A no-content response must not carry response content. Choose200if clients need a representation. - Assuming every
5xxshould be retried. Retrying can duplicate side effects or add load during an outage. Document safe retry behavior and use idempotency protections where appropriate. - Treating one validation mapping as a universal rule. Whether validation errors use
400or422is often a design convention. Consistency and clear documentation matter more than adopting a code without considering its semantics.
Recommendations for a consistent API
Create a status-code policy for your API and apply it across endpoints. Specify how the API handles authentication, authorization, missing resources, validation failures, conflicts, rate limits, and unexpected server failures. Include example responses and note any intentional exceptions.
Keep status codes aligned with the actual outcome, make error responses actionable, and ensure clients can distinguish permanent request problems from temporary service problems. When changing established behavior, consider how existing clients interpret both the code and the response body.
Conclusion
The right HTTP status code describes the outcome in terms clients and HTTP infrastructure can understand. Use specific success codes when they clarify what happened, choose client-error codes that accurately identify the problem, and reserve server-error codes for failures on the service side. Where the protocol leaves room for API design conventions, be consistent, document the choice, and test the complete response—including required headers and body behavior.
