Hypermedia as the Engine of Application State. Sounds fancy. It pretty much is. HATEOAS is a REST constraint where the state of the entity is transferred as well as what a consumer can do with that entity. It’s REST on steroids as it enables truly stateless distributed services that can scale without worrying about consumers.

In HATEOAS, the actions available for an entity are transferred with that entity. Take, for example, a traditional REST entity of a shopping cart:

<br>{<br>     "id": 11883,<br>     "total": "$10.00",<br>}<br>

In the traditional REST architecture strategy, a consumer would have to have logic to determine if it can add items to a cart, update cart item quantities, remove an item from the cart, purchase the items in the cart, save items from the cart for later purchase, etc. It would also need to know where to go to for each of these actions. This type of logic is intrinsic to a RESTful consumer application. Knowledge of how the REST API must be interpreted and developed prior to use.

Take the same shopping cart example and apply it to the HATEOAS API Design strategy:

<br>{<br>     "id": 11883,<br>     "total": "$25.00",<br>     "items":[{<br>          "id": 73,<br>          "name": "coffee",<br>          "price": "$10.00"<br>          "qty":2<br>     },{<br>           "id": 42,<br>          "name": "creamer",<br>          "price": "$5.00"<br>          "qty":1          <br>     }<br>     ],<br>     "links": [{<br>          "href": "https://shopping.localhost/11883/items/73",<br>          "rel": "item",<br>          "type":"DELETE"<br>     }, {<br>          "href": "https://shopping.localhost/11883/items/42",<br>          "rel": "item",<br>          "type":"DELETE"<br>     },{<br>           "href": "https://billing.localhost/purchase/11883",<br>           "rel": "purchase",<br>           "type":"POST" <br>     }, {<br>          "href": "https://profile.localhost/saved/73",<br>          "rel": "item",<br>          "type":" PUT"<br>     }, {<br>           "href": "https://profile.localhost/saved/42",<br>           "rel": "item",<br>          "type":"PUT"<br>     },{<br>          "href": "https://shopping.localhost/11883",<br>          "rel": "cart",<br>          "type":"DELETE"<br>     },{<br>          "href": "https://shopping.localhost/11883/items/73/qty",<br>          "rel": "qty",<br>          "type":"PUT"<br>     }, {<br>          "href": "https://shopping.localhost/11883/items/42/qty",<br>          "rel": "qty",<br>          "type":"PUT"<br>     }]<br>}<br>

This example shows how you could (poorly) structure your links attributes to handle any steps available when perusing your cart. You could update the quantity of your items, clear your cart, remove a single item, purchase all items, save items for later, etc. The point of this example is that the consumer doesn’t need to worry about the actual API calls. The consumer can just be aware of the entity types and leverage the actions available for any given resource. This example defines links as described in RFC5988. You could really use any type of defined links as long as it describes the actions that are available to the resource.


As you can see, this type of architecture strategy allows consumers to become more dynamic. A consuming application would only need to be made aware of an originating call to the API to retrieve entities with link attributes that determine what is available to the consuming application.

With HATEOAS, scaling web services becomes rather trivial. If multiple domains are used during scaling, the links attribute simply lists whichever are available and the consuming application can blindly follow these links to take whatever appropriate actions they provide.

Using HATEOAS is particularly useful in workflow management for multi-step processes. If you think of HATEOAS in terms of a workflow diagram, the linksattribute becomes more clear. Each step in a workflow diagram can be a resource guided by the links provided by that resource.