Building Hypermedia APIs – Links and Forms in JSON

When we create websites we don’t just create single pages that have no connection to other Web pages. From the beginning, hyperlinks were part of the core concept of the World Wide Web and for that reason HTML. Links are so essential to the Web that they are even used to rank the popularity of the Web pages on search engines. And who hasn’t gone on a journey through Wikipedia clicking link after link? Even though we all know and appreciate the importance of links on Websites, we rarely use links in our Web APIs. Why is that?

This is a blog series of 3 posts. In this part one we start with the fundamentals of hypermedia and json.

A lot of Web APIs nowadays use JSON. One of the reasons for the lack of links in Web APIs is that JSON doesn’t support links and doesn’t support forms. HTML, the language of the Web, on the other sides features the a element for links and forms with a lot of different kinds of fields. If you want to put a link into your JSON response, you can only use Strings.

Web API Standards like Siren and HAL want to change that. They both standardize links, and Siren also offers forms in the form of actions. In Siren, we structure a response like this:

  "properties": {
    "a": 1
  "links": [ 
    { "rel": ["self"], "href": "https://myapi.example/a" },
    { "rel": ["next"], "href": "https://myapi.example/b" }

We can see here that this resource has two links: One is a link to the resource itself, the other one links to another resource that has some ‘next’ relation to this resource. So probably ‘a’ and ‘b’ are in some list.

In the same way you can click on a link on a Web page, a client can follow the link to the next resource without any knowledge about the URLs of the API. All we need to understand is what the relation means. In the case of ‘next’ we have a relation that is generally defined by the IANA that it “indicates that the link’s context is a part of a series, and that the next in the series is the link target”. In other cases, an API needs custom relation types. We need to explain those somewhere.

Apart from that, an API is now self-explaining. And in the same way that you can change the target of a link on a Web page, you can also do that in your API. This gives you a lot of flexibility when restructuring. You can also remove the link to a resource temporarily or permanently. The URL becomes an unimportant implementation detail that can we can refactor at will.

That all sounds nice – why aren’t more people using this? At the beginning of this year I proposed that the reason for that is the tooling. When we look at the frameworks that we use to create APIs I see two categories:

  1. Web frameworks that are also used for creating Web pages: Frameworks like Rails and Django offer functionality to add an API to your site and frameworks like Rails API are stripped down versions of a Web frameworks. The tooling is similar to the one used to create a Web page.
  2. Low-level frameworks and libraries like Sinatra, Hapi or ArangoDB Foxx.

Each of them has one thing in common: They all put the URL first. Rails even features a system on standardizing the URLs. In our hypermedia philosophy this is however not our main concern: We want to put the links first. So I started thinking about a framework that would do just that and ignore URLs. The results are my master thesis and a feature of the upcoming 2.4 release of ArangoDB: FoxxGenerator.

In the next blog post (part 2) process I will describe the design process based on state machines. The excellent book RESTful Web APIs by Leonard Richardson, Mike Amundsen and Sam Ruby inspired my design process. The result of that design process is a drawn state machine. In the final blog post of this series I will then show how to translate this drawing into the DSL provided by FoxxGenerator to build a full functioning Web API.

If you want to try it out beforehand, try out our technical preview that features the first version of FoxxGenerator, learn about FoxxGenerator or read my thesis.

Dr. Frank Celler

Frank Celler

Frank is both entrepreneur and backend developer, developing mostly memory databases for two decades. He is the CTO and co-founder of ArangoDB. Try to challenge Frank asking him questions on C, C++ and MRuby. Besides Frank organizes Cologne’s NoSQL group & is an active member of NoSQL community.

Leave a Comment

Get the latest tutorials, blog posts and news: