Five Clues That Your API isn't RESTful

I get a lot of emails asking me to get involved with API projects, and that means I see a lot of both implemented and planned "RESTful" APIs. Now, I absolutely love REST and for a data-driven application, it would be my first choice. A service of some other description may work better for other scenarios or skill sets, and non-RESTful services can be very, very useful. If you tell me that your service is RESTful, then I expect it to be. If you're not sure, look out for these clues:

It has a single endpoint

I don't really care what else is going on in your API, any "RESTful" API which has a statement such as "all requests are made to http://example.com/rest" is ... not RESTful. REST is all about handling representations of resources, each is represented by its own URI and we operate directly on that. If it looks like "pretty URLs", then it's probably along the right lines.

All requests are POSTs

While it is completely valid to have POST requests in a RESTful service, if all requests to this API are to be made using POST, it's very unlikely to be RESTful. POST requests create new resources, so if that's all that is happening, then great. If you're able to retrieve, update or delete data, then this isn't a RESTful service.

Response metadata is in the body, not header

Any sign of data along the lines of status = success in the body of the response again means that this isn't RESTful. REST takes advantage of the HTTP envelope format and puts all the supporting metadata into the headers of the requests and responses. The body of the representation is literally just the representation of the resource.

There are verbs in the URL

This can be quite subtle but shows up especially with subresources. Look out for something like /item/42/activate ... REST deals with resources, an "activate" isn't a resource. If you're modelling a service, maybe something like /item/42/status could make a better alternative.

The URL includes method names

This is the easiest "tell" by miles. The most obvious non-RESTful aspect is when the URL has something like ?action=getRecentItems in the URL. Sometimes, this clue gets combined with another one, and the method name will even be in the body of the message - definitely not very RESTful!

Do We Care About RESTfulness?

Personally, I think that how useful an API is, and how RESTful it is, are entirely uncorrelated. Do take care though when describing your "sends-data-over-HTTP" application as "RESTful", because chances are, it might not be. Look out for anything with the word "REST" in it (if you ask nicely I might share the comments that I don't publish on this post) because REST has very specific criteria that can sometimes be difficult to adopt, and for some reason people interested in this subject seem to like to tell other people they are wrong a lot!

15 thoughts on “Five Clues That Your API isn't RESTful

  1. For better or for worse "REST" has become something thrown onto API descriptions without really thinking about it. It has become the a buzzword that is used because people associate value with it.

    Personally, I think that how useful an API is, and how RESTful it is, are entirely uncorrelated.

    Exactly, and this needs to get communicated in a much louder way. There is too much fear that if their API isn't "RESTful" it some how isn't useful or good. We need to get over that thinking.

    • Agree, I'd like to hear voices other than the REST "enthusiasts" (that's my polite term for those people) and see more people building APIs even if they are imperfect by some measure

  2. RE: Verbs in the URL: I'm having trouble wrapping my head around that one. It seems intuitive that POST request to a url such as /item/create would indicate that a new item is being created and would therefore be appropriate. How would you create/update a resource, avoid using verbs in the URL, and still convey that a resource is being created/updated?

    • You would use the verb in the HTTP header. Depending on your implementation, this could be:

      GET - gets a resource
      POST - updates a full resource
      PUT - creates a resource
      DELETE - deletes a resource
      PATCH - updates a partial resource

      There's no need to put any of that information into the URL, since HTTP already has all that built in.

  3. The verb in a request is based on the request type - PUT, POST, DELETE, GET etc.

    So the endpoint /item with a GET is different than a POST or PUT. The url should describe a noun - generically. /item with a GET returns a collection, /item/21 with a GET returns an entity, /item/21 with a POST should throw an error as POST should be reserved for creating new entities and the passed id should not exist at that time.

    http://stackoverflow.com/questions/630453/put-vs-post-in-rest

  4. Jeremy: Remember that REST is all about working with resources. If your resource is `item` with automatically incremented IDs, it could be that you'd POST an entire resource, like {"name":"Tobias"} for JSON, to /items and it would then show up at /items/321. In some rare cases it could be that you'd PUT the resource at a specific location, like /items/tobias.

    However, these often hardcoded URL schemes are also an indication your API is not RESTful. Hypermedia should be the "engine of application state" (HATEOAS), meaning this documentation of what to GET or POST to where should be discoverable through the API itself.

    I wrote about this a while back, "Your API is not RESTful": http://vvv.tobiassjosten.net/development/your-api-is-not-restful/

    "how useful an API is, and how RESTful it is, are entirely uncorrelated" — that hit the nail on the head!

  5. Pingback: Programowanie w PHP » Blog Archive » Lorna Mitchell: Five Clues That Your API isn’t RESTful

  6. "There are verbs in the URL" - wrong.
    Try to write here example how to authenticate user by login and password without having verb in API.

    • Let's stay away from the "right" or "wrong" labels please, that's exactly what causes at least half of the problems in this area!

      RESTful URLs do not contain verbs, that's a fact. Does that lend itself well to implementing something like a traditional login flow where a username and password is exchanged for a session cookie? Not really, but RESTful systems usually use a mechanism such as an Authentication header for this purpose. Or check out how GitHub allows you to create "authorizations" http://developer.github.com/v3/oauth as one alternative approach.

  7. Exactly, and this needs to get communicated in a much louder way. There is too much fear that if their API isn't "RESTful" it some how isn't useful or good.

    Sure, an API that is not RESTful can be useful — but there is value in creating things in a way that is consistent with what many others are doing. When you make a RESTful API developers already know how to use it if they have used any other RESTful API — the conventions are the same even though the underlying data is different.

    So, I think that the advantage of using a RESTful approach is that developers have to spend less time to get up and running with your API. The tools they have used for others work with yours with minimal changes. More importantly, the thought process (get, update, create, delete on an object) they use when considering how to implement your API is the same thinking they have used for others.

    • This is an excellent point, standards are always a good thing and ideally every service should be built in compliance with them. Sometimes, however, it makes business sense to break the "rules" (for example I recently built a supposedly RESTful API for a client which wasn't able to issue a DELETE request). My advice is therefore that any service which meets any of the points in my post should be described simply as "an HTTP web service" and avoid all the labelling and resultant flame wars of REST.

  8. I would not be so religious in preaching REST rules.

    REST is fine, except that it stumbles in real world problems that make some its conventions inconvenient, to the point you realized that you should not follow them.

    For instance, there are much more types of actions that the limited number of HTTP methods can accomodate.

    Lets say you have an API call that can preview how certain data will be rendered. That API call does not alter data, so POST, PUT, DELETE and PATCH are not appropriate. You are left with GET, which makes sense because you are retrieving data.

    The problem of using GET is that parameters are passed via URL. This is fine for parameters with a limited size. However, if you want to pass parameters that exceed the limits of URL of certain Web servers and proxies, the URL may get truncated. So, GET is not adequate. You would not to switch to POST because you would not have such a low parameter length limit.

    Another aspect is the problems of firewalls or proxies that block any type of requests except GET and POST. So if you need to access an API that requires PUT, DELETE, PATCH, or whatever, those HTTP methods are inadequate.

    It is not by coincidence that browser based Web applications only use GET or POST.

    In sum, REST is fine as a set of conventions, but if you do not follow its conventions, it is fine because that you need to adapt to the constraints of the real world.

  9. Hey Lorna, I'm a little curious about how you feel about the "standard" these guys are trying to popularize when contrasted with your assertion above that "Response metadata is in the body, not header" is anti-REST. Granted, theirs is with respect specifically to JSON responses but it fits within the assertion I think...

    http://labs.omniti.com/labs/jsend

    I see the logic in both approaches... Would love your insights though.

    • Standards are always good, but yeah I really dislike the status-in-body pattern. HTTP gives us this already

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>