
Some REST best practices - brgs
https://bourgeois.me/rest/
======
sjtgraham
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.

~~~
protonfish
I must disagree. REST is defined by four interface constraints:
[http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch...](http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5)
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.

~~~
protonfish
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.

~~~
paulddraper
"Hypermedia means HTML, period."

Um, no. XHTML and SVG are hypermedia.

JSON isn't hypermedia, but you can define hypermedia formats that use JSON
(just as SVG uses XML).

~~~
protonfish
True, but with so much confusion over a blatantly clear definition I figured I
needed to keep it simple.

------
freework
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.

~~~
cbd1984
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.

------
krick
> 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.

~~~
politician
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.

[1]
[http://tools.ietf.org/html/rfc7231#section-4.1](http://tools.ietf.org/html/rfc7231#section-4.1)

~~~
krick
Is it really safe and reliable? Are there any situations when I should NOT add
my custom verb whenever I please?

~~~
serve_yay
That sounds like a recipe for heartburn later, when you run into some WAF or
whatever that only allows PUT/GET/DELETE/POST.

~~~
politician
The cockroach that you see is usually not the only one around.

A framework that doesn't support extensible verbs in 2014 is bound to have
more problems than just a failure to implement one RFC correctly.

~~~
orand
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.

~~~
politician
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.

~~~
mistermumble
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.

~~~
politician
That's an argument for never doing anything.

~~~
toomuchtodo
Its an argument for being conservative in your design philosophy.

------
protonfish
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.

~~~
hesselink
The article gives some motivation for its best practices, you do not. Would
you care to provide some?

> using plurals is not the only, and probably not the superior, solution.

Why?

> Whatever you do, putting "v1" in the middle of your URL is the wrong way to
> do it.

Why?

> Nesting resources is an anti-pattern that quickly creates a mess.

Why?

Edit: not sure why the downvotes. I'm genuinely interested, but the parent
doesn't contain much useful content.

~~~
protonfish
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.

~~~
shangxiao
I've actually seen people use versioning in their URLs for _deprecated APIs
only_ , with the current version not using a version number.

~~~
Pxtl
That seems pointless, since you're still shifting the ground under your users'
feet.

~~~
eli
What's the alternative?

~~~
jessaustin
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.

~~~
eli
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.

~~~
jessaustin
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.

------
pmontra
There is a draft RFC for returning errors in APIs based on JSON.

[http://datatracker.ietf.org/doc/draft-ietf-appsawg-http-
prob...](http://datatracker.ietf.org/doc/draft-ietf-appsawg-http-
problem/?include_text=1)

Their example:

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.

------
shdon
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.

Is there something that I've missed?

~~~
justinsb
Why not pass a dummy value to satisfy the spec?

~~~
dragonwriter
Because a dummy value satisfies the syntax but not semantics of the spec.

------
jobu
Here are a couple more lists of Best Practices for REST APIs.

[http://blog.mwaysolutions.com/2014/06/05/10-best-
practices-f...](http://blog.mwaysolutions.com/2014/06/05/10-best-practices-
for-better-restful-api/)

[http://www.vinaysahni.com/best-practices-for-a-pragmatic-
res...](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api)

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/](https://developer.github.com/v3/)

------
grandalf
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.

------
Johnie
One minor nuance I use is adding a trailing slash to indicate resource vs
custom verb.

GET /products/ : will return the list of all products

POST /products/ : will add a product to the collection

GET /products/4/ : will retreive product #4

PATCH/PUT /products/4/ : will update product #4

POST /products/4/someCustomVerb : custom verb

------
shill
There can never be enough articles and books supporting API best practices.

Here are two of my favorite REST resources (pun intended).

Richardson Maturity Model: steps toward the glory of REST

[http://martinfowler.com/articles/richardsonMaturityModel.htm...](http://martinfowler.com/articles/richardsonMaturityModel.html)

RESTful Web Services Cookbook: Solutions for Improving Scalability and
Simplicity

[http://www.amazon.com/gp/product/0596801688](http://www.amazon.com/gp/product/0596801688)

And I am looking forward to widespread adoption of the REST problem standard
posted here a few weeks ago.

[http://www.ietf.org/id/draft-ietf-appsawg-http-
problem-00.tx...](http://www.ietf.org/id/draft-ietf-appsawg-http-
problem-00.txt)

------
shangxiao
> _use nested routing for a cleaner design_

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.

~~~
madeofpalk
I think what he's describing, or at least what I do, is when you get all
albums belonging to an artist.

    
    
        GET /artist/8/albums
            { albums: [89, 93] }
        
        GET /albums/89
            {
                album: {
                    id: 89,
                    title: 'Blah'
                }
            }

~~~
hawleyal
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.

/artist/8/albums

/albums?artist=8

~~~
shangxiao
Chances are you're (well at least with me) going to do filtering anyway so
/artist/8/albums becomes redundant ;)

~~~
hawleyal
I see what you're saying, but it's not redundant, it's just a synonym. By
redundant I meant that there are keys that are not necessary.

/artist/{artist}/albums

/albums?artist={artist}

AlbumsController#index(artist)

------
nateabele
Stopped reading at "Version your API". Clearly this guy has no idea what he's
talking about [0].

[0]
[https://twitter.com/fielding/status/376835835670167552](https://twitter.com/fielding/status/376835835670167552)

~~~
4326KFxu
This is is a genuine question: if you don't version your API _somehow_ , then
how do your clients handle breaking changes?

~~~
nateabele
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.

Much as I typically loathe self-promotion, I did give a talk on this recently
that enumerates some design strategies:
[https://speakerdeck.com/nateabele/designing-hypermedia-
apis](https://speakerdeck.com/nateabele/designing-hypermedia-apis) \-- check
out slides 8-20.

------
thewarrior
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.

So should we be returning 400 instead ?

~~~
dragonwriter
> So should we be returning 400 instead ?

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.

~~~
protonfish
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.

~~~
dragonwriter
> 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.

~~~
thewarrior
Yup this is definitely confusing. That's why I asked it here. Hoping that
someone knowledgeable might see this .

------
josai

      > Here are some bad examples :
      > /retreiveClientByOrder?orderId=1
    

I note the author didn't go on to demonstrate a better way of doing this. What
would he recommend, /clients?by_order_id=1 ?

~~~
misja
Using sub-resources, you get something like this: GET /orders/1/clients

~~~
jagger27
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?

~~~
mattmanser
No. Think of it as "for order 1 list all clients", so it would be:

    
    
        SELECT * FROM clients WHERE client_id IN (SELECT client_id FROM orders WHERE order_id = @order_id)
    

The GET /clients/1/orders is what would result in your query (for client 1
list all orders).

------
wnevets
is it just me or no one can agree on what the best practices for a REST API
are?

~~~
thibauts
No wonder.

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.

------
sre_ops
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

------
ericcumbee
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.

[https://leanpub.com/build-apis-you-wont-hate](https://leanpub.com/build-apis-
you-wont-hate)

------
euph0ria
What is the best practice regarding filtering? Suppose you'd like to filter
the artist's albums to only show albums from a range of years (2005-2014).

~~~
shangxiao
Query parameters on the collection. Dealing with ranges is always a tricky one
though and I've seen different REST libraries use different querying.

------
josai
> One way is to do is to pass the API version in the URL (/api/v1/...)

If you do it like this, how do you then deal with 1.0.1? Especially in a
framework like rails, where paths basically map to a folder structure?

I agree it's much nicer to be able to test manually when you have the version
in the path but it significantly reduces flexibility later on.

~~~
m_t
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.

~~~
Pxtl
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?

------
fixermark
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]](http://tools.ietf.org/html/rfc6585\])).

This is key for modern services.

~~~
EdwardDiego
> Twitter's 420

...really Twitter?

~~~
fixermark
"Enhance your calm." ;) [https://dev.twitter.com/overview/api/response-
codes](https://dev.twitter.com/overview/api/response-codes)

Was superseded by the RFC standard 429 in API version 1.1.

------
zkhalique
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.

------
kylequest
This is a much (much :-)) better post about "REST"/"HTTP" API best practices:

[http://www.vinaysahni.com/best-practices-for-a-pragmatic-
res...](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api)

------
neya
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.

------
thecodemonkey
This is a great article, I wrote a similar blog post recently [1]

[1] [http://scotch.io/bar-talk/designing-a-restful-web-
api](http://scotch.io/bar-talk/designing-a-restful-web-api)

------
shocks
We use jsend[1] for our responses.

1: [http://labs.omniti.com/labs/jsend](http://labs.omniti.com/labs/jsend)

~~~
nateabele
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.

~~~
shocks
Can you elaborate on this? Can you give some examples?

------
steakejjs
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.

------
Paul_Morgan
I'd accept both singular and plural. At least redirect one to the other.

------
rafekett
there are lots of problems (particularly with versioning/backwards
compatibility) that using better protocols (i.e., protobufs) can solve.

