Five Clues That Your API isn’t RESTful
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!
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.
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
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.
For such simple oiperations, HTTP verbs suffice. But what if you want to modify a list of items in some application specific way? In my opinion issuing a sequence of “RESTful” POSTS on each one of the “resources” is nonsense. And nonsense is also making up artificial “resources” whose sole purpose making your URL “verb free”, i.e. POST creditCard/123/derogatoryPaymentCheckOnExperian with no “derogatoryPaymentCheckOnExperian” “resource” on your db, instead of the simple: POST creditCard/123/controlDerogatoryPaymentHistoryOnExperian.
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
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!
Aha! Thanks, all. Avoiding the use of verbs in a RESTful API makes a lot more sense now.
Pingback: Programowanie w PHP » Blog Archive » Lorna Mitchell: Five Clues That Your API isn’t RESTful
“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.
Easy one, POST to “/sessions”. The idea is to think of “things” that you are manipulating, in this case creating a new user session.
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.
You make a wonderful point, but I think there are some use cases that deserve their own standard, something independent of REST. We we give tightly-coupled Web APIs a new banner to march under, we can have the benefit of a standard way of approaching these APIs without breaking all the rules of REST. You can read about one such proposal here: https://medium.com/@trevorhreed/you-re-api-isn-t-restful-and-that-s-good-b2662079cf0e
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.
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
Pingback: RESTful pagination | webbricks
Hi,
Without verbs how would you for example activate or deactivate a user?
I would have done – api.example.com/api/v1/users/1234/activate but you say this is incorrect, what alternatives ar there?
Cheers
There are two main options here. One is to update the user record by GETting the record, changing the “active” field and then PUTting it back. The other is basically what you describe here: create a sub resource /users/1234/active and then POST to it to activate and DELETE from it to deactivate. Hope that helps!
If this is the RESTful way of doing it, then it seems to me that it makes more sense to avoid using REST in this instance. If using REST makes the call less clear or intuitive (which is always more important than following a standard) then it probably makes sense not to use it.
How nice to come to the end of some comments and see a series of replies that sums up the discussion and even provides some closure:
Owen: “Some things seem like they would be hard to do with using a verb.”
lornajane: “To do it RESTfully, you just need to rethink your url and put it into a form that is supported by PUTs and POSTs, etc…”
Chris: “Then I probably shouldn’t use REST in this case, since doing so would sacrifice clarity for correctness.”
I think all of this is correct, and I come to the same conclusion that Chris does. To completely misquote Isaac Asimov: Never let your sense of what’s correct get in the way of doing what makes sense.
The straightforward RESTful way would be PATCH /api/v1/users/1234?state=active. This is quite intuitive once you are familiar with REST.
Thanks for this article. I know this has been up for a while, but I was bitten by the “Is that really RESTful?” bug when trying to design a query endpoint for an API today. For our particular application, REST (even if just for this part) didn’t seem to fit very well.
“Personally, I think that how useful an API is, and how RESTful it is, are entirely uncorrelated. ”
I hate days where I find myself squeezing something into a particular paradigm when it really doesn’t matter. You saved me from such silly follies today. Thank you.
is this restful or not, if not what is the correct way to make it restful
http://example.com/index.php?route=api/product/getgroupedproducts&filter_name=mobile&limit=1