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 hypermedia links are direct API URIs to actions you can perform on the response object. They allow your client application to be more dynamic by adapting to new links supplied by the service. More importantly, the clients do not have to construct the links themselves, a fragile process that couples the application to specific API versions. With hypermedia, 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 them.

In Apiture Open Banking 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 contains 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 document approvals 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. 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 approval

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 link is the href for the indicated operation. However, the href is something that the service automatically provides rather than 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, but the client does not have to know the business rules for who is allowed to approve or reject a document. The service does that. The client should also avoid any business logic that 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. (One of the benefits of hypermedia APIs is this ability of a service to evolve over time, independently of clients.) 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 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 support any new parameters that may be added in future versions of the API.

OpenAPI Specification

Apiture Open Banking APIs are described with the OpenAPI Specification. However, 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 Open Banking APIs HAL request bodies. Apiture Open Banking APIs attach links to resource model schemas rather than just an API response object. This also allows defining links in deeply nested objects, such as links within items inside a collection.

Apiture Open Banking APIs documentation describes which links are allowed or expected in request bodies, response bodies, and inside nested resources.