Technology and Products

Make API Documentation Great Again

October 23, 2016
Frode Bjerke
Platform Engineer

Throughout this text API(s) refers to HTTP APIs

Great API documentation makes integrating with an API a breeze. Not only because you can read it and implement a good client yourself, but more in the line of great API documentation would let us generate awesome clients such that we do not have to spend any time at all. The downside is that API documentation rarely is great, not existing at all, missing crucial information or just blatantly wrong. So how could we fix this and at the same time make it an enjoyable experience?

As developers, documentation is often something we write after the fact. On some occasional sunny days we might actually write documentation simultaneously as code. Unfortunately, the next day we might again change that piece of code and of course forget to change the documentation along with it. To my experience this is as much the fact when writing a piece of application code as when implementing APIs. The issue with not writing API documentation until when development is completed is that it stands as an extra barrier before releasing. Unsurprisingly, writing the documentation is likely to be hurried as it blocks release and the fact that the developer finds it tedious to document. Using annotation based API documentation in the code itself as opposed to defining the API documentation in a separate file helps, but is not in our experience sufficient to mitigate the issue of API documentation being an artifact updated only after technical implementations are completed.

The opposite approach, design-first, is an approach to building APIs where the documentation is written first, then the implementation is shaped after that piece of documentation. This approach has been covered by many thought leaders over the last couple of years: Programmable WebAPI Evangelist and InfoQ. The upside of this approach is that you get a chance to vet your API design without writing a line of code. Additionally, it acts as a natural task specification for the developers implementing the design. The main downside of this approach is that technical challenges with the API design might only surface very late in the process, making it more costly to actually amend the challenges gracefully. Furthermore, developers might feel bound by the specification in the API and feel the process to rigid, or in worse cases decide to change the design neglecting the already existing API document.

Many of the popular frameworks used to build web applications and APIs today rely heavily on convention to increase developer speed. The framework themselves by default defines what error codes are returned and what headers used. Even though the conventions are convenient, they tend to make writing accurate API documentation challenging. The challenge is due to the documentee having to remember to document all the less than visible default conventional behaviors. In our experience, being privy to the ‘complete’ set of these behaviors for any framework is a daunting challenge.

As for the issues mentioned we see two classes of issues: those related to making changes twice (code and documentation) and those that are a result of including the conventions used by our frameworks to our API documentation. As per our understanding to accommodate any or both of these issues API documentation must be a first-class citizen in our frameworks or languages we write APIs in. By first-class citizen we mean that the API design cannot change without the documentation changes and vice versa. Additionally, the framework should reflect all of its API design defaults in the API documentation. By completing this the API documentation basically works as a contract.

An example of a framework that does treat API documentation as a first-class citizen is the Go framework goa. goa makes a clean separation between the API design interface and your business logic. The API design interface is defined using a DSL. From the DSL API documentation, data models and the classic controller code is generated. As long as you do not alter the generated code, which easily can be enforced on a build server, your API design and API documentation are now always in sync. This characteristic makes uncovering breaks to a current API-contract as diff’ing the new and and old API documentation document.