54

I had a look at Best practices for API versioning?, but am not quite convinced of the answer, so I am question the versioning part again with a more specific example. I am having two URIs (one with versioning as part of the URI and one without):

http://xxxx/v1/user/123    -> favored solution in discussed thread
http://xxxx/user/123             

I am having my doubts whether the first link expresses the idea of REST. I find http://xxxx/v1/user/123 confusing as it suggests that there will be a higher api-version someday like http://xxxx/v2/user/123. But this does not make sense in REST terms, the api version itself is HTTP 1.0 or 1.1, which is already sent inside the HTTP request. This REST resource centric view differs very from other api-interfaces like SOAP or Java-interfaces (where it is common to have api-versions in qualified names).

At REST the only thing where versioning makes sense is the representation of that resource (e.g. new fields are added or removed). This versioning belongs to the part of content-negotiation like:

http://xxx/user/123 + HTTP 'Accept' Header -> Content negotation through header
http://xxx/user/123?v=1                    -> for perma-links/hyperlinks

One could also argue that such version content-negotiation could be part of the URI inside the path, but I find it counter-intuitive, because you could end-up with different URIs for the same resource and have to maintain redirects at some point.

To sum-up: In REST URIs there is no api-versioning, only versioning of the resource's representation. Representation version-info belongs to content-negotiation (as queryParam or HTTP 'Accept').

What do you think? In which things would you disagree/agree?

Community
  • 1
  • 1
manuel aldana
  • 15,650
  • 9
  • 43
  • 50
  • 1
    just one little thing to add. the only showstopper to me and to use the ...v1/ style is, when you haven't got the load-balancing under control and can't define directions to the app-servers on HTTP header basis on the frontmachines (-> content-negotiation is part of the HTTP-header). Often the standard is to use the URL path. and in the web-frameworks I can think of it is difficult to define the request-mapping endpoints inside controller on HTTP-header basis instead of the path. – manuel aldana Jan 21 '10 at 05:16

8 Answers8

39

I completely agree; a URI expresses identity, identity doesn't change when a new version is introduced. There might be new URIs for additional concepts, of course, and existing URIs might redirect … but including a "v2" in the URI smells RPCish to me.

Note that this has got nothing to do with REST, really, as from a REST perspective it's all just characters.

Stefan Tilkov
  • 1,683
  • 12
  • 10
  • 2
    yes, it is just characters. but it is good to have nice/concistent URIs, because they are part of the interface the api users program against. – manuel aldana Jan 21 '10 at 05:18
  • 1
    here is another good example of how not to use versioning in your url, http://blog.steveklabnik.com/2011/07/03/nobody-understands-rest-or-http.html – kidbrax Jul 27 '11 at 03:50
  • 1
    This has been answered in a greater detail before here http://stackoverflow.com/q/389169/104261. – Taras Alenin May 04 '12 at 00:36
  • The uri identifies the resource, for content negotiation you should use http headers like "Accept". I would recomment to NEVER use version numbers in the uri of a resource. – Carlos Verdes Jan 22 '17 at 06:27
12

You could listen for an X-API-Version HTTP request header. If the header exists, then the server must use that version of the API. If the header does not exist, the server may use the latest version of the API.

> GET /user/123 HTTP/1.1
> Host: xxx
> X-API-Version: >=1.5.1, <2.0.0
> Accept: application/json
>

< HTTP/1.1 200 OK
< X-API-Version: 1.6.12
<
< { "user": { "id": 123, "name": "Bob Smith" } }
<
yfeldblum
  • 65,165
  • 12
  • 129
  • 169
10

For what it is worth, I agree with you Manuel. You can see my reasoning in this question How to version REST URIs

There are plenty of people that seem to disagree but I would not worry. What your url looks like really does not have a big impact on your client as long as you respect the hypertext constraint.

Community
  • 1
  • 1
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • 2
    +1 "What your url looks like really does not have a big impact on your client as long as you respect the hypertext constraint". This can't be stressed enough. – Daniel Canas Jul 05 '11 at 08:08
  • +1 for "What your url looks like really does not have a big impact on your client as long as you respect the hypertext constraint" – andy Mar 25 '14 at 02:58
3

I agree that you don't want to see versions in the URIs of the resources presented in your API. That makes them not "cool". Also agree that the it is representations that are most likely to change.

However it does then raise the question of what happens when you change the contents of a particular representation. For instance if your original JSON representation of a frobnitz is

{"x": "bam", "y": "hello"}

and you want to add a "z" field you may feel that the client should have some awareness that we're now on version 2 of some kind of data scheme.

I'm not sure about that. I think you've got a few options:

  • Make your clients flexible in the face a gently changing representations. In the above example we're still generating a JSON dictionary.
  • If you must, put a version in the representation itself (a version field in this example). By doing so you're effectively declaring a sub-representation within the JSON content-type. I reckon that's pretty limiting though.
  • Use your own MIME types and version them: application/x-my-special-json1.0, application/x-my-special-json1.1. This allows you to version your representations independently of each other. Again, with this one you are making a significant demand on your clients to know what's going on.

In general I think you want to optimize your API and your representations for clients that you haven't invented yourself; ones that other people will create upon discovering your resources. I believe this is useful even in the case when you are making something that is private because it builds in a useful design constraint that will help make your system more robust.

cdent
  • 348
  • 1
  • 7
1

I find http://xxxx/v1/user/123 confusing as it suggests that there will be a higher api-version someday like http://xxxx/v2/user/123

It doesn't suggest that - however you have that ability in the future.

But this does not make sense in REST terms, the api version itself is HTTP 1.0 or 1.1, which is already sent inside the HTTP request.

The version of YOUR API and the version of HTTP that you are using to make requests do not have to be equal.

One could also argue that such version content-negotiation could be part of the URI inside the path, but I find it counter-intuitive, because you could end-up with different URIs for the same resource and have to maintain redirects at some point.

Its okay to have the version as a URI parameter as you demonstrated.

http://xxx/user/123?v=1 -> for perma-links/hyperlinks

mr-sk
  • 13,174
  • 11
  • 66
  • 101
  • thanks for hints. but one question: speaking REST terms, what in your opinion makes a version of 'YOUR API'? because I just don't see a version inside a REST application besides the HTTP protocol and the resource representation. – manuel aldana Jan 08 '10 at 02:51
  • 4
    I typically start REST API's at v1. The api version is basically a contract/interface of what clients can agree on. If I change the interface/api, and perhaps I break that contract, I might increment to a v2 or v1.1 - However, none of my reasoning for versioning reflects the version of the HTTP client making the request. Does that help? – mr-sk Jan 08 '10 at 20:20
1

Another approach could be to say that "one representation has multiple APIs":

http://xxx/user/123/api/1.json

And if you wish, you could return the representation using the latest API when requesting like this:

http://xxx/user/123.json

Personally I like other solutions better but this is another approach that I haven't seen suggested here yet.

MPV
  • 1,644
  • 14
  • 15
0

For REST, what most answers forget is the data element. I assume multiple version API's still share that same data layer. This means that the data layer forces you to think in a backward compatible way. Big changes that have to be done are only possible if your API changes in a backward compatible way. In practice this means that additional properties are added silently to your entities while using deprecation by date in your API document to indicate when something will be removed. Ideally you use a register scheme with email address of your API key users, so you can notify them about deprecation within a certain scope (a la Facebook).Therefore, I don't think you need to specify a version anywhere.

Pepster
  • 1,996
  • 1
  • 24
  • 41
0

The API can be treated as a top level resource, /apis/v1/users/, then there is absolutely nothing wrong with having a version number in the URI. With Semver only Major versions go into the URI, since Minor, Patch etc. are backwards compatible.

neko
  • 51
  • 5