A Question on API Design and Documentation

Posted by Howard on Friday, April 22, 2016

One of the projects that my team owns is the Concur Developer Center. Among other information, it houses the documentation for Concur’s Web APIs. The documentation for the more recent API versions uses Swagger and until recently was generated by reflecting over the .NET API code. There were a bunch of problems that resulted from this approach as I’ll describe in a second. But there’s also some interesting trade-offs about the kind of APIs you get by focusing on service contracts as your primary design artifact.

Recently, in response to a Swagger update process announcement, we got the following question. I want to share that question with you, along with my response, as it goes beyond a discussion of documentation and gives you some further insights into thoughts on services and API design in general.

My team is in the process of designing a new API. We plan to eventually generate JSON from code for use in the Swagger API Explorer (love that) but we’re still in the early days and want something to point at and touch while we review user stories. Using swagger-editor running in localhost for that purpose is a bit challenging especially since it saves your work in browser storage. I tinkered with writing RAML in Atom and then a tool called raml2html to make a self-contained web page which seems a bit neater (and safer since I can store the .raml file locally).

Thoughts? Guidance? Is anyone one using a tool to spec out the API for discussion purposes before any code gets written? Any lessons learned from an API PM perspective with sharing?

My 2 cents -

Not to sound too Zen about it or anything, but if your goal is RESTful styled APIs, then serializing code function signatures (whether that is using Swagger, RAML, WADL, API Blueprint, WSDL 2.0, or any other fancy service description language that comes along) will take you in the opposite direction of that goal. The RESTful style is about federated [and therefore loosely coupled], connected data, and these service description languages and tools - every one of them – are about creating machine-readable function signatures and serializable classes for the purpose of generating [tightly coupled] clients.

Now, all that said, the RESTful style is still elusive enough to where nobody here is really pushing for it in a pure form. The form that is generally agreed to is what I’ll call for this discussion “RPC with documents”. By that, I recommend focusing on the following for your design:

  • Place more emphasis on your types and design them in JSON-Schema, not in code. While it may not be as easy as generating from code, it is ultimately more simple because it forces you to define your implementation in terms of your contract, rather than the other way around. Plus, JSON has significantly fewer primitive types than .NET or Java, and so representing JSON types in one of those language is significantly more simple than trying to figure out how to represent IList<Person> in JSON-Schema (FYI – one of the cleanup tasks we had to write for the previous generation of generated “swagger” was removing JSON-Schema type definitions like IList``1 – pretty awesome).
  • Don’t have a closed data model (e.g. Failing a request in the event of extra data than what you’ve defined). It may seem easier up front but it will burn you in version n+1. Instead, extract the data you’re interested in from input documents, and ignore what you don’t understand. What you will understand will change over time, and applying this principle now will keep you from having to explicitly version your interface and break your customers when that time comes.
  • Your functions should hardly ever have more than one parameter and one return value – and both of those should be the types that you designed previously.

From there, you have the most important piece done (your data model), and representing that in Swagger, RAML, WADL, et al becomes trivial. You can also use your schema as the touch point between teams without worrying about the complexities of the function calls, because you will have kept them simple.

So the moral of the story? If you want a RESTful system, focus on data over functions. But if you just can’t completely make the mental shift, keep your functions simple and focus more on your documents. That will put you in a stronger position when and if you later decide you want to make that shift.