Apiary: Not Just For Bees
- Posted in:
With our relatively new desire to create quality API’s facilitating external integration with our products, we’ve decided to start using Apiary.
In actuality, we’ve been using Apiary for a while now, but not very well. Sure we used it to document what the API looked like, but we didn’t take advantage of any of its more interesting features. That changed recently when I did a deep dive into the tool in order to clean up our existing documentation before showing it to a bunch of prospective third party integrators.
Apiary is an excellent tool for assisting in API development. It not only allows for the clear documentation of your API using markdown and multi-markdown, but it also acts as a mock API instance. This of course allows you to design the API the way you want it to be, and then evaluate that design in a very lightweight fashion, before committing to fully implement it. Cheap prototypes make for lots of validation during the design phase, which in turn makes for a better design, which generally leads to a better end-result.
Even once you’ve settled on a design, and fully implemented it, you can use the blueprint to call into your real API, using the documented parameters and attributes. This allows for all sorts of useful testing and validation from an entirely different point of view (and is especially useful for those users unfamiliar with other mechanisms for calling an API).
Its not all amazing though (even though it is pretty good). There are a few features that are lacking which make me sad as a software development, and I’ll go into those later on. In additional to a few areas that are lacking, it has a bit of a learning curve, and it can be difficult to know exactly what will work and what won’t. There are quite a few good examples and tutorials available, but the Apiary feature set also seems to change quite rapidly, so it can be hard to determine exactly what you should be using.
This post is mostly going to contain an explanation of how we currently structure our API documentation, along with a summary of the useful things I’ve learned over the past week or so. Really though, its for me to fortify this information in my own head, and to document it in an easily sharable location.
I like to make sure that API documentation speaks for itself. Other than access credentials, you should be able to point someone at your documentation and they should be able to use it without needing anything else from you. Its not that I don’t like talking to people, and there are definitely always going to be questions, but I find that “doesn't need to come back to you” is a pretty good measure of documentation quality.
Of course, this implies that your documentation should do more than just outline your endpoints and how to talk to them. Don’t get me wrong, it needs to do that as well (in as much detail as you can muster), but it also needs to give high level information about the API (where are the instances, what is a summary of the endpoints available) as well as information about the concepts and context in play.
As a result, I lean towards the following headers in Apiary: Overview, Concepts and Reference.
The overview section gives a brief outline of the purpose of the API, and lists known instances (actual URLs) along with their purpose. This is a good place to differentiate your environments (CI, Staging, Production) and anything useful to know about them (CI is destroyed every night for example, so data will not be persisted).
It also lists a summary of the endpoints available, along with verbs that can be used on them. This is really just to help users understand the full breadth of the API. Ideally each one of these endpoints links to its actual endpoint specification in the reference section.
The concepts section is where you go into more detail about things that are useful for the user to know. This is where you can outline the domain model in play, or describe anything that you think the user would be unfamiliar with because it requires specialised knowledge. You can easily put Terms of Reference here, but you should focus on not only explaining unfamiliar words, but also on communicating the purpose and reasoning behind the API.
This is also a good place to talk about authentication, assuming you have some.
This is your normal API reference. Detail the endpoints/resources and what verbs are available on them. Explain required parameters (and the ways in which they must be supplied) along with expected outputs (both successful and failure). I include in this section a common sub-section, detailing any commonality between the API endpoints (like all successful results look like this, or any request can potentially return a 400 if you mess up the inputs, etc).
For Apiary in particular, make sure that your examples actually execute against a real server, as well as act appropriately as a mock. This is one of the main benefits of doing this sort of API documentation in Apiary (rather than just a Github or equivalent repository using markdown), so make the most of it.
I found that using Data Structures (using the +Attribute syntax) was by far the best way of describing request/response structures, both in terms of presentation in the resulting document and in terms of reusability between multiple elements.
Specifying a section for data structures is easy enough. Before you do your first API endpoint reference in the document (with the ## Customer [/customers] syntax), you can simply specify a data structures heading as follows:
# Data Structures ## Fancy Object (object) + Something: Sample Value (string, required) – Comment describing the purpose of the field + AnotherThing: `different sample escaped` (string, required) + IsAwesome: true (bool, optional) # Simple Thing (object) + Special: yes (string, required) ## Derivation (Fancy Object) + Magical: (Simple Thing, required)
You can then reference those data structures using the +Attributes (Data Structure Name) syntax in the API reference later on.
Notice that you can model inheritance and composition in a very nice way, which can make for some very reusable components, and that there is room for comments and descriptions to do away with any ambiguity that isn’t already dealt with via the name and example value.
It Could Be Better
Its not all great (even though it is pretty good).
I had a lot of issues with common headers in my API Blueprint, like a common header for identifying the source of a request, or even the requirement of an Authorization header. This was mostly just me not wanting to repeat myself, as I didn’t want to have to specify the exact same header for every single endpoint in the documentation, and have the examples be executable. Even the ability to specify variables to be substituted into the blueprint in a later place would have been better. I really don’t like having the same information stated in multiple locations. It makes maintenance a gigantic pain.
Another rough patch is that there seem to be a number of different ways to accomplish the same sort of thing (reduced duplication when dealing with request/response templates). You can use models (which can define headers, bodies and schemas) or you can use data structures (which are less JSON specific and more general, but can’t do headers) or you can manually specify the information yourself in every section. It can be difficult to determine the best tool to use.
I assume that this is a result of the service changing quite rapidly and that it will likely settle down as it gets more mature.
Finally, because of the nature of the markdown, it can be quite hard to determine if you have actually done what you wanted to do, in terms of the Apiary specific data structures and specifications. If you mistype or leave out some required syntax, its probably still valid markdown, so your documentation still works, but it also doesn’t quite do the right thing. There is some syntax and semantic checking available in the online editor, which is awesome, but it can be a bit flakey at times itself. Still, I imagine this will improve greatly as time goes on.
As a step up from normal API documentation (either in a Wiki or using some sort of Markdown), Apiary offers a number of very useful features. By far the most useful is the ability for the specification to actually create an executable service, as well as pass requests through to your real service. This can really improve the turnaround time for validating your designs and is a major boon for API development.
At a conceptual level, I’m still disappointed that we have to document our API’s, rather than somehow exposing that information from the API itself. My ideal situation would be if that sort of ability was included as part of the source of the API. I still hate the fact that the two can very easily get out of sync, and no matter how hard you try, the only source of truth is the actual executable code. Its the same problem with comments in your code. If you can’t make the code express itself well enough, you have to resort to writing around it.
If I have to document though, I want the documentation to be verifiable, and Apiary definitely provides that.