Hypertext Application Language

Hypertext Application Language, or HAL) is a proposed IETF specification for representing API resources and their relations with hyperlinks. While the original specification targets JSON, an additional IETF proposal targets XML.

HAL is a minimal specification, and addresses three specific things:

  • How to represent the elements of an API resource.
  • How to represent hypertext links of an API resource.
  • How to represent child resources.

Resources

HAL opts to keep out of the way. Where other specifications may push the data for a resource into a subkey (e.g., "data", "collection.items", etc.), HAL specifies resources as the primary payload.

As such, a resource is simply a document:

{
  "id": "XXXX-YYYY-ZZZZ-AAAA",
  "title": "Life, the Universe, and Everything",
  "author": "Adams, Douglas"
}

For XML documents, the element <resource> is reserved to detail the resource; every other element represents the document:

<resource>
  <id>XXXX-YYYY-ZZZZ-AAAA</id>
  <title>Life, the Universe, and Everything</title>
  <author>Adams, Douglas</author>
</resource>

This decision makes both consuming and generating HAL payloads trivial.

One goal of REST is to allow any given resource to provide hypertext controls, or links, allowing the consumer to know what they can do next. Most resources will provide a self relational link, so that the consumer knows how to request the resource again. However, a consumer might want to know what other actions are possible. For example, they may want to know:

  • how to get a list of related resources
  • how to access the first, previous, next, or last pages of a collection of resources
  • what resources are related: e.g., transactions, products, invoices, users, etc.

HAL addresses how to provide such links. This is necessary because JSON has no specific semantics around linking, and XML, while it has some semantics, does not cover how to provide multiple links for a given element.

HAL addresses JSON by reserving a special _links property, and specifying a structure for how links are represented. Each element of the _links property is named for the link relation, and the value is either an array, or a link object. A link object contains minimally an href property, with several other properties allowed. As an example:

{
  "_links": {
    "self": { "href": "/api/books/XXXX-YYYY-ZZZZ-AAAA" },
    "books": { "href": "/api/books" }
  }
}

At this point, the consumer knows they can access the current resource via the "self" relation, and a collection of "books" via the URI "/api/books".

HAL addresses links in XML with two semantics. First, the <resource> element can contain linking information, using the "rel" and "href" attributes (and any others necessary to describe the link). Typically, the "self" relational link is defined in the <resource> element. Second, the specification also reserves the <link> element; the relation, URI, and other attributes become attributes of that XML element.

An equivalent XML document to the JSON document above looks like the following:

<resource rel="self" href="/api/books/XXXX-YYYY-ZZZZ-AAAA">
  <link rel="books" href="/api/books"/>
</resource>

Child Resources

An API payload may have child resources for several reasons:

  • The resource may be related to the current payload, and providing it directly would prevent another request to the API.
  • The payload may represent a collection of resources (or even multiple collections of resources).

Generally, a child resource represents a relation. As such, HAL has very specific semantics for providing them.

In JSON documents, the specification reserves the property _embedded. This is an object, with the keys being the relations, and the values either resources, or arrays of resources. Each resource follows the same structure as a basic HAL resource, with a _links member, other members representing the resource, and optionally an _embedded member.

{
    "_links": {
        "self": { "href": "/api/books?page=7" },
        "first": { "href": "/api/books?page=1" },
        "prev": { "href": "/api/books?page=6" },
        "next": { "href": "/api/books?page=8" },
        "last": { "href": "/api/books?page=17" }
        "search": {
            "href": "/api/books?query={searchTerms}",
            "templated": true
        }
    },
    "_embedded": {
        "book": [
            {
                "_links": {
                    "self": { "href": "/api/books/1234" }
                }
                "id": 1234,
                "title": "Hitchhiker's Guide to the Galaxy",
                "author": "Adams, Douglas"
            },
            {
                "_links": {
                    "self": { "href": "/api/books/6789" }
                }
                "id": 6789,
                "title": "Ancillary Justice",
                "author": "Leckie, Ann"
            }
        ]
    },
    "_page": 7,
    "_per_page": 2,
    "_total": 33
}

The above represents a collection of book resources.

To address XML, the specification uses the <resource> element to embed additional resources. Resources of the same type use the same rel attribute. The XML equivalent of the above JSON documentation thus becomes:

<resource rel="self" href="/api/books?page=7">
    <link rel="first" href="/api/books?page=1"/>
    <link rel="prev" href="/api/books?page=6"/>
    <link rel="next" href="/api/books?page=8"/>
    <link rel="last" href="/api/books?page=17" templated="true"/>
    <resource rel="book" href="/api/books/1234">
        <id>1234</id>
        <title>Hitchhiker's Guide to the Galaxy</title>
        <author>Adams, Douglas</author>
    </resource>
    <resource rel="book" href="/api/books/6789">
        <id>6789</id>
        <title>Ancillary Justice</title>
        <author>Leckie, Ann</author>
    </resource>
    <_page>7</_page>
    <_per_page>2</_per_page>
    <_total>33</_total>
</resource>

Summary

With these three semantics — resources, links, and child resources — HAL allows you to describe any payload, and provide the hypertext controls necessary to allow API consumers to know what resources they can access next.

The next step, then, is learning how to create HAL payloads for your API!