Most of this has little to do with REST at all, e.g. URLs don't actually matter in REST (because of HATEOAS) and should be considered opaque. This is more HTTP API best practises (best practise in the author's opinion). REST has become a meaningless term.
This debate was settled almost a decade ago. URL forms don't matter in theoretical dissertation REST, but 15 years of practice has firmly decided they are indeed a core part of real-world REST.
HTTP based web services existed before Roy's dissertation and while the formalizing of them helped them mature rapidly, the idealistic principles aren't the final word on the subject anymore. Real world practice now is.
My point is that APIs are an exception mostly because developers are conditioned by the RPC "APIs" mental models, which doesn't take effect when they're thinking about a "website" instead, not due to some fundamental technological difference.
And having extra irrelevancies to worry about such as "Version your API", "Use nouns, not verbs", singular versus plural, and nested resources are the consequences of being "practical".
I have also found collection+json and hypermedia application language (HAL) to be useful.
Plus, I have spent a bunch of time reading the Restful Web APIs book from O'Reilly. Useful for me, as a relative newbie, in providing some logical foundation to start from . . .
REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them. That’s fine with me as long as you don’t call the result a REST API.
I've found a number of people who point at the Github api as a good example of a RESTful api that includes hypermedia links for clients to follow rather than constructing URI requests manually. It looks good to me.
I'd disagree. If I were critiquing a non-REST API over HTTP, I wouldn't get upset about requiring a call to POST /processOrder at all, whereas I'd begin to convulse if they said it was a REST API.
That is more of an indictment on how poorly REST has been presented. It remains mostly impossible to get a very good definition of REST or point to an API/whatever that is a good example of REST.
Indeed, and this is why I think "RESTful" APIs are a huge problem - they're largely undefined. We have SOAP for defining these things formally without the need to worry about implementation differences. Unfortunately it was essentially abandoned because it was too complicated and excessive. It would be really interesting to see something SOAP-like with some more modern features and made a bit simpler.
> I'm sorry, did you just suggest something SOAP-like with more features?
I suspect that where you seem to have read "more {modern features}" but ultramancool meant "{more modern} features".
That is, I think the intent was that the features of the otherwise SOAP-like thing would be more modern than the features of SOAP, not that SOAP-like thing would have more features than SOAP and that those additional features would be modern.
Indeed, this is a correct assessment. Sorry about my poor phrasing. In particular I was thinking things like using the HTTP protocol correctly in a similar manner to more "modern" RESTful APIs, removing some of the unnecessary things and allowing for alternatives to XML like json for size and ease of access from web platforms.
Uhm, I mentioned that in my post. Thanks for re-iterating? Personally, I thought it was pretty simple, but I come from a land of CORBA. I don't think the ultimate solution for "this structure is too complicated" should be "fuck structure altogether" though. Rather, we should try to arrive at a simpler structure.
URIs matter and REST matters because people have been using them incorrectly for so long. Common mistakes like putting verbs in URIs instead of using HTTP methods. You are correct though, about the design of verbs don't matter (outside of conventions) as long as everything is done correctly.
Just off the top of my head: if you think of verbs exposed in URLs as a common REST mistake, you may not have fully absorbed the HATEOS concept. If you have HATEOS, you're unlikely to have verb URLs.
I agree, that is what I was trying to say. If you are doing things correctly (fully absorbed the concept), everything will be fine and no one has to argue about REST, HTTP, and URIs.
I was expecting more from this HATEOS stuff. Everything I read before sounded like full auto-discovery of APIs.
But the only thing seems to be including possible next URLs in the responses.
Don't get me wrong, this is a good thing. It gives the backend devs more freedom and the frontend devs need less documentation to find out what's possible. But everyone still has to write the interfacing code to these APIs :D
At the risk of butchering the concept for the sake of simplicity:
In a HATEOS API, clients need to know exactly one entry point endpoint. Nothing else is hardcoded. There is no Python code that happens to know "if you want to add a widget to a product, you POST to /product/$X/widgets". The API itself tells you where to go.
An acid test: assume your API entrypoint is /api. If your API keeps HATEOS kosher, you could in a serverside update change every other URL endpoint in the application without breaking clients, because the clients would be getting those URLs from the entrypoint URL dynamically anyways.
(That's not really the point of HATEOS, but it's a side effect).
There is nothing wrong with simple HTTP APIs, and a lot wrong with explicitly RPC (verb) oriented APIs in general, so adhering to REST principles isn't an absolute good.
This might be the point where 'dragonwriter tells me I, too, have misunderstood HATEOS. :)
One thing that's always bugged me (in a small way) about REST is that proponents/experts always insist that REST does not rely on any specific protocol (HTTP) but all discussions of REST carry a very strong assumption that specific actions are mapped to specific HTTP verbs. For example, Martin Fowler's doctor appointment scheduling example gives you "discoverable" hypermedia links for canceling and editing appointments, but they use the same URI and there is an implicit assumption that the client knows how to distinguish between the two by choosing the appropriate HTTP verb. It just seems kind of strange to say, well, REST isn't tied to HTTP, it's tied to any request/response protocol where each request is bound to a specific URI and one of these core HTTP verbs. Wouldn't implementing REST on any other protocol look an awful lot like tunneling HTTP over that protocol?
Another small gripe is the notion that a REST client need not have URIs to specific resources/actions hardcoded in them. The fact that you don't hardcode the specific URIs but rather a bunch of link strings that you then use to look up URIs makes this a lot less interesting. The way it's described generally makes it sound as if there is some kind of magical mechanism by which a client actually learns of the existence of a given endpoint, which would truly be magical. Really, all that's happening is that a client knows a name for a specific endpoint that it's looking for, and the API provides a way to look up the specific URI for that endpoint. Makes things tidy, but it doesn't seem like a feature that has much practical impact if you follow a "URIs shouldn't change" philosophy anyway.
Yeah, I was just about to go edit that. "Cool URIs don't change" and all that. It would still be bad to change URLs; you just wouldn't need to update the client API code.
The most useful resource -- and its quite concise -- on HATEOAS is this 2008 blog post from Roy Fielding (who defined REST, so it's straight from the proverbial horse's mouth):
> "The principle is that a client interacts with a network application entirely through hypermedia provided dynamically by application servers. A REST client needs no prior knowledge about how to interact with any particular application or server beyond a generic understanding of hypermedia. By contrast, in a service-oriented architecture (SOA), clients and servers interact through a fixed interface shared through documentation or an interface description language (IDL)."
a truly RESTful service that follows the HATEOAS pattern doesn't require documentation to be hosted separately. it will supply all the information necessary directly through the RESTful service.
> a truly RESTful service that follows the HATEOAS pattern doesn't require documentation to be hosted separately.
It might need documentation of the special media types it relies on to be hosted separately (one place where most "REST" APIs fail to follow HATEOAS is that they reuse generic media types but rely on out-of-band descriptions of the "real" format of the data, so that a client familiar with only the media type and the data would not semantics of the resource representations being returned by the API.)
Web browsers have a human intelligence driving the interactions. API clients don't. Hence the huge gap, and as far as I can see, the rather pointlessness of HATEOAS.
In fact, I'm still totally lost as to the usefulness of REST at all, except as a generic term to mean RPC over HTTP except not as clunky as SOAP. Which isn't what REST is. I've yet to see or use an API that was easier to deal with because it was REST.
The Googlebot drives REST APIs just fine, and would be impossible to write using an RPC model.
I've yet to see or use an API that was easier to deal with because it was REST.
Of course not, because people actually want to use RPC, and so shoehorn REST into RPC-like models, which destroy its usefulness.
If you're sitting at your computer and deciding that you're now going to write a client against Service A's API, the point of REST was missed, and Service A might as well have used RPC.
The point of REST is to decouple the client from the specific service, using the Uniform Interface and standard formats to allow clients to interact with any service that "speaks" the same formats.
But nobody's is thinking on those terms. Everyone is still thinking that it's perfectly normal and OK to waste years of developer time rewriting the wheel, over and over again, for each new service that pops up. This is fueled by the services themselves, of course, whose companies want to use their API to lock you in.
So no, while this is the normal mentality, you won't see any major gains from REST.
Is probably something you already know. Consider this: in your HTML home page you link to some page to do some action, tomorrow you create a new page and add the link to it to your home page, magic done, your generic client (web browser) is now able to show the user a new functionality, no need to change anything on the client. If you have a native Android App (that does not use the browser) you probably need to update it.
> ... That only works because there's a human driving the browser.
It works for unattended web clients (like Google's spider) too -- and not just for generating basic listings, but for structured schema-based data to update Knowledge Graph. That's one of the foundations of many of the new features of Google Search in the last several years.
it works because links are defined in the hypertext and discovered by clients (say by the browser when a page is visited), so are new functionalities. A (well designed) web app is always up to date. In an Android native app the API URL(s) are (99%) hardcoded using the knowledge about the API of a certain moment. This auto-discovery mechanism works also for a spider.
Auto discovery does not mean that links are understood (@rel may help but..) you may need a human to decide but..
Suppose a (rest) application that lists links to its "services" in home page with the "service" page describing the service following a certain standard. You may have a bot that checks periodically the application for services you are interested in and be notified if a new service is available, with the possibility to navigate to the page and possibly subscribe.
1. why do you necessarily assume that REST API's are only accessed by robots? A human developer can benefit from HATEOAS quite a lot by being able to use the RESTful service's outputs as its own documentation. The developer can discover the features of the API by following links provided in the API outputs.
2. An API client can check that it matches the interface specified by the API just by comparing the URI's it is accessing with the URI's provided by the HATEOAS part of the RESTful service. You can automatically detect changes, breakages, or new feature introduction. This doesn't spare the client developer from having to update their client code, but it gives that developer a powerful tool for getting updates about the RESTful service.
So basically, putting structured comments in the API output would have the same effect? Instagram does that. They don't update their API docs, and instead put comments in the results so you might stumble on them while debugging
But specifically to hyperlinks, I don't see the point. For instance, a search API might want to return s next link. So they can do that with a URL. Or they can just include a next token I pass to the search API. The latter is somewhat easier to program against since you often abstract the HTTP/URL parts.
REST was in the original HTTP spec. Most people were just doing it wrong the entire time until recently when it became trendy to go back to the root REST ideals. And by most people I mean everyone involved in SOAP and RPC and other nonsense like that.
No, it wasn't. Fielding's dissertation, in which REST was defined, argues that a certain set of principles were an underlying foundation of the structure of the WWW architecture in its original construction, proposes REST as a formalization of and update to those principles, and proposes further that updates to the WWW architecture should be reviewed for compliance to the REST architecture. [1]
So REST is a further elaboration of a set of principles inferred from the original HTTP spec, not something present as such in the original HTTP spec.
I must disagree. REST is defined by four interface constraints: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch... and identification of resources is the first principle. This functionality is implemented by URLs in HTTP and is therefore critical. HATEOAS (the 4th principle) also seems to be gravely misunderstood. It only means that the API should have a version that is fully useable in a web browser.
> HATEOAS (the 4th principle) also seems to be gravely misunderstood. It only means that the API should have a version that is fully useable in a web browser.
No, it doesn't. In fact, a REST API can fully meet the requirements Fielding lays out without having any implementation that uses any communication protocol used by any web browser. REST is an architectural pattern that is independent of communication protocols.
What the URLs look like is not a concern of REST though.
Can you cite your latter point, since that's contrary to how I've seen HATEOAS explained? Many libraries do expose a browser-navigable form of the API, but I can't see how that's how it's originally defined nor it being a requirement.
Are you saying that it's just as good to have a URL be /fj3849-2qfjimpa as /customer? I agree that it is not strictly a REST principle, but in an API clarity matters. If we are talking about good practices, would your rather work with an REST API with readable, concise URLs or not? Maybe I am missing the point but the URL is one of the major building blocks of REST and choosing quality ones is a large part of API design.
I stated that HATEOAS is widely misunderstood so it isn't surprising that there are conflicting descriptions out there. No matter what your interpretation, this principle is about hypermedia and application state and says nothing about what a URL should or should not be.
> Are you saying that it's just as good to have a URL be /fj3849-2qfjimpa as /customer? I agree that it is not strictly a REST principle, but in an API clarity matters.
No, it is strictly a REST principle that the meaning of URLs other than the entry point is defined completely by the context in which they are used in resource representations and the definition of those resource representation (i.e., media types).
An implementation of a REST API may happen to present URLs with a consistent relationship of location structure to semantic meaning in the API, but that's entirely outside the scope of the REST API per se.
> If we are talking about good practices, would your rather work with an REST API with readable, concise URLs or not?
If you are using HATEOAS, URL format, readable or not, isn't a feature of the API at all (its a feature of a particular implementation of the API, but its one that clients don't need to be aware of.)
> Maybe I am missing the point but the URL is one of the major building blocks of REST and choosing quality ones is a large part of API design.
You are missing the point. URLs as opaque identifiers is one of the major building blocks of rest, and if you are worried about choosing one as part of "API design", you aren't building a REST API.
The resource representation (media type) should tell you what the URLs used in it are for, not the URLs themselves.
> I stated that HATEOAS is widely misunderstood so it isn't surprising that there are conflicting descriptions out there. No matter what your interpretation, this principle is about hypermedia and application state and says nothing about what a URL should or should not be.
If you need to communicate the URL structure and identify relative URLs for various endpoints to describe an API, it is not a REST API following HATEOAS; "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API)." [1]
HATEOAS clearly is misunderstood, as you've just demonstrated.
Incorrect. Resources are identified by URIs, but they are opaque, n.b. The Opacity Axiom
"The only thing you can use an identifier for is to refer to an object. When you are not dereferencing, you should not look at the contents of the URI string to gain other information."
His dissertation is quite out of date with respect to current practical experience. Some of the ideas turned out to be great, others largely irrelevant. It was very useful at the time but don't forget it was realistically based on less than a handful of years of real industry experience. And most of that was in reaction to SOAP/SOA wars.
Before and during the time it was written there were existing HTTP based web services that were successful and they didn't follow all the principles outlined in the dissertation. Fast-forward 15 years and the vast majority of successful HTTP based web services still don't follow all the principles. Some turned out to be more useful than others.
I've always interpreted "hypertext" in this context to mean "a document containing hyperlinks" in a rather general sense - nothing about it being restricted to HTML.
My statement that HATEOAS is misunderstood is corroborated over and over by the replies to my comment. HATEOAS being misunderstood is so weird because it is an acronym of its own definition so I have no idea where all these other definitions are coming from. Let's examine it closer. HATEOAS stands for:
Hypermedia as the engine of application state
Hypermedia means HTML, period. Putting a list of URLs in a text or JSON response does not magically make it hypermedia.
Engine of application state means that all representations of the resources must be possible.
Combine those two and it means that all functionality must be accessible to and from the text/html content type. It must be able to handle all supported HTTP verbs and no fancy request headers that are not supported by HTML forms or hyperlinks.
Wrong. Any resource representation that can contain links to other resources with semantic identification of the relationship they have with the current resource is hypermedia. HTML is particularly popular, but far from the only hypermedia format.
> Putting a list of URLs in a text or JSON response does not magically make it hypermedia.
No, not magically, but if you have URLs with identification of their relationship to the current document in JSON, it is hypermedia. Hypermedia is older than HTML, and extends well beyond it.
> Engine of application state means that all representations of the resources must be possible.
No, it doesn't. HATEOAS does not mean that all resources must have hypermedia representations, it means that all available actions on the application state (whether read actions or write actions) must be identified to the client through hypermedia. (E.g., through links communicated in hypermedia resource representations wherein the semantics of the representation and the media-type of the resource in which it appears and which applies to the linked resource define the available actions.) A resource representation to which access is provided via a hypermedia link but which does not define additional linked resources need not be in a hypermedia format (that is, some resources may be purely defined by things like straight -- not hyper- -- text resources, or images, or whatever.)
> Combine those two and it means that all functionality must be accessible to and from the text/html content type.
It doesn't mean that at all. What HATEOAS means is laid out most clearly by Roy Fielding in a blog post responding to the way in which his definition of REST had been misunderstood on this point: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
REST isn't about HTML or the Web, though the Web and HTML are the inspiration for the definition of the REST architectural style. REST (and HATEOAS more specifically) requires neither HTML, nor any of the other specific technologies (HTTP, etc.) that define "the Web".
I think that is at least in part because for a few years, every time someone thought they had a RESTful system, some genius would come through and declare it non-RESTful on account of not following some rule or other. So "RESTful" came to mean a type of HTTP API that tends to look a certain way. And so of course URLs matter.
Saying something is "RESTful" is a surefire way to find out the ways in which it fails to match up with what some obscure document says.
I agree. Links must be in the response, that's the point. Also I dont' understand this hierarchical path mania that brings one to make complicate things where URIs are parsed / produced. I use the query string for this in general, is much easier, only if I have some special needs I don't.
you're right, this is really about making a good JSON api that maps CRUD operations to HTTP verbs. REST is often used as a shorthand for that, though its not technically 100% accurate.
that said, it was still a good article. I agree with the author on his best practices for JSON API design.
As an experienced developer who as had to implement dozens of API's over my career, therre are two things that I care about:
1. Documentation - If I have to spend the next month doing trial+error to get your API working, thats no good. The best APIs have a page that describes how get up and running quickly.
2. Good error messages - When something goes wrong I want to know what went wrong. The error message being in a consistent format isn't that important, as long as there is a description of what happened. "Oops, an error occurred, try again later" is not a good error message.
Most of the stuff in this article is superficial stuff that I don't think matters.
Better documentation is a non-trivial example application that, one, exercises all "normal" uses of the API, and, two, shows what the API developers consider to be best practices, all the way through.
Let me into your minds. Show me how you think I think. If you don't know how the people consuming your API think, your API is going to be pretty bogus. If your way of thinking is inimical to me, fine and dandy. Just give me a reasonable way to find out which isn't reading hundreds of pages of Javadoc or similar.
And if the example contains copy-and-pastable code, or reusable functions, so much the better. Make the licenses align, even if the code which implements the API is fully proprietary, and things will work out just fine.
Oh, and if you can't keep your example code working, that says something I need to know, too. Something nasty.
All too often we'll receive a "specification" document which just lists a bunch of URL fragments with the word GET or POST next to them. If we're lucky, we'll get a sample of the request and response body.
What we're left with are the two problems you described. We have no idea how to actually _do_ anything with the API. And when things don't appear to work, we're left guessing.
Most of the stuff in this article is superficial stuff that I don't think matters.
What the article seems to describe are practices that generate consistent, predictable RESTful APIs, which is exactly how you yield easy to use APIs. This saves both the creator and consumer's time, as debate and decisions over deviations are avoided.
I'm not quite sure why so many comments have gone so negative -- this is hardly a revolutionary piece, yet many of us are creating or dealing with APIs that could do well to take some advice.
> For a clean and conscice structure, you should always use nouns.
Well, yeah, it's what everyone says, but not so easy to do in practice. Especially in complex apps there's a lot of stuff that isn't actually creating, updating or deleting an object, it is semantically an action. Say, action "send email" (and not some random email, but related or even defined by some business object you are referring to). Or in bookkeeping apps you often need something like "recalculate", which you probably wouldn't like to think of as "updating" because it isn't "take these values and apply to that object", but rather "hey, it's time to make some decision: please run some process (probably, with side effects) and tell us what the result is". Or it might be an action like "moveToQueue<Name>". Or better yet, you explicitly are telling your system to make some interaction with third-party service which is essentially imperative (like GDS, or some external trading API or whatever that isn't an object for your system, but really more like a service for which your app is just a friendly gateway). It is a little bit hard to think of good example right away, because if there is action "purchaseTicket" and there's no object "ticket" in your system you might ask WHY there's no object ticket in your system, but in all specific enough systems there always are situations like this, and mostly for some good reason. And yeah, there's also decisions made for performance sake or simplicity of client-app (like some frontend-side "action queue" so that you can use reactive programming on front-end in more natural way).
So what do I do then? All URLs like "/user/123/order[s]"(PUT,GET,...), "/product/321/comment[s]"(PUT,GET,...) and, suddenly "/sale/copyToAnotherService"? Now that kind of inconsistency is something I really don't like.
…And while I was writing the last one I though about: how should look url for something like "getRecommendedProducts" which depends on both user and product?
Now writing nouns/action names is a bit messy and so not-RESTful, but you always are able to write exactly what you mean by that request.
You know that the verb mechanism is extensible, right?
If your API could benefit from a particular verb (SEARCH, MOVE, CHECKOUT), just use it. You don't need (more) permission from (another) RFC - RFC 2616 and 7231 [1] already gave you permission to add verbs.
Most libraries and tools support arbitrary verbs including `XMLHttpRequest` and `curl`. Yes, there are a few libraries and frameworks that don't easily support arbitrary verbs, but the ones that have added support for PATCH generally have opened up.
Look, there are two Internets. One for people and one for machines. Our RESTful APIs are intended for consumption by machines, not people. You don't have to wedge everything into GET and POST and abuse query parameters to convey what you really mean.
Yes, of course there are situations when you shouldn't use a custom verb.
- Routes that intended for use by people via clickable links (web browsers and email clients) obviously must use GET; I believe HTML forms are likewise limited to GET and POST by the `method` attribute (I've never submitted a PATCH form myself).
- You may have to interop with intermediate proxies that perform some form of DPI. For example, some proxies know that certain requests can be cached based on a URI. These proxies may not have support for custom verbs.
- Corporate firewalls may whitelist verbs [1].
In general, the idea is to strive to use verbs that have broad applicability in your API, but that doesn't mean every resource must implement every verb (e.g. read-only collections usually don't implement DELETE). But that's just an standard application of the uniform access principle.
He's not talking about a framework, he's talking about web application firewalls that only support the default verbs. It's quite common and has nothing to do with which framework you use.
Thanks for clearing that up, yes, as I've said, you should not use custom verbs if you have to interop with firewalls or proxy caches that perform DPI unless you've tested them.
Problem is that you may test the system now and it all works fine. But the day after you deploy, somebody named Murphy adds or updates a proxy somewhere in your topology that breaks things. Or your organization gets a new customer or partner with a differently configured network.
Your request may go through proxy servers that do not recognize these verbs. Or users of your API may be stuck with an outdated framework that simply doesn't allow them.
Keep things sane and stick to GET/POST/PUT/DELETE.
Well, as its name implies, REST is intended for resources, and is basically a "database on the Web". There is nothing wrong with using other types of Web services -- particularly those based on procedures and messages -- where appropriate. Religiously adhering to "pure REST" just because it's en vogue is as dangerous as ignoring it completely.
EDIT: If we consider adding methods to HTTP, it is easy to imagine a new method, named say CALL or RUN, which would allow arbitrary procedures to be run bound to the requested resource, allowing for a sort of "object-oriented" RPC over REST...
This reflects my experience as well - most (all?) literature and presentations on REST cover extremely simple use cases, and when you start building complex applications things start to get ... complicated, and you discover that there aren't really any REST best practices to fall back on.
If anyone has anything on implementing more complex REST APIs, I'd be interested in reading it.
the "type" of products you want is a sub-set of all products (recommended). For differentiators I think using params is good. You can then do something like:
GET /product/recommended?user_id={user_id}&rating=5
Usually actions can be thought of as a consequence of a state change. For example, instead of exposing an API to send an email related to some business object, your backend should know to send an email when some corresponding state requires it.. e.g., send notification email when an order is created.
But often it is the opposite. Say, it is backend app and users are sales agents. There appears to be need for them to have a button like "send email number 4 to client" which is standard pre-composed email with few variables defined by user. And later on somebody comes up with idea that when this email is sent there should happen few (up to 20) other things in the system, they all are linked to this "send email" action, but none of them is that major and well defined as creating an order or something like that, but more like "this object linked to this order should appear now in two more queues, also few requests to external systems are made to notify somebody that this user did that thing on that time" and so on. It's hard to decompose that because this email was really the most obvious and thus the key action, the most natural description of what happened. Business logic of backoffice apps tends to get really messy and there's pretty much no way to avoid it completely. Sent email actually is somewhat simple case as everybody knows what email is. The real problem with that kind of apps is that there's a lot of atomic (from users perspective) actions that actually are a hundred of seemingly unrelated other actions linked in one with some "name of that specific business procedure" which is traditional for your users but pretty much meaningless for a layman. There's just no way to define what happened in terms of "order created" and such: only some magic spell that defines this particular business procedure completely.
A POST to /email would be fine...you'd expect back a 201 Created.
To really do it, you'd want /emails instead of /email, and then you'd expect that you could access any given email by /emails/<id>, getting a 401 or 403 if you tried to access one that doesn't exist. Further, you could expect that you could then augment the email resource with a status flag, and then you could even sort for sent emails by /emails?status=sent_and_acknowleged or similar.
For your second case, a POST would be a little weird, unless it returned you a new stats_report. I'd suggest changing that to /stats_reports, and have it create a new stats_report object. To view latest, you'd GET /stats_reports/head or something.
It depends, but POST to /email is more like "create new email template". As for "recalculate" what I mean is completely different from report. It is that there's some specific state of some object, when all info is already in the system and user has no control over it, but some values (depending on other values that all are already there) are denormalized and specific command from competent user is required to make it happen. For example, thing we "recalculate" might be balance or comission, but it cannot happen automatically, as some human has to verify manually that some parts of that process have been done properly.
I'd say maybe half of these are actual good practices. In my experience, these are not:
I agree that keeping resource names consistent is good, but using plurals is not the only, and probably not the superior, solution.
Versioning is an idea that gets talked about a lot but can easily create more problems than it solves. Small improvements in APIs should be backward compatible and major ones should be new APIs. Whatever you do, putting "v1" in the middle of your URL is the wrong way to do it. (And so is putting "api" in your URL. It's better to keep your URLs clean of ambiguous and redundant information.)
Nesting resources is an anti-pattern that quickly creates a mess. I've learned this the hard way so please don't repeat my mistakes.
The 3rd principle of REST interface constraints is "descriptive" error messages. It is better to be clear and thorough than consistent. Consistency gets you nothing, especially if it is consistently bad.
I suppose one must first define the qualities between a good and a poor API. I would say that it is the same as any code: The design should be readable, maintainable and modular.
The plurals or not thing isn't a big deal. I really just object to the author picking one and claiming it's better with justification.
Putting "vi" in your URL decreases both readability and modularity. All things being equal, concise URLs are more readable. "v1" are extra characters without significant benefit. It also creates huge maintenance overhead. How many APIs do you think you can simultaneously maintain well? I am happy with one good one myself. Every extra new version you create (as opposed to gracefully improving the existing one) is more technical debt.
Let's take the nesting example: /artists/8/albums. What if you want to access an album by itself? You also need an /albums resource so you've just created two resources when you need only one. The /artists/8 response should include a list of albums that hyperlink to the /albums resources. If you absolutely have to have a clean list (without the artist header information, just filter it with a query string /albums/?artist=8. This accomplishes the same thing in a more predictable and consistent way without magic URL params. The major benefit of this type of design is it makes tracing execution from the interface to a code location much clearer by avoiding spaghetti URL routing.
Nested URLs are useful to signify partonomy. If you delete an artist, you would expect his or her albums to be deleted as well. Versus, if you delete an album, you wouldn't expect the artist to be deleted. And for completely unrelated things (which both would sit at the top level), again you wouldn't expect a cascading delete either.
When developing an API that sits on top of HTTP, it's easy to use a web browser to develop/debug. The reason I include the version string in the URLs of my APIs is to enable browsers to consume the API without any added extensions for crafting HTTP headers. The same point could be used to argue in favor of HTTP basic auth.
Some say that if HATEOAS is followed, there should never be a reason for a client to "know" an API. The assumption is that every link in a resource can be characterized precisely (via link relations, profiles, media types, etc.) enough that automated clients know what they can do and how they should do it. In practice, we're not really to that point yet, but also in practice there is often a human around somewhere to help a client navigate a changed API even if it can't figure that out automatically.
I think I'd agree that automated clients have a ways to go before that works. But sometimes you don't even want anything automated: sometimes the API just needs to change because e.g. the world around it has changed, requirements have changed. A version string in the API seems like a reasonable way to do that.
I think we can agree that there is some level of change at which we should not consider "the world" to have changed. I.e. if previously one could frobnobulate Widgets A, B, and C, and now Widget A has been replaced by Widgets Y and Z, that probably isn't a change to "the world". Only a client ill-conceived enough to maintain its own Widget Catalog would get screwed up by that change. (Don't laugh; this has been done lots of times.) Now suppose that before frobnobulating Widget B, we must first fizzgiggle it. There is a non-empty set of clients that survived the widget update but that will DIAF with the widget-specific-dependency-of-transitive-widget-verb update. So, don't write a Transitive-Widget-Verbs-and-Their-Widget-Specific-Dependencies Catalog into your client either. Et cetera...
Eventually we'll all get to a point at which the generalization must stop. REST advocates think that point is much farther away than is commonly believed. In the case of my dumb example, giving the client developer a version number wouldn't really have helped her avoid a rewrite, because Widget A is no longer available and Widget B must be fizzgiggled before it is frobnobulated. You could imagine that she has enough pull to insist on treating her Widgets exactly as she pleases, but that's not the hypothesis here. (After all in that case she could just have her own entry URI.) It's much better to use media types, link relations, etc. to let the client implicitly learn the information it needs to know every time it needs to know it.
> The plurals or not thing isn't a big deal. I really just object to the author picking one and claiming it's better with justification.
Agreed, I was annoyed by that as well when reading the article.
> Putting "vi" in your URL decreases both readability and modularity. All things being equal, concise URLs are more readable. "v1" are extra characters without significant benefit. It also creates huge maintenance overhead. How many APIs do you think you can simultaneously maintain well? I am happy with one good one myself. Every extra new version you create (as opposed to gracefully improving the existing one) is more technical debt.
It is true that versioning your API creates more maintenance, since you're supporting old versions of your code. However, it does make things more maintainable for users of your API. If you don't provide at least two versions, there is really no way to make a breaking change to your API without breaking your API clients. We have an API that is now up to version (IIRC) v1.13.4, where the first two components indicate breaking changes, and the last component is for additions. While the extra maintenance is noticeable (and we sometimes discuss how to decrease it) it's not huge, and very manageable. And it's helped us maintain our own internal tools, as well as upgrade different services that talk to each other using these APIs, but can't be upgraded simultaneously.
> Let's take the nesting example: /artists/8/albums. What if you want to access an album by itself? You also need an /albums resource so you've just created two resources when you need only one. The /artists/8 response should include a list of albums that hyperlink to the /albums resources. If you absolutely have to have a clean list (without the artist header information, just filter it with a query string /albums/?artist=8. This accomplishes the same thing in a more predictable and consistent way without magic URL params. The major benefit of this type of design is it makes tracing execution from the interface to a code location much clearer by avoiding spaghetti URL routing.
I can see this if you have lots of domain objects that are related more loosely. However, for objects that are more closely related (say, a blog post and its comments) I can also see the advantages of the nested structure, and you'll probably never request a certain comment without first knowing the post. On the other hand, perhaps you want the comments but relating to a user instead of a post...
How we've dealt with this is by mounting a sub-resource (comments, for example) on multiple parent resources (posts and users). This doesn't have to lead to complicated code if your abstractions are set up right. But I can definitely also see the advantages to a completely flat url structure. The more I think about it, the more I want to try this for a future API.
If you are building a web service for the general public that you want to last forever (e.g. an interface to Wikipedia or something), follow theoretical REST principles and you'll be well served.
If you have actual paying customers that you'll need to support over many years then version your API. Paying customers won't tolerate API breakage and you can't always force them to update on your schedule. Assuming you still want to evolve the API and also sign up new customers, you'll quickly find out you'll need versioning.
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
{
"type": "http://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "http://example.net/account/12345/msgs/abc",
"balance": 30,
"accounts": ["http://example.net/account/12345",
"http://example.net/account/67890"]
}
type, title, detail and instance are attributes defined by the spec. balance and accounts are extra attributes added for this error. I suppose that if I want to return validation errors to decorate an input form I'll have to add many custom attributes like those.
The use of 401 Unauthorized is an annoying one because of a little thing in the spec: The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.
AFAICT, This makes it makes it inapplicable to REST APIs that do not use basic or digest authentication, at least without violating the spec for the 401 response code.
The Github team does a pretty good job of incorporating modern best practices as well, so I often use their API as a reference: https://developer.github.com/v3/
One very bad practice that is quite common is using status codes in application specific ways and not including a standard error payload.
One way to think of it is that status codes are part of the transport, and your own application logic (validation, application error conditions, warnings, etc.) should never use HTTP error codes.
A dumb proxy server should be able to cache any response (including its status code) on a GET or HEAD without needing to know about any application logic.
I think this is actually quite debatable and I've seen a lot of people argue that nested resources are an anti-pattern. I only ever use nested resources myself when the child resource is existentially dependent on the parent.
Agreed. Nested routing is fine, as long as it doesn't become redundant.
Do:
/artist/8/albums
/albums/9
Don't:
/artist/8/albums/9
Using query filters versus nesting are virtually synonyms. I would say there is a minor semantic distinction in that the first one is a definite relationship, and the second one is a possible relationship. That is, "get the albums for artist 8" versus "get the albums searching for artist 8". The search could include other parameters as well, making it not as definite.
What about collaborations? The nested hierarchy implies a directed tree structure, but the relationships are really a graph. And I've personally found no more insidious of a problem in data design than trying to shoehorn a graph into a directed tree.
The relationships in URIs are abstractions anyway. The data is not actually stored at /artist/8/albums or /albums?artist=8. Both are abstractions of whatever underlying system is used to store the relationships.
Version numbers simply represent a way of managing change over time. They certainly aren't the _only_ way, nor are they the most ideal in all situations, but they certainly are the most simple, accessible, and explicit, and they don't require a lot of planning ahead.
By contrast, the reason why designing real REST services is hard is because you actually have to _design_ them. This requires long, hard thinking about the domain of the problem at hand, and as such, doesn't square well with our "agile" methodologies of week-in and week-out iterative hacking.
What status code should one return when the server receives incorrect credentials for an authentication API ?
401 - Unauthorized looks like the correct answer, but if you read the Wikipedia article 401 is specifically intended for HTTP Authentication using usernames and passwords set in the headers.
I recently ran into a situation where a third party library on receiving a 401 proceeded to then ask for HTTP credentials and try to resubmit the request when actually the server indicated that we had just submitted the wrong username/password for our login API (which doesn't even use HTTP Auth). We don't use WWW-Authenticate headers but the third party library seems to be following the standard.
403 Forbidden (or 404 Not Found if you don't want to leak information about the existence of a resource to unauthorized users) is probably the right one to use when the access is unauthorized in the general sense, but not the specific kind of HTTP Authentication issue that 401 addresses.
The spec for 403 states that "Authorization will not help and the request SHOULD NOT be repeated" so I don't think that is appropriate either. It's a good question though. I've always used 401 and haven't run into problems but I can see why it's probably not correct. I am sure that 400 (with a proper response body explaining the authentication requirements) would not be wrong, but I am uncertain if it is best.
> The spec for 403 states that "Authorization will not help and the request SHOULD NOT be repeated" so I don't think that is appropriate either.
I think that in context "authorization" in 403 can only be understood to mean the same thing as is authorization is implied to mean by the use of "Unauthorized" with the specific definition in 401 -- that is, reauthentication via the HTTP authentication methods. Under that view, 403 (and, to avoid leaking information, 404) fits.
400 does not seem to fit: it is not a generic code that fits the whole class of things in the 4xx series. Its definition is specifically "The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications." But the problem that is being identified is not malformed syntax.
So mapping this request onto a SQL database would be something like...
SELECT * FROM orders WHERE client_id = 1
And for
GET /clients/1/orders
it seems like in practice it would be the same relation since it would be wasteful to store two tables. Is this roughly correct?
REST manipulates resources but not every software service maps to resources, or (very) painfully so. This is easy to overlook when you have not had to implement a substantial service that is not a simple storage interface in this fashion. It might be tempting to write an article not trying to solve or even address this but it wrongly makes things appear more simple than they are.
REST often tries to map a graph of resources on a tree (the URL space). This problem is more related to the web and naming in general yet there are many possible solutions and no clear rule to apply, leaving plenty of room to blind alleys and time lost pondering which option is the least ugly. I'm not blaming REST here but this still is a major problem seldom addressed in articles.
REST, HATEOAS and friends lean a lot on the theory side seducing you into thinking machines will use your API without human intervention and make you lose time building for a non-existant use case (and your boss doesn't want to make automated access to his data that easy by the way). I suspect they will succeed at the exact same time the semantic web succeeds.
REST tries to convince you that everything will map cleanly to the HTTP standard, and it's pretty close, but most of times it falls short in a way or another.
In pratice most blog posts will tell you to use nouns, to rely on status codes, etc, yet every other popular API will derail in a way or another when faced with the cases that don't fit.
To sum it up, theory is cute, reality is less. Having a clean scheme where everything could theoretically fit is very seducing to any software engineer. In a way it feels like the holy grail, and it could be, but maybe it's not. And if it's not, trying to make everything fit in the wrong model could just be an awful waste of time. I still like the fact that it forces my brain to think in a non-intuitive way about some problems, but well. Our profession is plagued with micro-cults, holy grail models, silver bullets, magic blueprints we try to cast everything we can get our hands on in. MVC comes to mind. I think REST is becoming my second favorite.
Well, if you want to never write anything that scales yes, those are in fact the correct practices for writing bone-headed APIs for applications that would blow up with 20k concurrent users doing simple GETs.
If for some unknown reason you want to write APIs that don't go down faster than a 15 year old girl faints upon stumbling onto a boy from 1D in a local McDonalds you should:
a) use verbs
b) separate heavy end point from light end points
c) make URL easy to parse by load balancers and proxies
I found "Build APIs you won't hate" to be an excellent resource. Probably somewhat of a beginners text, but I found it to be extremely clear and concise, and very readable for the amount of information it covered. It was also very pragmatic about when to adhere to REST dogma and when to deviate from it.
API Versioning is for your clients, not your code. The only reason to change the version is if you're going to make breaking changes that old clients can't process. It's possible to rewrite an API in a different language and still have it be the same version URI.
What we did for this case was to "not break the API during a minor version".
For instance, only return more data and not less. Do not change the conditions/meaning of errors.
If you need to, then it's the right moment to switch to v2.
Exactly. All minor/revision API changes should be backwards compatible. You can add new optional parameters and new methods/objects, but you can't change the semantics of anything existing.
If you need a breaking change, that's time to increment the major number. Besides that, who'd want to support that many versions running live?
Post is missing advice on what to do to notify the client that the request is completely serviceable but should be retried later (i.e. Twitter's 420, or the actual RFC standard 429 [http://tools.ietf.org/html/rfc6585]).
I personally think that POST should hit an existing resource and create a new, related one. While PUT should hit an existing resource and modify it (if permissions allow). GET and DELETE are pretty obvious. Those are the conventions I use when I create REST interfaces.
If you're coming from a Rails background, then you know, most of this stuff is actually done (and also documented) for you by the framework itself, if you use its scaffolding feature. One more reason why I love Rails and the people behind it.
As the author of JSend, I no longer recommend this. Browsers' capabilities and my own understanding of HTTP's semantics have evolved beyond there being any further use for it.
One thing I've noticed that will become increasingly important in the future is for JavaScript APIs it would be really nice if you had a per user path, for example:
api.com/steakejjs/v1/
This way, user's of your API can implement Content-Security-Policy in a secure manner (where an attacker can't use your 3rd party API to exfiltrate data). It's not like there aren't other ways to exfiltrate data, but this will definitely help.