As a software engineer, not a day goes by where I don’t have to interact with some other piece of software, via an API (Application Programming Interface). A good API can make your day, a bad one can cause hours of frustration and at worst, bugs in production. In this post I want to share some of the things I look for in an API and some of the things I attempt to build when designing an API.
What is an API?
First, I’d like to define a little more rigidly what I am referring to when I say ‘API’. An API could be how you communicate with a database, it could relate to hardware or it could just be how you interface with a Python library. In this article, I’ll mostly be talking about a web-based system that uses HTTP to communicate with other services (sometimes called a “Web API”).
Show me the Docs
The first aspect I look for in an API is documentation. I put this at the top as this is probably how a developer is going to first interact with an API. You decide you need to incorporate another system or service into yours, you find a good candidate, you go and read their docs. Now I’ve heard some developers say that an API can suffer from ‘over documentation’. Personally, I’ve never experienced this. The more the better, I say. In terms of documentation, the best API I’ve used, hands down, is for the payment service Stripe.
Their website includes quick start guides for many of the usual use cases, tutorials and then the structured reference docs for each API endpoint. What’s especially nice here is that the endpoint documentation paths are laid out in a similar way to the API itself, e.g. https://stripe.com/docs/api/cards/object. This makes it extremely easy to navigate and adds to the understanding of the API.
Design is how it works
Once I’ve got the documentation for an API, the next aspect I’m looking for is how the endpoints are laid out. API endpoints are like the ‘front door’ of an API. I’m ideally looking for simplicity here. Obviously, if the data model is complex, then the API is going to reflect that complexity, but I’ve seen complex apps which have nice, clean endpoint layouts. An example of this would be the Mailchimp API. Looking through the endpoints here, we see that ‘campaigns’ appear to have many features that are accessible through the API, but the layout of the endpoints is intuitive. In fact, I’d probably say that if you knew this feature well, you could guess at an endpoint and probably get it right. You can also see that the documentation for this API is very nice. Each feature has a table showing HTTP verb (GET, POST, etc.), endpoint and function.
This hints at another question that will come up when considering an API; is there a language specific library I can use? My thoughts on this used to be that, if the layout was simple and discoverable, you’d not need a library. I’ve changed my mind on this somewhat over the last few years though. The reason I now like to see a library is down to authentication. Authenticating yourself with an API can sometimes be non-trivial, especially if you want to use something like OAuth. A library should nicely abstract this away for you, so you can get up and running with minimal fuss.
We all need a REST
I don’t think we can really mention an API these days without mentioning REST (REpresentational State Transfer). There are many developers out there who are quite strict on what they will call a RESTful API. Personally, there’s only a few attributes from REST that I look for. The first of which is that HTTP verbs are used correctly and not added to the endpoint names. For example, if I see an endpoint named
/api/getAllDocuments, then I’m likely to move on and not use it. It shows a fundamental misunderstanding of how to use HTTP as a protocol for an API. In the same vein, using HTTP means you should use HTTP status codes to indicate an error state. Don’t always return a 200 and invent some of your own error codes and pop those in the response. That’s going to confuse me and force me to keep going back to the documentation and not just relying on my knowledge of the HTTP standard.
This pattern is simple, and takes advantage of the verbs built into the HTTP standard
GET /api/documents GET /api/events GET /api/comments
This pattern introduces the ‘GET’ verb twice and introduces unnecessary duplication when extended to multiple endpoints:
GET /api/getAllDocuments GET /api/getAllEvents GET /api/getAllComments
Learning by doing
Finally, I’d like to touch on the notion of ‘discoverability’ in an API. Now to make a truly RESTful API, it is supposed to incorporate the idea of discoverability. More specifically, each response should essentially contain hyperlinks to other resources. The idea behind this aspect was that a client could consume an API without any prior knowledge of the structure of the system itself. From my experience though, this is rarely used. With every API I have ever consumed I’ve ended up with at least some element hard coded into the client. I don’t personally see this as a bad thing. If the documentation is good and the versioning is up to scratch then things should just continue to work.
The three main aspects I look for in an API are:
- Good documentation
- Clear, logical endpoint layout
- The correct use of the HTTP protocol.
I don’t really put much importance on discoverability as long as the documentation is good. These are also the three aspects I will focus on when designing an API for public consumption.
APIs are for people too
A good API should act like a bridge, connecting people to data and services that could benefit them. A bad API can have the reverse effect - becoming a barrier that hides information from those that need it. If the APIs you are using (or creating) fall into the latter category, maybe it’s time to ask yourself: is your technology working for you?