Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 156 additions & 54 deletions chapters/http-status-codes-and-errors.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -461,16 +461,16 @@ 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.
unless a non-item-specific failure occurs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't remove the leading spaces -- they are needed for formating


* 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.
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.
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_!
Expand Down Expand Up @@ -529,23 +529,23 @@ 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.
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.
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.
allowed to make in this window.
* `X-RateLimit-Remaining`: The number of requests allowed in the current
window.
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.
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
Expand All @@ -564,52 +564,32 @@ number of requests made within a given window for each named entity.
== {MUST} support problem JSON

{RFC-9457}[RFC 9457] 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).
Comment on lines -567 to -573
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep this paragraph.


*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.
`application/problem+json` to provide a standardized format for expressing
errors in API responses. It serves several purposes:

*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.
* Developers: to debug, diagnose and resolve issues during API integration or
operation
* Client applications: to inform users about errors (in user interface) and to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem object is provided for developers, not for application and UI users.
I would dismiss this and the above additions.

support automated processing and error handling when appropriate.

The OpenAPI schema definition of the Problem JSON object can be found
==== Problem object specification
The Problem object is specified in the OpenAPI
schema definition
https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml[on
GitHub]. You can reference it by using:
GitHub].

[source,yaml]
----
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:** If a member's value type does not match the specified type,
the member MUST be ignored -- i.e., processing will continue as if
the member had not been present.
Comment on lines +581 to +583
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**Note:** If a member's value type does not match the specified type,
the member MUST be ignored -- i.e., processing will continue as if
the member had not been present.
**Note:** If a field value does not match the specified type,
it MUST be ignored -- i.e., processing will continue as if
the field had not been provided.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better delete it here -- this aspect is already addressed below.


*Note:* Problem `type` and `instance` identifiers in our APIs are not meant
to be resolved. {RFC-9457}[RFC 9457] encourages that problem types are URI
{RFC-9457}[RFC 9457] encourages that problem types are URI
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old wording is IMO clearer.

references that point to human-readable documentation, *but* we deliberately
decided against that, as all important parts of the API must be documented
using <<101, 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-9457}[RFC 9457] we proposed to use
In order to stay compatible with {RFC-9457}[RFC 9457] we recommend to use
https://tools.ietf.org/html/rfc3986#section-4.1[relative URI references]
usually defined by `absolute-path [ '?' query ] [ '#' fragment ]` as simplified
identifiers in `type` and `instance` fields:
Expand All @@ -622,9 +602,131 @@ identifiers in `type` and `instance` fields:
*Hint:* The use of https://tools.ietf.org/html/rfc3986#section-4.3[absolute
URIs] is not forbidden but strongly discouraged. If you use absolute URIs,
please reference
https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.0.yaml#/Problem[problem-1.0.0.yaml#/Problem]
https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem[problem-1.0.1.yaml#/Problem]
instead.

==== Usage of Problem Object
Clients may use, but *should be robust and not* depend on the Problem
properties being present or having specific values of specific types.
The examples of such cases are:

- response might be created by infrastructure components (and have a different
response format, comparing to the guidelines)
- response might be created by a service that is unable to comply with the
guidelines due to certain error situations

In cases where the Problem Object lacks the required information, clients must
implement fallback mechanisms, defaulting to reasonable behavior similar to
handling errors without a Problem Object provided.

The OpenAPI schema definition of the Problem JSON object can be found
https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml[on
GitHub]. You can reference it by using:

[source,yaml]
----
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'
----

Comment on lines +622 to +636
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be moved to the Problem object Specification above.

*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.

==== Client processing of Problem Object
Problem details are often not described explicitly in the API and may evolve
over time.

Unless the API defines and enumerates stable values for `type` and `instance`
with clear semantics, these fields *should not* be relied upon for client-side
automated decisions.

The following guidelines offer best practices for utilizing type in automated
processing:

1. Property `type` may be used by clients to make automatic decisions in
certain failure modes. The `title` property serves as a concise,
human-readable summary of the type. It is particularly helpful for debugging
and serves as an engineer-readable shorthand for the problem type.

2. Clients may use these fields to drive automated actions if the API
explicitly defines the semantics of `type` and `instance` and enumerates
stable values. This can be achieved by extending the Problem JSON object and
associating an x-extensible-enum with the type property.

3. Clients must handle scenarios where the type is absent or unrecognized and
fallback to default behaviors.

4. For collections of related APIs, using shared type values for similar errors
and distinct values for different errors simplifies automated processing and
error handling for clients working across APIs.
Comment on lines +666 to +668
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a hint for the clients, but for the servers is it?
It is unclear for me, and I not sure we should give this hint.


*Note:* Include descriptions for each known error that can happen directly in
the specification or reference external documentation to clarify their meanings
and intended use.

==== Extensions of Problem Object schema
APIs can define custom fields in the Problem Object to provide more context
to meet specific application needs.
The custom fields should not conflict with the standard fields.
To extend the Problem Object, the API specification must define the custom
Problem, which would include Problem object members and custom ones. The
custom Problem can be used in the API specification as a reference, same as
a standard Problem object.
Example:
[source,yaml]
----
components:
schemas:
Problem:
type: object
properties:
type:
type: string
format: uri
example: "https://example.com/errors/invalid-parameter"
title:
type: string
example: "Invalid Request Parameter"
status:
type: integer
example: 400
detail:
type: string
example: "The 'color' parameter is invalid"

CustomProblem:
allOf:
- $ref: "#/components/schemas/Problem"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply reference to the standard definition?

properties:
errorCode:
type: string
example: "ERROR12345"
flowId:
type: string
example: "2914eefe-814e-4100-a332-42bac3352524"
----

*Note:* In case when client does not support some of the fields,
they should be ignored.

==== Handling Multiple Errors in Batch/Bulk Responses
When an API processes batch requests, multiple errors may occur.
To ensure clarity and usability, the response should structure these errors
in a way that allows clients to identify and handle individual failures.

Depending on the use-case the response can be structured in two ways:

- as an array of Problem objects where each entry in the array represents an
individual error related to a specific request item.
- as a map where associated value contains the corresponding Problem object for
that specific request item.

[#177]
== {MUST} not expose stack traces
Expand All @@ -643,9 +745,9 @@ redirection to migrate clients to a new service location. However, this is
better accomplished by one of the following.

1. Changing the clients to use the new location in the first place, avoiding
the need for redirection.
the need for redirection.
2. Redirecting the traffic behind the API layer (e.g. in the reverse proxy or
the app itself) without the client having to be involved.
the app itself) without the client having to be involved.
3. Deprecating the endpoint and removing it as described in <<deprecation>>.

For idempotent {POST} cases, where you want to inform the client that a resource
Expand Down
33 changes: 21 additions & 12 deletions models/problem-1.0.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ Problem:
type: string
format: uri-reference
description: >
A URI reference that uniquely identifies the problem type only in the
context of the provided API. Opposed to the specification in RFC-9457,
it is neither recommended to be dereferenceable and point to a
human-readable documentation nor globally unique for the problem type.
An optional member, URI identifying the problem type, typically more
specific than the HTTP status code. In many cases, an error code can be
placed in the type property. It may support automated client decisions
in certain failure modes. If the type doesn’t provide additional
information, it can be omitted (defaulting to `"about:blank"`).
default: 'about:blank'
example: '/some/uri-reference'
examples:
- 'https://example.com/errors/invalid-parameter'
- 'https://example.com/errors/ERR12345' # with error code
title:
type: string
description: >
A short summary of the problem type. Written in English and readable
for engineers, usually not suited for non technical stakeholders and
not localized.
example: some title for the error situation
A short, human-readable summary of the problem type. It *SHOULD NOT*
change from occurrence to occurrence of the problem. Written in English
and readable for engineers, usually not suited for non-technical
stakeholders and not localized.
example: 'Invalid parameter'
status:
type: integer
format: int32
Expand All @@ -27,19 +31,24 @@ Problem:
minimum: 100
maximum: 600
exclusiveMaximum: true
example: 400
detail:
type: string
description: >
A human readable explanation specific to this occurrence of the
problem that is helpful to locate the problem and give advice on how
to proceed. Written in English and readable for engineers, usually not
suited for non technical stakeholders and not localized.
example: some description for the error situation
example: 'The \"color\" parameter is invalid'
instance:
type: string
format: uri-reference
description: >
A URI reference that identifies the specific occurrence of the problem,
e.g. by adding a fragment identifier or sub-path to the problem type.
May be used to locate the root of this problem in the source code.
example: '/some/uri-reference#specific-occurrence-context'
This field should serve the purpose of defining a clear error instance
from which a developer can determine the source location of the error.
Additionally, it may include relevant contextual information, such as
parameters associated with the error and optionally `Flow-ID` for
debugging purposes.
example: '/errors/12345'