Web API Patterns - Ajax Patterns

Web API Patterns

From Ajax Patterns

This is a collection of patterns for designing and managing Web 2.0 style APIs. The patterns are inspired by the successful efforts of Flickr, Delicious, Google, and others to open their content up for mashups and other applications. They look not only at the technical design details, but also about the surrounding processes like documentation and versioning.

Feel free to click on the Edit tab above and update these patterns, or add your own! I only ask that you don't get into an argument about whether these are "patterns" or "recipes" or something else. It's boring and in fact not relevant to anyone who has a use for them.

Contents

RESTful

The overall structure and naming of modern Web APIs follows REST and being RESTful means following a number of conventions. For the purposes of this conversation, the most important thing is to get the basics of REST right:

  • Use GET for read-only requests and POST for those which change server state (creation, updating, deleting).
  • Keep it simple and based around the standard conventions of the web. You should be able to type a URL into the browser address bar and get a view of the corresponding resource. You should be able to submit a standard HTML form to affect server state (creation, updating, deleting).
  • Any authentication is handled with simple API keys and/or cookies; not some custom protocol.

REST is a lot more than this and it's worth knowing the full gamut of RESTful principles; nonetheless, a number of APIs have flourished just by following the basic principles above ("lo-rest" as opposed to "hi-rest"). Even basic REST has the virtue of simplicity and working within the standard protocols of the web, as opposed to adopting a complex standard like SOAP. Empirically, the vast majority of Web 2.0 APIs are RESTful, rather than being based on SOAP or some bizarre ad hoc protocol.

Service-Oriented

How easy is it for clients to perform typical tasks? It's not good enough to just expose all relevant functionality in one way or another; you need to ensure frequent tasks can be fulfilled in a single call; it makes client programming easier, it makes the calls faster, and it reduces load on your server. For example, you may offer a web service that checks for Australian-ness. The naieve way is to offer several fine-grained services - "Does the user eat Vegemite?", "Does the user drink beer?", "Does the user have a kangaroo in their backyard?". This happens a lot because the API designer simply replicates whatever back-end functionality available. While it's potentially useful that these services are offered on an individual basis, the vast majority of clients want to call all three at once, since the user can only be called Australian if "yes" comes back for each answer. That being the case, there's a strong argument to expose a single Facade (Gamma et. al) function - "is the user Australian?" - that accepts all three parameters at once and delegates to the back-end as needed. That's service-oriented architecture.

Well-Documented

Provide enough tutorial documentation for the user to get up and running; and enough reference material for them to keep going. One-to-one discussions/emails between client developers and API owners should be minimal; that's not a scaleable solution. Where API owners do need to be involved is in keeping documentation up to date, and participating in the overall community by blogging, curating wikis, and so on. A general approach known as Documentation As Conversation. Under this approach, each time the developer answers a question (in a mailing list, blog, whatever), the response is public and becomes a permanent asset to the community. Now that is scaleable.

Library Support

You'll find that any remotely popular web API has a number of open-source libraries around it, offering language-specific bindings. Instead of posting some XML payload to http://example.com/users, a Java developer can simply call new User("joe").store(), a Ruby developer can call User.new("joe").store, and a PHP developer can call createUser("joe"). Helping to keep client code clean makes the API more attractive. Sometimes, these libraries are offered by the API provider itself. However, the provider is often not in the best position to build such APIs - it's the community of API consumers who are familiar with its workings and therefore the best API libraries are usually open-source projects developed by people with an itch to scratch. From a provider's perspective, the important message here is to focus on making the web-based service as clean as possible; don't worry much about providing libraries in all flavours of programming language, because if the service is compelling and cleanly-design, the libraries will come from the community before long.

Versioning

As with any software, the API will undergo changes in its lifetime. However, clients remain blissfully unaware of those changes, because any changes that occur are either: (a) backwards-compatible, meaning that clients to previous versions will continue to work just fine; or (b) explicitly versioned - a client points to http://example.com/1.0/service, which continues to work when the provider releases version 2.0 with URLs like http://example.com/2.0/service.

Ready to Go (No Manual Negotiation)

With Web 2.0 APIs, you don't need to call up the API provider, and arrange for a custom license. You just look up the docs, point your client at the API, and start consuming it. Ideally, you don't even require the user to apply for an API key - the Delicious API flourished in part because no key was required, according to founder Joshua Schachter. Even if you do require API keys (e.g. to track or limit usage), there should be no human interaction involved; your API website simply lets users create an account and automatically issues the API. Only when you want to start using the API in a more serious way - like making lots of calls or making money off it - will some providers require you to initiate a manual negotiation process.

Multiple Representations

Expose your resources in flexible ways. Multiple representations increases the likelihood that you'll be offering the most attractive format for clients, which in turn makes them more willing to use your API. Consider outputting the following formats:

  • HTML A block of content that can be displayed directly in the browser. The HTML should generally be free of any layout and formatting information; allow the client developer to influence look and feel by including ID and CLASS tags in key HTML tags.
  • XML XML is the gold standard for transfers and is easily manipulated in any programming language, as well as by Javascript inside the browser.
  • JSON Riding the Ajax wave, JSON has quickly ascended to be a popular transfer format.
  • Plain Text Sometimes a simple, plain-text, message is all you need - easy to create and parse providing the format is clear.

The focus here is on download formats, but there is sometimes an argument for XML and JSON uploads as well. However, with uploads, the more important format is that generated by HTML forms, i.e. a POST message containing CGI-formatted parameters.

How do clients determine which format they want? There are a few options:

  • Mimic the file suffix convention by accepting a suffix to the resource identifier. e.g. http://twitter.com/statuses/public_timeline.xml versus http://twitter.com/statuses/public_timeline.json. This is the simplest and generally most preferable option, but some RESTafarians will argue against it on the basis that the same resource should have the same URL, regardless of its representation.
  • Accept a "format" parameter - e.g. http://example.com/users/joe?format=json. This is the most commonly used option and is the ugly brother of the previous option - same basic idea, usually a bit easier to impement, but with less tasteful URLs.
  • Accept a request header called Accept:. This is a W3C standard header which can, by convention, be used by a client to request a particular type of format, e.g. Accept: text/javascript. It has picked up momentum following Rails Lead DHH's brainwave as to its importance, meaning many Rails-powered web apps and APIs respect this header. Many RESTafarians will see it as the "right" way to go. However, it suffers from a simplicity perspective, in that clients can't test different formats with the browser; they have to write a program or use a specialised command-line HTTP client like Curl.

A special case where clients need extra flexibility is with JSON, where On-Demand Javascript is typically used to pull JSON content down from an external domain. For reasons explained in that pattern, the service must add some text around the JSON, and this text must be provided by the client. (The JSONP protocol is becoming a popular way to design this interaction.)

SEO-Friendly

When someone searches for this kind of API, they find it. e.g. a user might search for "news api" or "news mashup service" or any other variant in Google; get your SEO right to ensure the results of these queries point to your service. Furthermore, submit your service to Web API directories like ProgrammableWeb and WebMashup.

LINKS

MSDN paper on web services patterns and anti-patterns