Great APIs Start with a Great Design
Everyday the web becomes more connected; not just in the sense of more nodes, more people, and more content, but in the sense of being interconnected. Web services and APIs (Application Program Interfaces) allow access to an application's features, usually for integration into other applications. When you use an app to share something on Facebook, login with Google, or upload a photo to Flickr, for example, there is an API in use.
As web developers, we spend more time every year interacting with these third-party services to handle everything from credit card processing to blog comments. More web applications and services mean more APIs.
Unfortunately very few of these APIs are easy to work with, it is like Rube Goldberg invented the School of API Architecture. Behind every mobile, web, or desktop application is code, and that code was written by a human. The design of these APIs means a lot to the people that write applications.
A Means to an Endpoint
Most APIs we encounter seem like an afterthought. It appears the typical API planning meeting goes like this:
Sales Team: That new web site app thingy we launched is going great. Lets create one of those new-fangled API on Ajaxes so we can be cool, like Microsoft.
Mobile Team: As much as we hate to agree with Bob, having an API would allow us to harness all the power of the web app's backend with a clean native experience.
Web Team: Sure, can we have time to design this properly and roll it out in stages? We want this to be done right.
Sales Team: You already wrote all that CRUD stuff, just expose that and everyone will be happy. I bet you can have it up and running by lunchtime.
So what we end up with are basically web view variables dumped as JSON and endpoints that expect the exact information that is in some web form for all creates and updates.
Making the assumption that the API should just reflect the controller actions of the web application is rarely the best solution, believe me, we've tried. An API should not just be a means to an end, shoehorned in months after launch. An API should be well thought out, with each endpoint handling one task, and each namespace grouping actions into intelligent classifications.
Exploring use cases and developing a sound API architecture should be the first step in rolling out any interface to your software. Considering the needs of the consumer, planning out the URI and endpoints prior to writing code, determining required fields, mocking up return values, and defining response handling are all vital to a successful API.
The Art of Discovery
Finding your way around an API should not be like Columbus discovering the New World. Developers are notorious for releasing or updating features prior to updating the docs, if the docs ever get updated at all. This makes learning the ins and outs of web APIs a process of discovery, which some systems could use help on making easier.
A well written API should essentially be self documenting. A list of namespaces, endpoints, and example requests and responses will act as a map for the future voyages of other developers into the worlds you create. I am not advocating dumping the docs, but at the very least follow some convention and style to make the process easier.
As developers, we spend most of our lives naming things: variables, classes, functions, filenames, and every other thing that requires a name. We strive to assign names that make sense and will remind us of what the thing in question is doing. Some developers argue that well written code needs no documentation, though that discussion has been known to end in flame-wars of epic proportions.
If we craft our endpoints with this same mindset, everything else seems to fall into place and makes more sense to the implementing developer. The documentation is easier to consume when the naming conventions follow common sense. Responses that return consistently formated data result in happier developers. Lastly, error codes and messages that can be understood by a human are paramount.
418 — I'm a Teapot
Once the appropriate endpoint has been found, one must figure out how to communicate with it. There is nothing like sending what appears to be a properly formed request to a documented endpoint and getting a response like
99999 - Error
First of all, the Phoenicians invented HTTP Status Codes right after the written alphabet, they have been around forever so do not be afraid to use them. If you are going to use a custom status code, like
99999, please be kind enough to provide a good error message.
In that particular case we were passing expired credentials. A simple
401 - Unauthorized would have been a lot more helpful. If you are authoring an API, please be compassionate to your users — call it professional courtesy.
It is much easier to handle errors programmatically when different errors have different codes or messages. The support staff will get less emails if the words in the error message actually mean something, and the final product will be less brittle.
Like endpoints, your API's error messages should be well thought out and reflect a level of sophistication that represents your underlying product.
APIs should be reliable, period. If we build an application that is in production, we expect it to work all the time. If a third-party API changes, especially without notice, our production server is affected, usually in a bad way.
There are some things that we realize are going to happen from time to time with various 3rd party services. While some outages or other issues are hard to predict, breaking changes to an API are something the development team has full control over.
Versioning, deprecating features, staged rollouts, even postcards with notification of pending changes written in Vogon poetry are better than just making breaking changes to APIs that people are using without notice. Developers are depending on these services, they should should not be a moving target.
Recently we interacted with a third-party web API that had some very strenuous authentication and security restrictions. For each request, we had to use white-listed IP addresses, pass authentication headers with preassigned keys on top of OAuthing, and send a signed certificate with each request. It seems like each time they heard of a new way of authentication, they just added it to the stack like a door with 15 deadbolts on it.
In one of my lectures on security at Codeup, I have the students envision the most secure house they could possibly conceive. Think of moats with drawbridges, filled with sharks armed with lasers beams on their heads, rocket turrets everywhere, razor wire fences, biometric locks, concrete doors two feet thick. Think of the kind of place you would want to be if the zombie apocalypse broke out at the same time as World War III.
Then we talk about what that house would be like if we were driving back from the grocery store, in torrential rain, with two screaming infants in the back seat. The entry process to make it through security would make our house almost unusable, and under normal, peace-time conditions that level of security makes for a bad user experience.
A good design can strike a balance between security and usability, especially for API users. Developing a strategy that makes sense for your product and market while maintaining a usable interface is very important. Stripe has one of best designed APIs on the market, and they process millions of dollars in transactions without the razor wire and hellfire missiles.
How do we overcome the thrown together heap of endpoints with super-max security restrictions that are constantly changing and throwing error messages that require the Rosetta Stone and a team of engineers to decipher?
We simply need to rethink the approach to API architecture.
Before wearables and mobile devices, there was the simple web, the thin web, and it was all about the screen. We developed the web for the screen, and sometimes the pesky printer, and all was good. Then came mobile, and the mobile first movement.
Now, in the time of mobile app wonderland, wearable tech, interconnected everything, and front-end MVCs galore, we expect a popular application to have tailored experiences for each device. To achieve this with equal sophistication and elegance we must design the API to be robust, not just expose the web app's endpoints. Embracing an API first mentality is important to staying nimble in the ever changing world where consumption methods grow almost daily.
Using hypermedia to build your API can solve the painful problems associated with API versioning and discoverability.
Many services claim to provide RESTful interfaces or APIs. Often times, this only means that they use HTTP methods like
PUT/PATCH/DELETE (in addition to
GET/POST) and ignore hypermedia altogether. Hypermedia usage is a constraint of REST, not optional or a nice-to-have. If you are building a RESTful API, but you are not using hypermedia, it's not REST.
By serving hypermedia, your API can change independently of any clients without suffering the effects of backwards incompatibility.
There are several existing and emerging conventions and specifications for API responses, including:
If your API has endpoints like
/api/v1/resource to indicate different document structures, something is likely wrong. Love your users, love your clients, serve hypermedia.
API4H — Application Program Interfaces for Humans
Remember, before your API is being used by a program, it is first being consumed by a programmer. Until servers become sentient we rely on humans to understand the services they are integrating before they can automate the processes.
By designing your APIs for human consumption, and as a foundation for your application versus an add-on, you make happier developers and increase the likelihood of people building applications around your services.
At Grok Interactive, we design and build custom APIs for our clients. If you need assistance creating a back-end solution for your mobile or web application, please do not hesitate to contact us for assistance.
Special thanks to Josh Freeman and the rest of the Grok team on this blog post.