I would say that Representational State Transfer (better known as REST) has become the de facto standard for APIs on the web, except that I can’t, because REST is not a standard. It’s a set of design principles created by Roy Fielding as part of his Ph.D. dissertation. As a result, there is much discussion (and confusion) out there on the web about how to apply these principles in practice. It seems that a rough set of conventions have emerged, as excellently collected in a recent RESTful API best practices blog post by Vinay Sahni.
However, the question that most API designers (including Vinay) seem to be asking is, “How can I best apply the principles of REST to my API design?”. The ensuing academic discussion leaves out one critical component: the users! I want to encourage all of you API designers out there to ask a different question instead: “How can I apply the principles of REST to create a great API?”
If you look at the prevailing conventions from this perspective, you will see some egregious usability anti-patterns.
Anti-pattern 1: Hide Critical Information in the Link Header
One common convention is to use the HTTP Link header to store pagination information. Yes, the Link header itself is as much of a standard as anything on the Internet, with its own Standards Track RFC. And included in that RFC are relations for pagination, like “next” and “prev”.
But think about this from a usability standpoint. No HTTP client in common use shows the HTTP headers by default! Curl doesn’t, wget doesn’t, and web browsers certainly don’t. Your users aren’t going to find this information unless they’re specifically looking for it. And this is critical information — it’s telling your users that the response is incomplete and further action is required on their part. So, unless your users have already read your documentation carefully or are familiar enough with this convention to think to check the Link header, they will be left utterly confused. Instead, why not just include your pagination information in the body of the response?
Anti-pattern 2: Avoid Verbs in your URLs at All Costs
A basic tenet of REST when applied to HTTP is that your URLs should name resources (nouns), not actions (verbs). I am not proposing a return to RPC semantics by any means, but keep in mind that the HTTP request does contain one verb: the HTTP method — GET, POST, PUT, DELETE, and sometimes PATCH.
What I am proposing is that, in certain limited circumstances, moving this verb (or an equivalent one) into the URL can improve the usability of your API.
Fallbacks for methods other than GET and POST
A problem in practice is that some HTTP clients and proxies don’t support or allow methods other than GET and POST. The prevailing convention for handling these cases seems to be to resort to a non-standard HTTP header that overrides the HTTP method. Depending on who you ask, this header might be called X-HTTP-Method, X-HTTP-Method-Override, or X-METHOD-OVERRIDE. These headers not only violate the HTTP standard, but can have security implications as well.
I would like to propose a simple alternative. Keep DELETE https://my.api/resource/3 as the standard way to delete a resource, but simply add POST https://my.api/resource/3/delete as a fallback for DELETE-challenged clients. I’m sure this suggestion will make the RESTafarians’ skin crawl, but why is it better to violate the well-specified HTTP standard in this case than to violate the ill-defined concept of a RESTful API? It’s a hack either way. At least this hack is easier for your users (no need to muck with HTTP request headers) and isn’t going to cause you any headaches when it comes to security.
Same URL for Fetch and Edit
This next one is a bit more controversial, so let me first say this. Feedback is a critical part of UI design. I don’t think it’s controversial to say it’s a good idea to let the user know whether their action was successful, their request was malformed, etc.
This is where I see some problems with using the same URL to both fetch and edit a resource, only changing the HTTP method. What feedback does the user receive in each case? With the GET, the response is straightforward — it’s the resource they requested. If they get the resource back, it worked. With the POST (or PATCH), things get a bit more fuzzy. Probably the most intuitive thing to return (as Vinay recommends in his blog post) is the updated resource itself. But this is the same thing the GET returns, just with a few fields changed! So, if I accidentally send my edit as a GET, it’s not very easy to tell that anything went wrong.
It’s true that REST-savvy users will not have much trouble with this. But you may want to ask yourself: how certain are you that your API users are REST-savvy? Perhaps a separate /edit endpoint could provide better feedback. Then, if the user accidentally sends a GET request, the API can just return 405 Method Not Allowed. You can even support both and let the user choose.
I would encourage all API designers to think about usability first, and how RESTful their API is second. There is no single REST standard, anyway; no RFC to violate by taking some artistic license in your API design. You may technically lose the privilege of calling your API RESTful, but according to Dr. Fielding, you probably already lost that privilege, anyway.