Designing a great HTTP API — why heavyweight XML is not the answer

ElasticHosts recently released our HTTP API. In the course of system integration for our products, evaluating our competitors’ APIs and designing our own, we came to a clear view on what makes a great HTTP or web services API. Like many things in computing, it comes down to KISS:

Keep It Simple, Stupid

— simple for the users, that is!

Simple syntax

Simple syntax means making it easy for any user with a standard tool to call the API. If you can’t call the API with curl from a single line of shell then your API is not good enough. This rules out many of today’s cumbersome XML-RPC and SOAP APIs, although you will want XML as an option for users who are using XML-friendly languages.

We believe in:

Choice of syntax: Different users will find different syntax most natural. At the unix shell, space-deliminated text rules. From Javascript, you’ll want JSON. From Java, you may want XML. Some tools parse x-www-form-encoded data nicely. A great HTTP API makes every command available with data in all of these formats for all of these users, specified with either different URLs or MIME content types. (OK, we admit that we’ve only released text/plain ourselves so far, but the rest are coming very soon!).

Don’t reinvent the wheel: Smart people designed the internet. There are good existing mechanisms for security (e.g. SSL/TLS), authentication (e.g. HTTP auth), error codes (e.g. HTTP status codes), etc. Use them, and don’t invent your own, unlike one UK payment gateway who invented a simple XOR encryption which is vulnerable to a known plaintext attack and didn’t fix it when we pointed this out!

Simple semantics

Simple semantics means having a small number of powerful, orthogonal commands. If your API needs a 300 page document to explain it then something is wrong. Equally, your users shouldn’t even be aware of the artificial abstractions and data structures which you invented inside your software.

We believe in:

Few powerful orthogonal commands: For your API users, each call adds overhead, both in code and response times. Produce a few powerful calls which do the work of many smaller ones. In our case, our API has a single call for “server create”, where this would take many calls with some of our competitors’ APIs: starting the server, associating a static IP, associating persistent storage, etc.

No artificial abstractions: API users don’t care how you wrote your software, and shouldn’t have to know or change their calls when you change your design. Try as hard as you can to hide your internal structures from the user unless it’s absolutely necessary to expose them. In our case, a cloud infrastructure platform provides virtual server hardware, and we let users configure this as they would real hardware, choosing an amount of RAM, specifying which hard disk is on which IDE bus, etc. We don’t invent “instance types” and we deal with mapping the well-known hardware descriptions to how the virtualization platform sees them.

Immediate response where possible: All of our API commands are synchronous, and they usually complete within seconds of all input data arriving.

If we can do this for a cloud infrastructure platform, then surely you can for your application?