How RESTful is Your API?


It’s been over a decade since Roy Fielding wrote his seminal dissertation on Representation State Transfer (REST). Over this period we’ve seen SOAP/WSDL fall out of favor as the cool kids transition their services over to the REST paradigm. Or so it seems on the surface.

In reality, we’ve spent the last 10 years building various ad-hoc services over HTTP that borrow bits and pieces from the grand vision that Roy outlined. We’ve settled into a rhythm that, depending on your outlook, is either a naive implementation or an enlightened massaging of the initial approach. Is the glass half empty, or half full?

A Religious Debate

Your answer depends on your faith. I say faith because a group of RESTafarians defend Roy’s initial vision with near spiritual fervor. Yet, those with such devotion must accept that they’re on the fringe. Why? Virtually no popular APIs that claim to be RESTful today actually honor the complete tenets of the faith. The market has spoken and chosen to be pragmatic. We, the wild unruly developers, have chosen to do our own thing. Check out Facebook, Twitter, and Twilio. All have APIs that claim to be RESTful but have various unique properties that go against REST tenets.

Pragmatism has a variety of benefits which I’ll get to in a moment, but many APIs that claim to be RESTful vary greatly in their implementation. Thus, REST has lost any concrete meaning since the canonical reference is rarely honored in the real world. Fact is, there’s no jargon to describe the architecture of the vast majority of “REST” APIs in use today1.

This inconsistency complicates the entire ecosystem around HTTP based APIs. Consider the following aspects:

  • Learning – Learning REST is difficult with such an amorphous definition. There’s no canonical reference and those who subscribe with devotion to Fielding’s work must accept a striking disconnect between his vision and a large body of popular “frauds” in the wild.
  • Development – Developers often rely upon benchmark implementations, but today’s “RESTful” APIs provide wildly inconsistent conventions. Even after ten years, the tooling is weak and much of the work remains ad-hoc.
  • Consumption – Since every “REST” API is a unique flower, consumers must carefully read documentation to assure they understand the unique approaches of each provider. Lack of convention slows both understanding and consumption.

So Is Anyone Doing it “Right”?

Well, this isn’t about right and wrong, but here are a select few APIs that fully honor REST:

John Moore presented an excellent example of a truly RESTful API at Oradev. Wow, that’s a short list. There’s a sea of “REST” APIs by major players that just don’t fit this bill.

REST Cheat Sheet

So let’s get down to brass tacks. Outside of the rare exceptions above, today if you see an API that claims to be RESTful, it’s basically saying

“To work with our data, send the proper HTTP verb to the URIs in our online docs and specify whether ya want JSON or XML”.

Yep, it’s that simple, and about that casual too. We API developers are doing the simplest thing that could possibly work. No shame in that.

Here’s a number of common ways today’s RESTful APIs deviate from Fielding’s REST, along with an explanation of why the deviation may be useful.

REST Principle  

Why Deviate?

Honor HTTP Verb Semantics

Although REST prescribes using HTTP GET, PUT, POST, and DELETE verbs for CRUD operations, some clients can’t generate the less common PUT and DELETE requests. In addition, some overzealous firewalls block PUT and DELETE. Thus, some RESTful APIs accept all requests via HTTP POST or GET and place the HTTP verb in the querystring. For example, to delete user 124, the POST request would be for the following URI: /users/124?method=delete This technique is especially common in Ruby circles.

Utilize HTTP Status Codes

HTTP offers a rich set of 71 separate status codes which should be used to describe response status. Some “RESTful” APIs always return an HTTP 200, even when errors occur. This can be necessary when the client won’t allow the developer to elegantly handle any HTTP responses other than HTTP 200, such as when working with Flash. Twitter provides the best of both worlds by allowing the caller to request supression of HTTP status codes and always return a 200. Most RESTful APIs utilize a small subset of the potential status codes.

Self Descriptive Messages

REST specifies that the HTTP accept header should declare a custom and specific format. However, very few real world APIs do so. Instead, two popular compromises exist:

  1. HTTP Accept Header – Set the HTTP Accept Header to Accept: application/json or Accept: application/xml to request JSON or XML respectively.
  2. Pseudo URI file extension – Manipulating HTTP headers is slightly more work than simply changing the URL, so for convenience many APIs place the format in the URI by appending the format to the end of the URL. For example, to get a list of users in JSON: /users.json. This approach makes for longer URIs and is less RESTful since it ignores HTTP semantics, but it makes testing in the browser easier since no HTTP headers have to be manipulated.

Discovery via Linking and Hypermedia (HATEOAS)

Here’s the unicorn. Virtually none of today’s APIs honor this. To prevent tight coupling between the client and the service, truly RESTful APIs provide a discovery based API. Each call provides a reference to related calls. This allows the API to be highly evolvable because it avoids creating a coupling between the client and the server. This aspect is nearly universally ignored by today’s popular APIs, as made evident by the common pattern of publishing a list of URIs.

Hypermedia Aware Media Type

Examples of hypermedia aware media types include HTML, XHTML, Atom, SVG. Notice what this doesn’t include? XML and JSON. Neither offers a native way to convey a hyperlink. This constraint is necessary to support discovery. So, if you’re not interested in the benefits of discovery (and based on real-world uptake, few are), feel free to return XML or JSON.

No Version Number

Since fully RESTful APIs are discovery based, the API is expected to change at any moment. Thus, no version number is required. However, as we’ve discussed, the majority of today’s popular “REST” APIs document a static list of URIs that they support. Once you’ve accepted discovery is off the table, version numbers are beneficial to assure all clients aren’t required to simultaneously upgrade whenever the API changes. Version should either be the first segment /v1/users/ or in the querystring /users?v=1. If you plan to support concurrent versions of your API, specifying version should be required on day one.

No static URIs

A discoverable API can change regularly and thus should be interacted with solely through the links provided through API calls. However, the vast majority of today’s “REST” APIs document precise URIs and their corresponding return types. The benefit is efficiency since you can directly make the desired call, but at the expense of flexibility due to the tight coupling it creates between the consumer and producer. With “hard coded” documented URIs, if you change the API you need to support concurrent versions as described above, otherwise both consumer and producer have to change simultaneously.

For more insight on Pragmatic REST, check out this excellent video by Brian Malloy at Apigee.

So Is Microsoft Pragmatic?

In the .Net space, we have two common options for creating RESTful APIs: WCF’s REST Template and the new kid on the block, Web API. The former was recently deprecated in favor of Web API. Although both technologies are completely capable of supporting a fully RESTful API, out of the box neither does so. Both direct developers down the path of creating a pragmatic RESTful API in today’s most popular style. In short, this means neither directs the developer to utilize either discovery or leverage the power of native HTTP response codes.

Hammock

So what’s the big deal?

Okay, full disclosure, I believe in pragmatic REST. Hey, I strive to be a pragmatic programmer. Although I have no qualms with the deviation, the fragmentation and inconsistency need to be addressed with a canonical reference or convention that shines light on the deviations. In the meantime, developers must strive to make conscious and rational decisions when designing RESTful APIs. REST is an overloaded term, so it’s important that we’re clear and deliberate about the tradeoffs we accept when deviating from the initial spec.

Edit: This post hit the front page of Hacker News! There is plenty of great conversation over there in addition to the comments below.

1 The same issue has occurred today with AJAX. We’ve long since moved on to JSON from XML but AJAX remains in the vernacular. It’s understood that returning JSON over XmlHttpRequest can still be referred to as an AJAX call. (Yes, some pushed for using the term AJAJ but it didn’t catch on).

More Resources:

Comments

Christian Schröder — 2012-08-27

We recently worked with the Salesforce Chatter API and i think it fits the bill for discoverable API and is nice example. Also for documentation, they have their structures explained and have example json responses and requests.
See the entry point.

Nick — 2012-08-27

Landlords have tenants. Beliefs have tenets.

Nick — 2012-08-27

And it’s “brass tacks” not “brass tax”.

Tomasz Kubacki — 2012-08-27

“In the .Net space, we have two common options for creating RESTful APIs”
… and one good one: http://servicestack.net/

Geoffrey — 2012-08-27

“XML and JSON. Neither offers a native way to convey a hyperlink.”

Could you elaborate a bit on this? What do you mean “native way to convey a hyperlink”?

Christopher Miles — 2012-08-27

I’d be curious to know what you think of Webmachine and similar libraries. While they don’t really enforce any of the “rules” of REST, I do think they make it easier. I maintain a Webmachine-like library for Clojure; take a look at the sample application to get an idea of what a service might look like.

https://github.com/tnr-global/bishop-sample

Mark — 2012-08-27

Great post and presentation!!

Its also worth to mention that returning valid error codes prevents proxies from caching. So if you return 201 like facebook does with a specific error msg in the body, it could happen that this request is considered as valid and is beeing cached in the proxy.

Chad McCallum — 2012-08-27

I started writing a reply about the discoverability feature in REST and how it’s not implemented, and I ended up turning it into a post on my blog 🙂

Quick summary: There is no standard for discoverability, making it hard to implement on the server. Furthermore, I don’t think there’s any interest in a “rest browser” client app – client apps are where developers can control the UX and design specific to the API(s) they’re using, end users don’t want a generic api browser app, which I think the discoverability feature is really geared towards.

http://rtigger.com/blog/2012/08/27/discovering-the-value-in-discoverable-apis/

Zed — 2012-08-27

My favorite hilariously-non-REST API is TeamCowboy’s “REST API”: http://api.teamcowboy.com/v1/docs/

Somebody should make a big scorecard for web APIs, so we can see at a glance just how much in violation of REST principles they are. Of course, it might well turn out to be a big table of pure red X’s.

brad laney — 2012-08-27

I don’t understand. The bullet point is no version number. Yet you advocate using a version number? I understand for a brief moment you say not to have one, but then you go on for the rest of the paragraph explaining how you should do it. If you are recommended no version number, why not give solutions to problems when you don’t have version numbers, instead of saying “have versions”?

Daniel — 2012-08-27

What are your thoughts on the linked data space? They seem to have it right in a lot of ways that are hypermedia friendly, and prefer sparql endpoints over custom Apis for the GET side of things…

Dmitry Goldenberg — 2012-08-27

A couple of comments…

A. “With “hard coded” documented URIs, if you change the API, both consumer and producer have to change.” – not if you version your API. With versioning, consumers don’t have to change unless they choose to do so.

B. I see a lot of arguments in favor of specifying the API version through the Accept header, rather than as part of the URI path or query string. (Granted, it’s harder to test the API via the browser in that case but then again why test through the browser?)

C. I see a surprisingly small amount of discussions about how to formalize a given RESTful service with something like WADL or perhaps WSDL 2.0 (http://www.ibm.com/developerworks/webservices/library/ws-restwsdl/). I’m very curious about folks’ experiences with grammar-oriented tools like those.

Rob — 2012-08-27

I spent a lot of time working on a REST API for my company, it’s amazing how hard it is to design and how easy it’s so obvious once you’re done, anyway, anyone interested on more nitty gritty details can go here: http://www.websanova.com/tutorials/web-services/how-to-design-a-rest-api-and-why-you-should

Kyle Rush — 2012-08-27

On the point about status codes, if the API supports JSONP then it needs to always respond with a 200 status code. This is because most clients will not execute the JavaScript/JSON file that is returned with a status code other than 200.

peter chu — 2012-08-28

can anyone explain what is “Self Descriptive Messages REST specifies that the HTTP accept header should declare a custom and specific format”?

Tobias Sjösten — 2012-08-28

Hi Cory! Thanks for a good read.

I agree with your assertion that that majority of today’s “REST” APIs does not actually meet the criteria to be called such. And that’s *perfectly fine*. As I recently wrote, your API *doesn’t have to* be RESTful.

However there’s a perfectly clear definition of what the REST architectural style is. Your implementation either fulfills the criteria or it doesn’t. It’s either RESTful or (most likely) it isn’t.

I am 100% convinced that all these faulty labels comes from ignorance. Most developers doesn’t know better and they honestly confuse REST with HTTP. Maybe you’ll agree with this?

But where we seem to disagree is how to meet this ignorance. I believe there’s value in calling cows cows and horses horses. Rather than giving in I would love to see more effort in educating the fledgling developers.

Perhaps all we’re missing is some abbreviation for Nice HTTP Based APIs?

John Weeder — 2012-08-28

Fielding defines REST as client/server, stateless, cache-able, uniform interface, layered system, and code-on-demand (optional).

He says it doesn’t even have to be HTTP and he certainly doesn’t discuss HTTP verbs or status codes.

This article should titled “Does your API conform to my personal, subjective definition of what comprises a RESTful API”.

Anonymous

Scott — 2012-08-29

Can someone give me an idea what clients can’t generate PUT and DELETE?

larry — 2012-08-30

OK. JSON is not a native Hypermedia format, but what about JSON-Schema? (http://tools.ietf.org/html/draft-zyp-json-schema-03 , version 4 is out too). Is there an API using this properly?

Anonymous

Glenn Block — 2012-09-02

Overall I like your post, however…..I have a few bones to pick on your representation of Web API.

I think your “Does Microsoft Get it” section does not accurately represent Web API at all and lumping it in with the WCF REST template is a big mistake. I agree with your statement that there are some things that are not included in the box, like support for ETags for example.

However, I’d argue (and we worked with a many folks from the REST community to ensure) that it has all the foundational pieces to enable building a RESTful system and does not stand in your way. I’d also argue that it naturally leads you toward a RESTful system however it is not opinionated about REST and does not FORCE you down a RESTful path. So yes, it allows a more “pragmatic” path.

Based on your comments, I’d would ask you though if you actually did look at it?

1. Web API supports custom media types including those that use hypermedia. It includes an extensibility point for custom formatters. A formatter can be any representation including one with hypermedia. Web API ships out of the box with support for one one media type that can use linking, OData. However it can support a much broader set. For example if you head on over to Web API contrib you will see support for HAL via a HAL formatter.

2. Web API supports conneg out of the box. Media types are selected by default based on the accept header. This includes custom media types such as the HAL formatter I described above.

2. Web API maps to the uniform interface conventionally. An API controller is design to be a handler for a resource with each method (action) mapping against an HTTP method.

3. Web API supports a new easily accesible HTTP programming model. This allows you to directly manipulate HTTP requests and responses in order to adhere to the spec. For example it is very easy to return a status 201 and set your location header on a POST, something that the HTTP spec describes.

4. Web API supports a pipeline for addressing other standard HTTP concerns like ETAGs.

Glenn Block — 2012-09-02

Aside from that last rant, I do agree with the crux of the post. I am pretty hardcore about REST when the business constraints warrant it. However, it’s not the only way to build a system exposed over HTTP. It is however excellent for building systems where you need client and server evolvability over a long period of time, or where you have many different types of clients and a rapidly changing system. Many systems however do not fit that bill. Beyond that whether they do or do not, it’s up to the business to decide whether or not the investment is warranted. I agree with you there are a lot of misconceptions around REST vs NOT. For many folks in the REST community / the restifarians the concern is not so much whether or not you build a RESTful system or not, it is whether or not the term is used appropriately.

Glenn Block — 2012-09-02

In terms of the WCF REST Template, I don’t think it actually is easily capable of a truly RESTful api. For example, see how easy it is to plug in a custom hypermedia format or to support ETAgs. Yes it’s technically possible but ALOT of work. The template makes it easiest to simply expose your existing web services via URLs, there’s a big difference between that and a RESTful system. Also you find yourself constantly knocking your head against the wall based on early design decisions which were heavily impacted by SOAP. That’s one of the reasons we built Web API and ultimately pulled it out of WC altogether.

OK, I am done….

Anonymous

Anonymous

Philippe Mougin — 2012-09-03

Trying to find the origin of the demarcation between REST and non-REST-but-claiming-to-be-REST APIs is interesting. But I believe you are wrong in identifying it as “pragmatism”. And the reason is that it can often be very pragmatic to build what you call “discoverable” APIs. I do that all the time when we need loosely-coupled, evolvable systems: that’s a very pragmatic choice. Thus, this ideal-REST vs pragmatic-REST demarcation isn’t the right one, I beleive.

So, why are there non-RESTful API that call themselves RESTful ? In my 10+ years of REST aware consulting, in about 99% of cases I came across it was simply due to ignorance (I did it at some point too, of course). Usualy, people knowing what REST is and producing a non-RESTful API don’t call it RESTful (unless they are insane).
BTW, I also observed this in big shops (MS, Amazon, etc.) If you think people there magicaly aren’t as clueless as everyone else, I think it’s probably bc you haven’t meet them! Hell, even someone of the caliber of Don Box said that they did SOAP the way they did bc at that time they didn’t understand the Web and were beginers Web wise.

Kushal Dave — 2012-09-07

Great post. Two other reasons to deviate: JSONP forces you to return 200s, and trying to constrain response size to work well with mobile devices forces you to avoid discoverable APIs. Also, it seems like even a discoverable API requires some shared understanding of what should be available, and versioning when the server wishes to break that contract?

Anonymous

Anonymous

Anonymous

Trevor — 2016-04-01

Fantastic post. Another term for this “pragmatic REST” concept is RESOURCEful APIs. You can read about it here: https://medium.com/@trevorhreed/you-re-api-isn-t-restful-and-that-s-good-b2662079cf0e