In my last post I addressed the worst acronym ever, HATEOAS, and how to truly have hypermedia drive the stateful interaction of your application. The discussion rounded out the more standard guidelines for creating hypermedia APIs, creating a nice foundation for understanding for the next four guidelines which are part of the forthcoming hAPI specification to drive adoption of hypermedia APIs through reduced complexity and better tools. In this first post in the series addressing the next stage of hypermedia APIs, I would like to address goals. Specifically, I would like to address the goals of the consumers of your API, and put some serious effort behind helping them achieve their goals.
If you take a step back and look at the interaction of a CRUD, you should be able to see a usage pattern which relies heavily on understanding the model of the service provider’s implementation to understand what interactions are required, and in which order to accomplish a larger goal. Due to my history in the financial sector and common familiarity with banking, I tend to use the creation of a checking account as a good example to demonstrate the issue.
Suppose you had the following CRUD APIs:
/account
/address
/person
If you wanted to create a new checking account, considering documentation like OAS doesn’t show larger interaction arcs, what would you do? The most likely implementation scenario requires you to create a person with an address, and then use this person and address to create an account. The problem is I had to reason my way through to this conclusion as the service implementer. As a consumer I don’t, and shouldn’t be forced to, care about the concerns of implementing a service in order to consume it. This was an easy enough example, so you might be inclined to shrug this off as manageable. If you have not, well then I’m sorry for your trouble because you have been through the same pain I have, it wasn’t fun. If however, you have yet been spared from the joy of integrating a service designed by someone else’s undocumented and internal data model of confusion, then I have concocted just the elixir for you to prove just how real this problem is.
Assuming at this point, we’re all on the same page regarding the previously mentioned pain we need to look at the hypermedia solution, which is without a doubt a much friendlier interface to a very similar albeit muted frustration. You see, despite the ease of engagement with the service being significantly better, I am still required to understand the domain model and internal implementation and composition structure enough to make value judgements to determine how to crawl the service intelligently. As a consumer correctly discovering the service, I have two choices, try everything, or try everything while guessing at relationships. Neither of which sound particularly appealing, but at least it’s better than using CRUD.
I propose a third option, as part of the vocabulary for the service define domain relevant goals which can be provided by a consumer to express their domain intent for consuming the service. In the banking example above, it would be much easier if profile linked by the home document contained a goal of “new-customer-create-account” which I could provide to the server in order to tailor the hypermedia of the responses in order to steer my client towards the new account goal. Hypermedia APIs are a great leap forward in usability, by using goals with hypermedia we can greatly reduce the interaction difficulty and enhance the speed at which we can integrate and release new APIs.
The hypermedia API designer should not only look to create the appropriate vocabulary for the service, but also look to encapsulate the larger goals of the domain to provide stateless hypermedia curation for their consumers! Together this will allow you to reduce the amount of knowledge a consumer needs to have about a particular domain or implementation in order to successfully consume it.