Skip to content

Latest commit

 

History

History
263 lines (213 loc) · 9.88 KB

meta-information.adoc

File metadata and controls

263 lines (213 loc) · 9.88 KB

REST Basics - Meta information

{MUST} contain API meta information

API specifications must contain the following OpenAPI meta information to allow for API management:

  • #/info/title as (unique) identifying, functional descriptive name of the API

  • #/info/version to distinguish API specifications versions following semantic rules

  • #/info/description containing a proper description of the API

  • #/info/contact/{name,url,email} containing the responsible team

Following OpenAPI extension properties must be provided in addition:

  • #/info/x-api-id unique identifier of the API (see rule 215)

  • #/info/x-audience intended target audience of the API (see rule 219)

{MUST} use semantic versioning

OpenAPI allows to specify the API specification version in #/info/version. To share a common semantic of version information we expect API designers to comply to Semantic Versioning 2.0 rules 1 to 8 and 11 restricted to the format <MAJOR>.<MINOR>.<PATCH> for versions as follows:

  • Increment the MAJOR version when you make incompatible API changes after having aligned the changes with consumers,

  • Increment the MINOR version when you add new functionality in a backwards-compatible manner, and

  • Optionally increment the PATCH version when you make backwards-compatible bug fixes or editorial changes not affecting the functionality.

Additional Notes:

  • Pre-release versions (rule 9) and build metadata (rule 10) must not be used in API version information.

  • While patch versions are useful for fixing typos etc, API designers are free to decide whether they increment it or not.

  • API designers should consider to use API version 0.y.z (rule 4) for initial API design.

Example:

openapi: 3.0.1
info:
  title: Parcel Service API
  description: API for <...>
  version: 1.3.7
  <...>

{MUST} provide API identifiers

Each API specification must be provisioned with a globally unique and immutable API identifier. The API identifier is defined in the info-block of the OpenAPI specification and must conform to the following definition:

/info/x-api-id:
  type: string
  format: urn
  pattern: ^[a-z0-9][a-z0-9-:.]{6,62}[a-z0-9]$
  description: |
    Mandatory globally unique and immutable API identifier. The API
    id allows to track the evolution and history of an API specification
    as a sequence of versions.

API specifications will evolve and any aspect of an OpenAPI specification may change. We require API identifiers because we want to support API clients and providers with API lifecycle management features, like change trackability and history or automated backward compatibility checks. The immutable API identifier allows the identification of all API specification versions of an API evolution. By using API semantic version information or API publishing date as order criteria you get the version or publication history as a sequence of API specifications.

Note: While it is nice to use human readable API identifiers based on self-managed URNs, it is recommend to stick to a UUID (freshly generated when first creating the API) to relief API designers from any urge of changing the API identifier while evolving the API. Do not copy an API unless you immediately change the API identifier in it!

Example:

openapi: 3.0.1
info:
  x-api-id: d0184f38-b98d-11e7-9c56-68f728c1ba70
  title: Parcel Service API
  description: API for <...>
  version: 1.5.8
  <...>

{MUST} provide API audience

Each API must be classified with respect to the intended target audience supposed to consume the API, to facilitate differentiated standards on APIs for discoverability, changeability, quality of design and documentation, as well as permission granting. We differentiate the following API audience groups with clear organisational and legal boundaries:

component-internal

This is often referred to as a team internal API or a product internal API. The API consumers with this audience are restricted to applications of the same functional component which typically represents a specific product with clear functional scope and ownership. All services of a functional component / product are owned by a specific dedicated owner and engineering team(s). Typical examples of component-internal APIs are APIs being used by internal helper and worker services or that support service operation.

business-unit-internal

The API consumers with this audience are restricted to applications of a specific product portfolio owned by the same business unit.

company-internal

The API consumers with this audience are restricted to applications owned by the business units of the same the company (e.g. Zalando company with Zalando SE, Zalando Payments SE & Co. KG. etc.)

external-partner

The API consumers with this audience are restricted to applications of business partners of the company owning the API and the company itself.

external-public

APIs with this audience can be accessed by anyone with Internet access.

Note: a smaller audience group is intentionally included in the wider group and thus does not need to be declared additionally.

The API audience is provided as API meta information in the info-block of the OpenAPI specification and must conform to the following specification:

/info/x-audience:
  type: string
  x-extensible-enum:
    - component-internal
    - business-unit-internal
    - company-internal
    - external-partner
    - external-public
  description: |
    Intended target audience of the API. Relevant for standards around
    quality of design and documentation, reviews, discoverability,
    changeability, and permission granting.

Note: Exactly one audience per API specification is allowed. For this reason a smaller audience group is intentionally included in the wider group and thus does not need to be declared additionally. If parts of your API have a different target audience, we recommend to split API specifications along the target audience — even if this creates redundancies ({api-audience-narrative}[rationale (internal_link)]).

Example:

openapi: 3.0.1
info:
  x-audience: company-internal
  title: Parcel Helper Service API
  description: API for <...>
  version: 1.2.4
  <...>

For details and more information on audience groups see the {api-audience-narrative}[API Audience narrative (internal_link)].

{MUST-SHOULD-MAY} use functional naming schema

Functional naming is a powerful, yet easy way to align global resources as host, permission, and event names within an application landscape. It helps to preserve uniqueness of names while giving readers meaningful context information about the addressed component. Besides, the most important aspect is, that it allows to keep APIs stable in the case of technical and organizational changes (Zalando for example maintains an internal naming convention).

A unique functional-name is assigned to each functional component serving an API. It is built of the domain name of the functional group the component is belonging to and a unique a short identifier for the functional component itself:

<functional-name>      ::= <functional-domain>-<functional-component>
<functional-domain>    ::= [a-z][a-z0-9-]* -- managed functional group of components
<functional-component> ::= [a-z][a-z0-9-]* -- name of API owning functional component

Depending on the API audience, you must/should/may follow the functional naming schema for hostnames and event names (and also permission names, in future) as follows:

Functional Naming

Audience

must

external-public, external-partner

should

company-internal, business-unit-internal

may

component-internal

Please see the following rules for detailed functional naming patterns: * {MUST} follow naming convention for hostnames * [213]

Internal Guideance: You must use the simple {functional-name-registry}[functional name registry (internal_link)] to register your functional name before using it. The registry is a centralized infrastructure service to ensure uniqueness of your functional names (and available domains — including subdomains) and to support hostname DNS resolution.
Hint: Due to lexicalic restrictions of DNS names there is no specific separator to split a functional name into (sub) domain and component; this knowledge is only managed in the registry.

{MUST} follow naming convention for hostnames

Hostnames in APIs must, respectively should conform to the functional naming depending on the audience as follows (see {MUST-SHOULD-MAY} use functional naming schema for details and <functional-name> definition):

<hostname>             ::= <functional-hostname> | <application-hostname>

<functional-hostname>  ::= <functional-name>.zalandoapis.com

Hint: The following convention (e.g. used by legacy STUPS infrastructure) is deprecated and only allowed for hostnames of component-internal APIs:

<application-hostname> ::= <application-id>.<organization-unit>.zalan.do
<application-id>       ::= [a-z][a-z0-9-]*  -- application identifier
<organization-id>      ::= [a-z][a-z0-9-]*  -- organization unit identifier, e.g. team identifier

Exception: There are legacy hostnames used for APIs with external-partner audience which may not follow this rule due to backward compatibility constraints. The API Linter maintains an allow-list for these exceptions (including e.g. api.merchants.zalando.com and api-sandbox.merchants.zalando.com).