Wednesday, December 15, 2010

API Design

I recently presented some opinions and ideas about web API design at Salesforce.com's Cloudstock event in San Francisco.

In the talk, I start with a poorly designed API and iterate it toward a well-behaved REST API. Along the way, I compare APIs from Facebook, LinkedIn, Twitter, Foursquare and others and share my opinions about which APIs do things well and which don't.

If you're thinking about API design, please give it a view and let me know what you think.

5 comments:

1. Versioning: I don't think it's right to add /v1 to the leftmost part of the URL because that URL indicates a unique resource and the API version doesn't have anything to do with that particular resource. HTTP headers should be used in this case.

2. Format: The format in which the returned data is should be determined by using "Accept" http header because that header is meant to be used for accepted format of data. The same with versioning, an 'extension' is not part of the resource itself but with its representation.

On the other hand, "Content-Type" is not meant to be used for returned data, but for the format of the data of the message being sent, not the format of the data of the returned message.

I like the talk though we differ on quite a few things one area we are in strong agreement is around simplicity and discoverability of the API.

You mentioned in the section on formats your recommendation that the API should be addressable via a uri extension i.e. ".json" and not via headers. You also said that if an API supports both you are not sure which takes precedence.

The answer is the accept header always takes precedence. However the server is really free to do what it wants regardless. For example if I sent an accept of "application/xml' to "order/1.json", the server could do one of the following.

On the same note, there is nothing wrong with supporting bookmarks to a specific representation i.e. orders/1.json. It is helpful for many scenarios as you mentioned.

The advantage however of supporting accept is it provides a standard "protocol" for asking for a specific representation. It allows the server to evolve to support new formats and lets standard HTTP clients request it without having to know about the servers uri space.

For example, you might look at your logs and see clients are looking to get that order back in PDF form by sending an "accept: application/pdf". You see that and say oh, some clients wants to see an hardcopy of the original order.

Great, we'll add that to the system, so you then update your system accordingly.

After the update, the next time that client comes and sends that accept, it gets back the PDF. That same client may interact with different servers, the beauty of accept is regardless which server it talks to it uses the established protocol of content negotiation via accept.

Now as you mentioned there are plenty of developers that won't care about this. For those I would support the simple bookmarks. However, for develoers / systems that do care (and there are plenty) I would recommend supporting conneg.

It's not an arcane esoteric science, it's how all the most popular web servers and proxies work today. :-)

As far as the item resource being plural. "Makes sense" is in the eye of the beholder. While you can make the argument that it makes sense to make it plural, I have equally seen many folks that believe the opposite makes sense.

Personally I don't care which way you go, and I don't think it diminishes the quality of your api by having s or not in the uri name.

Lastly I'll push back on your you only need 2 root uris. I'll argue you only absolutely need one, but that makes an assumption that you are building a hypermedia based system, which has plenty of other advantages.