Programmatic API Documentation
In software development, it’s no longer good enough to provide a web application. More often than not, the server components we build need to support a wide variety of client devices: mobile apps, third party clients and applications, as well as traditional web applications. Because of this, modern web applications are decomposed into an API layer and a client or presentation layer.
Even with the the code decomposed into an API and client, development of both pieces usually occurs in lockstep - each being incrementally modified and deployed - and more often than not each of these provide breaking changes so that both the API and client need to be deployed simultaneously in a symbiotic relationship.
At nToggle, we thought about how the API was going to be used and we realized quickly that we could not develop in this manner. The API had to be able to live as its own entity, so that our customers had the ability to integrate directly against it as well as have an option to use a provided UI.
With this decision, the requirements we were looking to satisfy became:
- A common format to discuss APIs between server teams, UI/client teams and customer integration teams,
- Ability to iterate changes to an API quickly, potentially using a UI/editor (which would also be able to correct any specification validations),
- Ability to generate SDKs across multiple languages and
- Ability to publish APIs as HTML for everyone to consume.
For documenting APIs, there are many options available, including Apiary, API Blueprint, RAML and Swagger. The features of each are similar but ultimately we decided to go with Swagger based on a large community of users and developers (with contributions to the ecosphere) and prior exposure of our engineers.
Swagger has a lot going for it. Getting started was easy - you have the option of using editors directly from links of the Swagger web site and there are many examples available to view.
The community is a great resource. The news groups are active and there are code contributions by the community for outstanding tickets.
Having the documentation/definition as code. It’s always good when the documentation being provided is part of the code that is deployed - it makes it easy to maintain. Because of our development environment (Scala and Akka Streams & Http), we were unable to take advantage of annotations and automatically building the definition JSON file. This led to a little more overhead than we would like, but so far, keeping both in sync has not been a problem. The really nice feature is that whenever the APIs are deployed, the API docs are right there with it as HTML - and up to date!
One of the unexpected advantages was that the HTML produced can exercise the API directly. No need to write test code or to use browser tools (such as Postman). Specifying enums and default values made this even easier as the HTML was tailored to reduce what needed to be entered and the control to enter values.
Where it breaks down
For all the common usage Swagger worked as expected. When it broke down, it was usually on features that are less commonly used.
There were a few places when writing the specification wasn’t obvious to us, this included:
- When providing examples, instead of providing an example for each property, an example is required for only the top level object and must include all dependent objects,
- “Required” is an array of property names, not boolean on each property, and
- Defining parameters can be awkward/verbose, especially if you have the same param that can be both required and not required.
The editor was a great tool to have, but over time we used it less frequently. The main issue here was that you can modify Swagger via an easier to use YAML format (rather than JSON), but the process of importing the file, making updates, exporting the file and then including it in the project became very time consuming - especially when only small changes were being made. Instead, we tended to make updates to the JSON directly and then every so often (when the changes were large enough), we used the editor to validate and correct any problems.
The biggest surprise was with authentication. We use OAuth2 for authentication in our APIs, but we don’t use the implicit flow that is the only one supported out of the box. After some digging around, we found a community submitted patch that helped. With security a common concern, I’d like to see more on this front, which will help bring Swagger into enterprise engineering groups and expand it’s usage.
In the end, we didn't use the SDK generation. We use React for our client side development and at the time there were no projects that could generate React clients from the Swagger documentation. This will be something that we keep a close eye on, both for updating our UI client and also as we start working with customers that are looking to utilize the API in other languages and frameworks.
Overall Swagger has helped tremendously. By providing a format that’s easy for all stakeholders to view, its made the intent of our APIs clearer and changes faster and sparked several discussions that only come from talking about an API before it’s implemented. The issues we faced were minor, and could be worked around, and we’re looking forward to improvements as the project continues its maturity.