Hypermedia

Must: Use REST Maturity Level 2

We strive for a good implementation of REST Maturity Level 2 as it enables us to build resource-oriented APIs that make full use of HTTP verbs and status codes. You can see this expressed by many rules throughout these guidelines, e.g.:

Although this is not HATEOAS, it should not prevent you from designing proper link relationships in your APIs as stated in rules below.

Could: Use REST Maturity Level 3 - HATEOAS

We do not generally recommend to implement REST Maturity Level 3. HATEOAS comes with additional API complexity without real value in our SOA context where client and server interact via REST APIs and provide complex business functions as part of our e-commerce platform.

Our major concerns regarding the promised advantages of HATEOAS (see also RESTistential Crisis over Hypermedia APIs, Why I Hate HATEOAS and others):

  • We follow API First principle with APIs explicitly defined outside the code with standard specification language. HATEOAS does not really add value for SOA client engineers in terms of API self-descriptiveness: a client anyway finds necessary links and description how to use methods on endpoints depending on its state in the API definition.
  • Generic HATEOAS clients which need no prior knowledge about APIs and explore API capabilities based on hypermedia information provided, is a theoretical concept that we haven't seen working in practise and does not fit to our SOA set-up. The OpenAPI description format (and tooling based on OpenAPI) doesn't provide sufficient support for HATEOAS either.
  • In practice relevant HATEOAS approximations (e.g. following specifications like HAL or JSON API) support API navigation by abstracting from URL endpoint and HTTP method aspects via link types. So, Hypermedia does not prevent clients from required manual changes when domain model changes over time.
  • Hypermedia make sense for humans, less for SOA machine clients. We would expect use cases where it may provide value more likely in the frontend and human facing service domain.
  • Hypermedia does not prevent API clients to implement shortcuts and directly target resources without 'discovering' them

However, we do not forbid HATEOAS; you could use it, if you checked its limitations and still see clear value for your usage scenario that justifies its additional complexity. If you use HATEOAS please share experience and present your findings in the API Guild [internal link].

Must: Use a well-defined subset of HAL

Links to other resources must be defined exclusively using HAL and preferably using standard link relations.

Clients and Servers are required to support _links with its href and rel attributes, not only at the root level but also in nested objects. To reduce the effort needed by clients to process hypertext data from servers it's not recommended to serve data with CURIEs, URI templates or embedded resources. Nor is it required to support the HAL media type application/hal+json. The following snippet specifies the HAL link structure in JSONSchema:

Link:
  type: object
  properties:
    href:
      type: string
      format: uri
      example: https://api.example.com/sales-orders/10101058747628
  required:
    - href
Links:
  type: object
  description: |
    Values can be either a single Link or an array of Links
    See https://docs.pennybags.zalan.do/ for more.
  additionalProperties:
    # keys are link relations
    type: array
    items:
      $ref: '#/definitions/Link'
  example:
    'self':
      - href: https://api.example.com/sales-orders/10101058747628

We opted for this subset of HAL after conducting a comparison of different hypermedia formats based on properties like:

  • Simplicity: resource link syntax and concepts are easy to understand and interpret for API clients.
  • Compatibility: introducing and adding links to resources is not breaking existing API clients.
  • Adoption: use in open-source libraries and tools as well as other companies
  • Docs: degree of good documentation

Standard Simplicity Compatibility Adoption Primary Focus Docs
HAL Subset Links and relationships
HAL Links and relationships
JSON API Response format
JSON-LD ? Link data ?
Siren Entities and navigation
Collection+JSON Collections and queries

We define HAL links to be extensible, i.e. to contain additional properties if needed. For consistency extensions should reuse attributes from the Link header.

Interesting articles for comparisons of different hypermedia formats:

We don't allow the use of the Link Header defined by RFC 5988 in conjunction with JSON media types, and favor HAL instead. The primary reason is to have a consistent place for links as well as the better support for links in JSON payloads compared to the uncommon link header syntax.

You should consider using a custom link relation if and only if standard link relations are not sufficient to express a relation. Related or even embedded (sub-) resources should be linked via “meta link attributes” within the response payload; use the following HAL compliant syntax:

{
  ...
  “_links”: {
    “my-relation”: {
      “href”: “https://service.team.zalan.do/my-entities/123”
    }
  }
}

In earlier versions of this rule we proposed URIs but dropped that in favor of readability. Since link relations are properties in the _links object you should define and describe them individually in the API specification.