At a glance#
An error response carries the status code that says what happened and a JSON body with one error object. The body is the same for every API, so a client parses it once.
{
"error": {
"code": "quota_exceeded",
"message": "Your quota is exhausted. Retry after the time given in Retry-After, or upgrade your subscription.",
"request_id": "3f6d0c1e-9a47-4b3f-8d0e-5a1c7b2e9f10",
"docs_url": "https://api360.sa/docs/consumer/errors-and-retries#quota_exceeded"
}
}| Field | Type | Meaning |
|---|---|---|
code | string | A stable, machine-readable snake_case code. A client branches on it, so it never changes meaning. |
message | string | A sentence for a person. An API that serves Arabic and English answers in the language of the Accept-Language header. The text can be reworded; the code cannot. |
request_id | string | The value of the X-Request-Id response header, so a report to support points at one call. |
docs_url | string | The page that explains the code. |
code, message and request_id are always present. A provider that cannot link a page for a code still sends docs_url with the page of its API reference.
Status codes#
| Status | Use it when | Notes |
|---|---|---|
400 | The request is malformed or a parameter is out of range | Includes a per_page above the maximum |
401 | The credential is missing or not valid | |
403 | The caller is known and not allowed | |
404 | The resource or the route does not exist | |
409 | The request conflicts with the current state, or an Idempotency-Key is still in flight | |
422 | The request is well formed and cannot be processed, or an Idempotency-Key was reused with another request | |
429 | A quota or a rate limit is used up | Sends Retry-After and the RateLimit-* headers |
500, 502, 503, 504 | The service failed | 503 sends Retry-After; a client retries 502, 503 and 504 with backoff |
Use the status that fits; never answer 200 with an error body.
Headers#
| Header | On | Value |
|---|---|---|
Retry-After | 429, 503 | Seconds until a retry can succeed |
RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset | Responses that carry a quota or a rate limit | The limit, what is left, seconds to the reset |
X-Request-Id | Every response | The value in request_id |
Content-Language | Every error | The language of message |
In the specification#
Declare the error responses an operation can return, with one shared component, so the file describes the envelope once:
components:
responses:
Error:
description: The error envelope.
content:
application/json:
schema:
type: object
required: [error]
properties:
error:
type: object
required: [code, message, request_id]
properties:
code: { type: string }
message: { type: string }
request_id: { type: string }
docs_url: { type: string }Each operation lists at least one error response (400, 401, 404 and so on, or default) that points at it.
The gateway answers every error it produces itself, such as a missing key, an unknown route or an exhausted quota, in this envelope on all environments, with the error codes published as one catalogue. An error that a provider's own service returns is passed through unchanged.
Checked by#
| Rule | Severity | Checks |
|---|---|---|
api360-error-envelope-schema | error | A declared 4xx, 5xx or default response with a JSON body describes the envelope: an error object with string code, message, request_id and docs_url, the first three required |
api360-error-responses-declared | warn | Every operation declares at least one error response |
See also#
- Errors, status codes and retries: what the gateway answers today.
- Idempotency: the
409and422of a repeated key. - Pagination: the
400for aper_pageabove the maximum.