Hypermedia APIs

When you visit a web page, the links on that page connect to related resources or inform you of what actions you can take next. In a web application, the server provides the links. For example, from the web page Roy Fielding, the server embeds related links, such as links to the pages HTML, World Wide Web Consortium, or Representational state transfer, so that the reader does not have to build such links themselves.

Just as web links make browsing the the web more convenient, hypermedia is an essential component of true REST APIs. Hypermedia is simply the inclusion of links in a REST API response. These links from hypermedia APIs allows clients to be more dynamic by adapting to new links supplied by the service. More business logic is located in one place - the API services - rather than dispersed (perhaps inconsistently) among multiple clients.

There are many useful resources which describe hypermedia APIs, such as Improve API Experience using Hypermedia.

HATEOAS

HATEOAS is an initialism for Hypermedia as the Engine of Application State, coined by Roy Fielding. HATEOAS means hypermedia-driven APIs or simply hypermedia APIs, where the representations passed between the client and server contain links and data representing the state of the application. In hypermedia APIs, the service provides the related links, so that clients do not have to generate the links.

In Apiture APIs, all resource representations contain a "self" link which is the URI of that resource. When fetching a page of resources from large a collection, each item in the response array contains a “self” link which allows the client to locate and operate on the individual resource. When the client performs a GET on that link’s href URL, the response will contain additional links with more operations that apply to that specific resource.

Example: Approving or Rejecting a Document

The Approvals API allows financial institution staff to review and either approve, return, waive, or reject documents attached to a bank account application, Examples of such include an individual’s driver’s license for identification purpose, or a company’s articles of incorporation. Each document is assigned an approval resource with a unique URI. When the admin client uses the GET operation on the approval resource URI, the response contains several links corresponding to actions the authenticated user may perform on the approval resource. For example, an approval may have the following links:

  • apiture:approve - approve the document
  • apiture:reject - reject the document
  • apiture:return - return the document, perhaps because it was the wrong document type, or it was illegible
  • apiture:waive - waive the document

The abbreviated JSON representation of the approval is similar to the following:

{
  "_id" : "1bf7a277-e57d-4cf8-bf20-f990f45a848a",
  "_profile" : "https://api.apiture.com/schemas/approvals/approval/1.0.0/profile.json",
  "_links" : {
      "self"            : { "href" : "https://api.thirdpartybank.com/approvals/approval/1bf7a277-e57d-4cf8-bf20-f990f45a848a" },
      "apiture:approve" : { "href" : "https://api.thirdpartybank.com/approvals/approvedApprovals?approval=1bf7a277-e57d-4cf8-bf20-f990f45a848a" },
      "apiture:reject"  : { "href" : "https://api.thirdpartybank.com/approvals/rejectedApprovals?approval=1bf7a277-e57d-4cf8-bf20-f990f45a848a" },
      "apiture:return"  : { "href" : "https://api.thirdpartybank.com/approvals/returnedApprovals?approval=1bf7a277-e57d-4cf8-bf20-f990f45a848a" },
      "apiture:waive"   : { "href" : "https://api.thirdpartybank.com/approvals/waivedApprovals?approval=1bf7a277-e57d-4cf8-bf20-f990f45a848a" },
      "apiture:target"  : { "href" : "https://api.thirdpartybank.com/url/of/target/resource" },
      "apiture:approvalType" : { "href": "/approvals/approvalType/0399abed-fd3d-4830-a88b-30f38b8a365c" }
  },
  "..." : " ... other properties ..."
}

(See Resource Sets for more information about this design pattern.)

Associated with each such link is the href for the indicated operation. However, the href is something that the service provides rather being a URL that the client constructs from the API documentation.

In addition, if the currently authenticated user does not have entitlements to approve or reject a document, the service omits those links from the approval’s set of _links. Thus, the absence or presence of a link conveys the user’s permissions. The client should not provide access to an Approve or Reject action if the corresponding links are not available. The client should also avoid any business logic which tries to construct the URLs for such operations or related resources.

Example: Changing the State of an Account

Another example are the links that exist on an account:

  • apiture:freeze - freeze an account
  • apiture:deactivate - deactivate an active account
  • apiture:activate - activate a pending, deactivated or frozen account
  • apiture:close - close an account

Loosely-Coupled Clients

Clients are strongly encouraged to use the links and href values provided in the API responses, rather than construct URIs to make additional calls. The paths returned in the link’s href are also subject to change because the API service may move resources to other locations (paths) to make access more efficient. (This is one of the benefits of HATEOS - tha ability of a service to evolve over time.) Using the links provided by the API (rather than hard-coding links) makes the client more resilient to change.

In addition to using the preferred locations of the related resources or actions, the links in the API responses will include the correct query parameters. The next and prev pagination links are such an example. The API service computes the correct ?start= query parameter for pagination, carries over the current ?limit= parameter, any ?filter= and ?sortBy=` parameters, etc. If the API did not return links, not only would the client have to keep track of these query parameters, the client would not be able to support any new parameters that may be added in future versions of the API.

OpenAPI Specification

Apiture APIs are described with the OpenAPI Specification. However, in the OpenAPI Specification does not fully support hypermedia API description. While the OpenAPI Specification 3.0 can define links in an API response object, it cannot describe links that are part of API request bodies, as is done with Apiture APIs HAL request bodies. Apiture APIs attach links to resource model schemas rather than just an API response object. This also allow defining links in deeply nested objects, such as links within items inside a collection.

Apiture APIs documentation describes which links are allowed or expected in request bodies or which may appear inside nested resources.