You must only use official HTTP status codes consistently with their intended semantics. Official HTTP status codes are defined via RFC standards and registered in the IANA Status Code Registry. Main RFC standards are {RFC-7231}#section-6[RFC7231 - HTTP/1.1: Semantics] (or {RFC-7235}#page-6[RFC7235 - HTTP/1.1: Authentication]) and {RFC-6585}[RFC 6585 - HTTP: Additional Status Codes] (and there are upcoming new ones, e.g. draft legally-restricted-status). An overview on the official error codes provides Wikipedia: HTTP status codes (which also lists some unofficial status codes, e.g. defined by popular web servers like Nginx, that we do not suggest to use).
APIs should define the functional, business view and abstract from implementation aspects. Success and error responses are a vital part to define how an API is used correctly.
Therefore, you must define all success and service specific error responses in your API specification. Both are part of the interface definition and provide important information for service clients to handle standard as well as exceptional situations. Error code response descriptions should provide information about the specific conditions that lead to the error, especially if these conditions can be changed by how the endpoint is used by the clients.
API designers should also think about a troubleshooting board as part of the associated online API documentation. It provides information and handling guidance on application-specific errors and is referenced via links from the API specification. This can reduce service support tasks and contribute to service client and provider performance.
Exception: Standard errors, especially for client side error codes like 401 (unauthenticated), 403 (unauthorized) or 404 (not found) that can be inferred straightforwardly from the specific endpoint definition need not to be individually defined. Instead you can combine multiple error response specifications with the default pattern below. However, you should not use it and explicitly define the error code as soon as it provides endpoint specific indications for clients of how to avoid calling the endpoint in the wrong way, or be prepared to react on specific error situation.
responses:
...
default:
description: error occurred - see status code and problem object for more information.
content:
"application/problem+json":
schema:
$ref: 'https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem'
The most commonly used codes are best understood and listed below as subset of the official HTTP status codes and consistent with their semantics in the RFCs. We avoid less commonly used codes that easily create misconceptions due to less familiar semantics and API specific interpretations.
Important: As long as your HTTP status code usage is well covered by the semantic defined here, you should not describe it to avoid an overload with common sense information and the risk of inconsistent definitions. Only if the HTTP status code is not in the list below or its usage requires additional information aside the well defined semantic, the API specification must provide a clear description of the HTTP status code in the response.
Code | Meaning | Methods |
---|---|---|
OK - this is the most general success response and used, if the more specific codes below are not applicable. |
{ALL} |
|
Created - Returned on successful resource creation.
{201} is returned with or without response payload (unlike {200} / {204}).
We recommend to additionally return the created resource URL via the |
{POST}, {PUT} |
|
Accepted - The request was successful and will be processed asynchronously. |
{POST}, {PUT}, {PATCH}, {DELETE} |
|
No content - Returned instead of {200}, if no response payload is returned. |
{PUT}, {PATCH}, {DELETE} |
|
Multi-Status - The response body contains status information for multiple different parts of a batch/bulk request (see {MUST} use code 207 for batch or bulk requests). |
{POST}, ({DELETE}) |
Code | Meaning | Methods |
---|---|---|
Moved Permanently - This and all future requests should be directed to the given URI. |
{ALL} |
|
See Other - The response to the request can be found under another URI using a {GET} method. |
{POST}, {PUT}, {PATCH}, {DELETE} |
|
Not Modified - indicates that a conditional GET or HEAD request would have resulted in 200 response if it were not for the fact that the condition evaluated to false, i.e. resource has not been modified since the date or version passed via request headers If-Modified-Since or If-None-Match. |
{GET}, {HEAD} |
Code | Meaning | Methods |
---|---|---|
Bad request - unspecific client error indicating that the server cannot process the request due to something that is perceived to be a client error (e.g. malformed request syntax, invalid request). Should also be delivered in case of input payload fails business logic / semantic validation (instead of using status code 422). |
{ALL} |
|
Unauthorized - actually "Unauthenticated": credentials are not valid for the target resource. User must log in. |
{ALL} |
|
Forbidden - the user is not authorized to use this resource. |
{ALL} |
|
Not found - the resource is not found. |
{ALL} |
|
Method Not Allowed - the method is not supported, see {OPTIONS}. |
{ALL} |
|
Not Acceptable - resource can only generate content not acceptable according to the Accept headers sent in the request. |
{ALL} |
|
Request timeout - the server times out waiting for the resource. |
{ALL} |
|
Conflict - request cannot be completed due to conflict with the current state of the target resource. For example, you may get a {409} response when updating a resource that is older than the existing one on the server, resulting in a version control conflict. Hint, you should not return {409}, but {200} or {204} in case of successful robust creation of resources (via {PUT} or {POST}), if the resource already exists. |
{POST}, {PUT}, {PATCH}, {DELETE} |
|
Gone - resource does not exist any longer, e.g. when accessing a resource that has intentionally been deleted. |
{ALL} |
|
Precondition Failed - returned for conditional requests, e.g. {If-Match} if the condition failed. Used for optimistic locking. |
{PUT}, {PATCH}, {DELETE} |
|
Unsupported Media Type - e.g. clients sends request body without content type. |
{POST}, {PUT}, {PATCH}, {DELETE} |
|
Locked - Pessimistic locking, e.g. processing states. |
{PUT}, {PATCH}, {DELETE} |
|
Precondition Required - server requires the request to be conditional, e.g. to make sure that the "lost update problem" is avoided (see [181]). |
{ALL} |
|
Too many requests - the client does not consider rate limiting and sent too many requests (see {MUST} use code 429 with headers for rate limits). |
{ALL} |
Code | Meaning | Methods |
---|---|---|
Internal Server Error - a generic error indication for an unexpected server execution problem (here, client retry may be sensible) |
{ALL} |
|
Not Implemented - server cannot fulfill the request (usually implies future availability, e.g. new feature). |
{ALL} |
|
Service Unavailable - service is (temporarily) not available (e.g. if a required component or downstream service is not available) — client retry may be sensible. If possible, the service should indicate how long the client should wait by setting the {Retry-After} header. |
{ALL} |
You must use the most specific HTTP status code when returning information about your request processing status or error situations.
Some APIs are required to provide either batch or bulk requests using {POST} for performance reasons, i.e. for communication and processing efficiency. In this case services may be in need to signal multiple response codes for each part of a batch or bulk request. As HTTP does not provide proper guidance for handling batch/bulk requests and responses, we herewith define the following approach:
-
A batch or bulk request always responds with HTTP status code {207} unless a non-item-specific failure occurs.
-
A batch or bulk request may return {4xx}/{5xx} status codes, if the failure is non-item-specific and cannot be restricted to individual items of the batch or bulk request, e.g. in case of overload situations or general service failures.
-
A batch or bulk response with status code {207} always returns as payload a multi-status response containing item specific status and/or monitoring information for each part of the batch or bulk request.
Note: These rules apply even in the case that processing of all individual parts fail or each part is executed asynchronously!
The rules are intended to allow clients to act on batch and bulk responses in
a consistent way by inspecting the individual results. We explicitly reject
the option to apply {200} for a completely successful batch as proposed in
Nakadi’s POST
/event-types/{name}/events
as short cut without inspecting the result, as we
want to avoid risks and expect clients to handle partial
batch failures anyway.
The bulk or batch response may look as follows:
BatchOrBulkResponse:
description: batch response object.
type: object
properties:
items:
type: array
items:
type: object
properties:
id:
description: Identifier of batch or bulk request item.
type: string
status:
description: >
Response status value. A number or extensible enum describing
the execution status of the batch or bulk request items.
type: string
x-extensible-enum: [...]
description:
description: >
Human readable status description and containing additional
context information about failures etc.
type: string
required: [id, status]
Note: while a batch defines a collection of requests triggering independent processes, a bulk defines a collection of independent resources created or updated together in one request. With respect to response processing this distinction normally does not matter.
APIs that wish to manage the request rate of clients must use the {429} (Too Many Requests) response code, if the client exceeded the request rate (see {RFC-6585}[RFC 6585]). Such responses must also contain header information providing further details to the client. There are two approaches a service can take for header information:
-
Return a {Retry-After} header indicating how long the client ought to wait before making a follow-up request. The Retry-After header can contain a HTTP date value to retry after or the number of seconds to delay. Either is acceptable but APIs should prefer to use a delay in seconds.
-
Return a trio of
X-RateLimit
headers. These headers (described below) allow a server to express a service level in the form of a number of allowing requests within a given window of time and when the window is reset.
The X-RateLimit
headers are:
-
X-RateLimit-Limit
: The maximum number of requests that the client is allowed to make in this window. -
X-RateLimit-Remaining
: The number of requests allowed in the current window. -
X-RateLimit-Reset
: The relative time in seconds when the rate limit window will be reset. Beware that this is different to Github and Twitter’s usage of a header with the same name which is using UTC epoch seconds instead.
The reason to allow both approaches is that APIs can have different needs. Retry-After is often sufficient for general load handling and request throttling scenarios and notably, does not strictly require the concept of a calling entity such as a tenant or named account. In turn this allows resource owners to minimise the amount of state they have to carry with respect to client requests. The 'X-RateLimit' headers are suitable for scenarios where clients are associated with pre-existing account or tenancy structures. 'X-RateLimit' headers are generally returned on every request and not just on a 429, which implies the service implementing the API is carrying sufficient state to track the number of requests made within a given window for each named entity.
{RFC-7807}[RFC 7807] defines a Problem JSON object using the media type
application/problem+json
to provide an extensible human and machine readable
failure information beyond the HTTP response status code to transports the
failure kind (type
/ title
) and the failure cause and location (instant
/
detail
). To make best use of this additional failure information, every
endpoints must be capable of returning a Problem JSON on client usage errors
({4xx} status codes) as well as server side processing errors ({5xx} status
codes).
Note: Clients must be robust and not rely on a Problem JSON object being returned, since (a) failure responses may be created by infrastructure components not aware of this guideline or (b) service may be unable to comply with this guideline in certain error situations.
Hint: The media type application/problem+json
is often not implemented as
a subset of application/json
by libraries and services! Thus clients need to
include application/problem+json
in the {Accept}-Header to trigger delivery
of the extended failure information.
The OpenAPI schema definition of the Problem JSON object can be found on GitHub. You can reference it by using:
responses:
503:
description: Service Unavailable
content:
"application/problem+json":
schema:
$ref: 'https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem'
You may define custom problem types as extensions of the Problem JSON object if your API needs to return specific, additional, and more detailed error information.
Note: Problem type
and instance
identifiers in our APIs are not meant
to be resolved. {RFC-7807}[RFC 7807] encourages that problem types are URI
references that point to human-readable documentation, but we deliberately
decided against that, as all important parts of the API must be documented
using OpenAPI anyway. In addition, URLs tend to be fragile and not
very stable over longer periods because of organizational and documentation
changes and descriptions might easily get out of sync.
In order to stay compatible with {RFC-7807}[RFC 7807] we proposed to use
relative URI references
usually defined by absolute-path [ '?' query ] [ '#' fragment ]
as simplified
identifiers in type
and instance
fields:
-
/problems/out-of-stock
-
/problems/insufficient-funds
-
/problems/user-deactivated
-
/problems/connection-error#read-timeout
Hint: The use of absolute URIs is not forbidden but strongly discouraged. If you use absolute URIs, please reference problem-1.0.0.yaml#/Problem instead.
Stack traces contain implementation details that are not part of an API, and on which clients should never rely. Moreover, stack traces can leak sensitive information that partners and third parties are not allowed to receive and may disclose insights about vulnerabilities to attackers.