In the case of closing an account, it depends on what actually happens when you do so, but I would normally have a "status" attribute and use PATCH to update that.
PATCH /users/123
[{ "op": "replace", "path": "/accounts/12345/status", "value": "closed" }]
I personally think that's less readable than the original, but I agree that it seems to more closely fit the REST standard.With the deposit, I don't really understand what's changed here from the original. To me, it just looks like deposit has been pluralised, and everything else is the same:
POST /account/12345/deposits
amount=10Regarding the deposits, the difference is that 'deposits' is a collection of deposit resources vs 'deposit' as a verb. I think in this case it makes a lot of sense to do it that way, as you can then GET /account/12345/deposits and see all the deposits ever made.
POST /accounts/12345/deposits
instead of: POST /accounts/12345/deposit
Perhaps your example would be more obvious if it had different terms, where the noun and verb were more distinct - maybe 'game' and 'play'.Even then, from experience, you end up with some horrible URLs just so it's RESTful. While I try to follow REST, I balance it against making the API readable by human beings.
No, you don't. RESTful applications use URLs as opaque identifiers, and communicate all information via resource representations. Communicating information via resource identifiers is decidedly not-RESTful, so any particular URL structure chosen to communicate specific information in the URL is, ipso facto, not RESTful.
POST /documents/12345/print
To me, while this was not RESTful, it was the most readable way I came up with. When I asked somebody who had more experience with REST than me, he suggested I build the URL like this: POST /users/123/print-jobs
url=/documents/12345
Doing this, I would have to add validation to make sure it was a printable URL. Also, there was no corresponding GET request, so it seemed pointless. And it made the code weirder, as the 'print' action would be separated from the rest of the actions on documents.So how would you do it instead? Or you would do it the same way, and just not worry about the problem?
It seems that consensus on how to do REST breaks down when you have custom verbs.
POST /documents/12345/print-jobs
And you say there's not corresponding GET request, but maybe there should be? Perhaps you'd want to list print jobs, get the status of a particular job, and maybe cancel it?I don't have a print queue because nobody has ever asked for one or shown the need for one.
> When I asked somebody who had more experience with REST than me, he suggested I build the URL like this:
> POST /users/123/print-jobs
What was the logic: neither version is more RESTful, even if you ignore the role of URLs in REST and adopt what seems to be the usual definition of RESTful URLs used by people who use any coherent definition: the URL represents some logical hierarchy of resources.
In this case, your original "POST /documents/12345/print" implies a collection of print requests (I'd probably call it "prints" or "print-requests" rather than "print", but that's a minor quibble) pertaining to a particular document, to which a new request is added when the user wants to print the document. Sounds perfectly sensible.
The alternative offered suggests a list of print jobs belonging to a user, which is also sensible. But there is no strong reason to prefer one over the other.
And if you were actually RESTful, it wouldn't matter, because your resource representation for the print job/request would actually include both the URL and the user. (And maybe status and other information.)
Both your original (with no representation) and the alternative (with the user in the URL and the document in the resource representation) aren't RESTful because they have information that logically belongs to the resource in the URL and out-of-band context rather as part of the resource. But that's not a matter of URL construction, its fine for a URL scheme to correspond to information about the resources, as long as the information is actually still part of the resource.
> It seems that consensus on how to do REST breaks down when you have custom verbs.
If you have real custom verbs, then you may need to extend HTTP's set of methods (it wouldn't be the first time that has been necessary -- PATCH isn't a base HTTP/1.1 method.)
But there is a difference between a generic action on resources of the type represented by an HTTP method and an action-in-the-domain, and it sounds in your case "print" is an action in the domain, which is an event which should have a corresponding noun -- and thus a resource representation -- in the model. But while URLs are inherently hierarchical, real relationships in real domains are often webs, and so there's not one true way to map it into a hierarchy.
One thing that helps is not nesting resources too deep, to avoid having really long URLS.
POST /transfer
from_account_id=12345&to_account_id=67890&amount=10
Perhaps I've misunderstood your comment, as I don't really understand why this is better than the original: POST /accounts/12345/transfer
to_account_id=67890&amount=10
or even: POST /accounts/12345/withdraw
amount=10The key point though is that 'transfer' is the resource to perform all three of the original deposit/withdrawal/transfer actions.