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
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ $(DIRINCLUDES): models/headers-1.0.0.yaml $(DIRSCRIPTS)/generate-includes.sh
html: $(DIRINCLUDES) check assets pull
$(DOCKER) run --interactive --user=$$(id -u):$$(id -g) \
--volume=$(DIRWORK):$(DIRMOUNTS)/ \
$(ASCIIDOC) asciidoctor -D $(DIRMOUNTS)/$(DIRBUILDS) index.adoc;
$(ASCIIDOC) asciidoctor -r $(DIRMOUNTS)/extensions/custom-admonitions.rb \
-D $(DIRMOUNTS)/$(DIRBUILDS) index.adoc;

watch:
watchexec --exts adoc,css --ignore output -r make html
Expand Down
25 changes: 13 additions & 12 deletions chapters/api-operation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,25 @@ APIs (see <<219, API Audience definition>>). While this is optional
for <<219, component-internal>> APIs, we recommend doing so to profit from
our API management infrastructure and review services.

As described in https://cloud.docs.zalando.net/howtos/api-publishing/[How to publish API Specifications (internal_link)],
an API specification is published with the deployment of the implementing service
by copying it to the reserved `/zalando-apis` directory. The directory must only
contain _self-contained YAML files_ that each describe one API (exception see <<234>>).
*Legacy hint:* We prefer this deployment artifact-based method over the old
As described in https://cloud.docs.zalando.net/howtos/api-publishing/[How to publish API Specifications (internal_link)],
an API specification is published with the deployment of the implementing service
by copying it to the reserved `/zalando-apis` directory. The directory must only
contain _self-contained YAML files_ that each describe one API (exception see <<234>>).

Historic information: We prefer this deployment artifact-based method over the old
`.well-known/schema-discovery` service endpoint-based publishing process
(which still is supported for backward compatibility).

*Motivation:* In our dynamic and complex service infrastructure, it is important
NOTE: In our dynamic and complex service infrastructure, it is important

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's revert this change.

to provide API client developers a central place with online access to the API
specifications of all running applications. As a part of the infrastructure,
the API publishing process is used to detect API specifications and to make it
discoverable via
https://sunrise.zalando.net/apis?group=all[Sunrise (internal_link)] and the
the API publishing process is used to detect API specifications and to make it
discoverable via
https://sunrise.zalando.net/apis?group=all[Sunrise (internal_link)] and the
https://apis.zalando.net/[API Portal (internal_link)].

*Note:* APIs are discoverable only for recently running services. Hence, make sure
to always publish the API Specification as part of the service artifact deployment.
TIP: APIs are discoverable only for recently running services. Hence, make sure
to always publish the API Specification as part of the service artifact deployment.


[#193]
Expand All @@ -37,5 +38,5 @@ Owners of APIs used in production should monitor API service to get
information about its using clients. This information, for instance, is
useful to identify potential review partner for API changes.

Hint: A preferred way of client detection implementation is by logging
TIP: A preferred way of client detection implementation is by logging
of the client-id retrieved from the OAuth token.
2 changes: 1 addition & 1 deletion chapters/best-practices.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ the `query` filters should be transported via body - in the request as well as
in the response, while the pagination consistency should be ensured via the
`query_hash`.

*Note:* The efficiency of cursor-based pagination depends on the efficiency
TIP: The efficiency of cursor-based pagination depends on the efficiency
of the ordering index. In most cases a single ordering index, e.g. based on
`modified_at` is sufficient. Only in case of a low selectivity a combined
index including the `id` or other filter criteria is needed. This should be
Expand Down
4 changes: 2 additions & 2 deletions chapters/changelog.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Non-major changes are editorial-only changes or minor changes of existing guidel
Major changes are changes that come with additional obligations, or even change an existing guideline obligation.
Major changes are listed as "Rule Changes" below.

*Hint:* Most recent major changes might be missing in the list since we update it
NOTE: Most recent major changes might be missing in the list since we update it
only occasionally, not with each pull request, to avoid merge commits.
Please have a look at the
Please have a look at the
https://github.com/zalando/restful-api-guidelines/commits/main[commit list in Github]
to see a list of all changes.

Expand Down
11 changes: 6 additions & 5 deletions chapters/compatibility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ We strongly encourage using compatible API extensions and discourage versioning
(<<107>>) and consumers (<<108>>) enable us (having Postel’s Law in mind) to
make compatible changes without versioning.

*Note:* There is a difference between incompatible and breaking changes.
NOTE: There is a difference between incompatible and breaking changes.
Incompatible changes are changes that are not covered by the compatibility
rules below. Breaking changes are incompatible changes deployed into operation,
and thereby breaking running API consumers. Usually, incompatible changes are
Expand All @@ -30,7 +30,7 @@ situations it is possible to deploy incompatible changes in a non-breaking way,
if no API consumer is using the affected API aspects (see also <<deprecation,
Deprecation>> guidelines).

*Hint:* Please note that the compatibility guarantees are for the "on the wire"
Please note that the compatibility guarantees are for the "on the wire"
format. Binary or source compatibility of code generated from an API specification
is not covered by these rules. If client implementations update their
generation process to a new version of the API specification, it has to be
Expand Down Expand Up @@ -294,7 +294,7 @@ Media type versioning should...
Vary: Content-Type
----

NOTE: Until an incompatible change is necessary, it is recommended to stay
Until an incompatible change is necessary, it is recommended to stay
with the standard `application/json` media type without versioning.

Further reading:
Expand Down Expand Up @@ -367,8 +367,8 @@ delivery_method:
See <<240>> about enum value naming conventions – these apply here too.


**Important**:

[IMPORTANT]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's revert this change for better readability.

====
* API consumers must be prepared for the fact that also other values can be returned
with server responses (or be contained in consumed events), and implement a
fallback / default behavior for unknown new values, see <<108>>.
Expand All @@ -379,6 +379,7 @@ See <<240>> about enum value naming conventions – these apply here too.
* The list should not be reduced for inputs (that would be an incompatible change).
* Before additional values are accepted or returned, API owners should update the API description and extend
the `examples` list, see <<107>>.
====

(Note that the last 3 bullet points do not apply for uses of `examples` _without_ the
"Extensible enum." prefix in the description – here any value fitting the rest
Expand Down
13 changes: 8 additions & 5 deletions chapters/data-formats.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ You *must* use these formats, whenever applicable:
| `string` | `regex` | regular expressions as defined in {ECMA-262}[ECMA 262] | `"^[a-z0-9]+$"`
|=====================================================================

*Note:* Formats `bigint` and `decimal` have been added to the OpenAPI defined formats --
The formats `bigint` and `decimal` have been added to the numeric formats defined by OpenAPI --
see also <<171>> and <<169>> below.

We add further OpenAPI formats that are useful especially in an e-commerce environment
Expand All @@ -64,7 +64,7 @@ You *must* use these formats, whenever applicable:
| `string` | `gtin-13` | Global Trade Item Number -- see {GTIN}[GTIN] | `"5710798389878"`
|=====================================================================

*Remark:* Please note that this list of standard data formats is not exhaustive
NOTE: Please note that this list of standard data formats is not exhaustive
and everyone is encouraged to propose additions.


Expand Down Expand Up @@ -104,10 +104,13 @@ APIs {MUST} use the upper-case `T` as a separator between date and time and
upper-case `Z` at the end when generating `time` or `date-time` -- as opposed to lower-case `t`,
`z` which are accepted in {RFC-3339}[RFC 3339].

*Exception:* For passing date/time information via standard protocol headers,
[EXCEPTION]
====
For passing date/time information via standard protocol headers,
HTTP https://tools.ietf.org/html/rfc7231#section-7.1.1.1[RFC 7231] requires to
follow the date and time specification used by the Internet Message Format
https://tools.ietf.org/html/rfc5322[RFC 5322].
====

As defined by the standard, `time` and `date-time` relates to UTC and may be optionally
equipped with an offset.However, we recommend to only use times without offsets, for example `2015-05-28T14:07:17Z`
Expand All @@ -118,7 +121,7 @@ offsets are not easy to understand, different to time-zones and often not correc
Localization should be done locally by the services that provide
user interfaces, if required.

*Hint:* We discourage using numerical timestamps. It typically creates
TIP: We discourage using numerical timestamps. It typically creates
issues with precision, e.g. whether to represent a timestamp as 1460062925,
1460062925000 or 1460062925.000. `date-time` strings avoid this ambiguity.

Expand Down Expand Up @@ -250,7 +253,7 @@ identifiers. This gives us more flexibility to evolve the identifier naming
scheme. Accordingly, if used as identifiers, UUIDs should not be qualified
using a format property.

Hint: Usually, random UUID is used - see UUID version 4 in {RFC-4122}[RFC 4122].
TIP: Usually, random UUID is used - see UUID version 4 in {RFC-4122}[RFC 4122].
Though UUID version 1 also contains leading timestamps it is not reflected by
its lexicographic sorting. This deficit is addressed by
https://github.com/alizain/ulid[ULID] (Universally Unique Lexicographically
Expand Down
8 changes: 4 additions & 4 deletions chapters/deprecation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ During the deprecation phase, the producer should add a
8594 section 3]) header on each response affected by a deprecated element (see
<<187>>).

*Note:* We explicitly discourage the use of `Link` relation headers using
We explicitly discourage the use of `Link` relation headers using
`rel="sunset|deprecation"` as defined in {RFC-9754}#section-3[RFC 9745 section
3] and {RFC-8594}#section-6[RFC 8594 section 6] as these do not provide a
significant benefit over the documentation provided via the API specification.
Expand Down Expand Up @@ -107,10 +107,10 @@ include::../includes/deprecation.yaml[]
include::../includes/sunset.yaml[lines=3..-1]
----

*Note:* adding the {Deprecation} and {Sunset} header is not sufficient to gain
NOTE: Adding the {Deprecation} and {Sunset} header is not sufficient to gain
client consent to shut down an API or feature.

*Hint:* In earlier guideline versions, we used the {Warning} header to provide
*Historic information*: In earlier guideline versions, we used the {Warning} header to provide
the deprecation info to clients. However, {Warning} header has a less specific
semantics, will be obsolete with
https://tools.ietf.org/html/draft-ietf-httpbis-cache-06[draft: RFC HTTP
Expand All @@ -126,7 +126,7 @@ to get information about future sunset of APIs and API features (see <<189>>).
We recommend that client owners build alerts on this monitoring information to
ensure alignment with service owners on required migration task.

*Hint:* In earlier guideline versions, we used the `Warning` header to provide
*Historic information*: In earlier guideline versions, we used the `Warning` header to provide
the deprecation info (see hint in <<189>>).


Expand Down
50 changes: 27 additions & 23 deletions chapters/events.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ conform to the functional naming depending on the <<219, audience>> as follows:
<version> ::= [Vv][0-9.]* -- major version of non compatible schemas
----

*Hint:* The following convention (e.g. used by legacy STUPS infrastructure) is deprecated
*Historic information*: The following convention (e.g. used by legacy STUPS infrastructure) is deprecated
and *only* allowed for <<223, internal>> event type names:

[source,bnf]
Expand All @@ -287,7 +287,7 @@ and *only* allowed for <<223, internal>> event type names:
<application-id> ::= [a-z][a-z0-9-]* -- application identifier
----

**Note:** consistent naming should be used whenever the same entity is exposed
NOTE: Consistent naming should be used whenever the same entity is exposed
by a data change event and a RESTful API.


Expand Down Expand Up @@ -490,8 +490,8 @@ schema payload at the top-level of the document, with the
information (the contents of <<event-metadata,metadata>> are
described further down in this section).

*Note:*

[NOTE]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's revert this change.

====
* The General Event was called a _Business Event_ in earlier versions of
the guidelines. Implementation experience has shown that the
category's structure gets used for other kinds of events, hence the name
Expand All @@ -501,6 +501,7 @@ defining events that drive a business process.
* The Nakadi broker still refers to the General Category as the Business
Category and uses the keyword `business` for event type registration.
Other than that, the JSON structures are identical.
====

See <<201>> for more guidance on how to use the category.

Expand Down Expand Up @@ -673,11 +674,11 @@ the same `eid` value as the initial (possibly failed) attempt.
The `eid` supports event consumers in detecting and being robust against
event duplicates -- see <<214>>.

*Hint:* Using the same eid for retries can be ensured, for instance, by
generating a UUID either (i) as part of the event object construction and
using some form of intermediate persistence, like an event publish retry
queue, or (ii) via a deterministic function that computes the UUID value
from the event fields as input (without random salt).
TIP: Using the same eid for retries can be ensured, for instance, by
generating a UUID either (i) as part of the event object construction and
using some form of intermediate persistence, like an event publish retry
queue, or (ii) via a deterministic function that computes the UUID value
from the event fields as input (without random salt).


[#201]
Expand Down Expand Up @@ -725,7 +726,7 @@ event ordering the event type definition:
* *should* specify the `ordering_instance_ids` property to define which
field(s) represents the business entity instance identifier.

*Note:* The `ordering_instance_ids` restrict the scope in which the
NOTE: The `ordering_instance_ids` restrict the scope in which the
`ordering_key_fields` provide the strict order. If undefined, the ordering is
assumed to be provided in scope of all events.

Expand All @@ -736,13 +737,13 @@ The business ordering information can be provided – among other ways – by ma
* a strictly monotonically increasing sequence counter (maintained per partition
or event type).

*Hint:* timestamps are often a bad choice, since in distributed systems events
TIP: Timestamps are often a bad choice, since in distributed systems events
may occur at the same time, or clocks are not exactly synchronized, or
jump forward and backward to compensate drifts or leap-seconds. If you use anyway
timestamps to indicate event ordering, you _must_ carefully ensure that the designated
event order is not messed up by these effects and use UTC time zone format.

*Note:* The `received_at` and `partition_offset` metadata set by Nakadi typically is
The `received_at` and `partition_offset` metadata set by Nakadi typically is
different from the business event ordering, since (1) Nakadi is a distributed concurrent
system without atomic, ordered event creation and (2) the application's implementation
of event publishing may not exactly reflect the business order. The business ordering
Expand Down Expand Up @@ -780,9 +781,12 @@ to keep transactional dataset replicas in sync as source for data analytics.
For details about how to provide the data change ordering information,
please check <<203>>.

*Exception*: In situations where the transactional data is 'append only',
[EXCEPTION]
====
In situations where the transactional data is 'append only',
i.e. entity instances are only created, but never updated or deleted, the
ordering information may not be provided.
====


[#204]
Expand Down Expand Up @@ -843,18 +847,18 @@ is required by the business, and duplicates need to be explicitly ignored, where
customer behavior reporting (click rates) might not care about event duplicates
since accuracy in per-mille range is not needed.

*Hint:* Event consumers are supported in deduplication:
Event consumers are supported in deduplication:

* Deduplication can be based on the `eid` as mandatory standard for all events -- see <<211>>.
* Processing data change events to replay data changes and keep transactional
data copies in sync (CDC) is robust against duplicates because it is based on
data keys and change ordering -- see <<202>> and <<242>>.
* Data analytics users of the Data Lake are well advised to use curated data as a
source for analytics. Raw event datasets materialized in the lake are typically
cleaned-up (including deduplication and data synchronization) and provided as
transactional data copy or curated data products, for instance
https://curated-product-data.docs.zalando.net/[curated product data [internal link]] or
https://curated-sales-data.docs.zalando.net/[curated sales data [internal link]].
* Processing data change events to replay data changes and keep transactional
data copies in sync (CDC) is robust against duplicates because it is based on
data keys and change ordering -- see <<202>> and <<242>>.
* Data analytics users of the Data Lake are well advised to use curated data as a
source for analytics. Raw event datasets materialized in the lake are typically
cleaned-up (including deduplication and data synchronization) and provided as
transactional data copy or curated data products, for instance
https://curated-product-data.docs.zalando.net/[curated product data [internal link]] or
https://curated-sales-data.docs.zalando.net/[curated sales data [internal link]].

*Context:* One _source of duplicate events_ are the event producers, for instance,
due to publish call retries or publisher client failovers. Another source is
Expand Down
Loading
Loading