Don't version APIs, version resources. I.e., this is wrong:
Global version number has a few problems:
-
A backwards incompatible change to any one resource invalidates all clients, even those who don't use this particular resource. This is unnecessary maintenance burden on client developers.
-
It constrains development on the server as you have to synchronize releases of independent backwards incompatible features to fit them into one version change.
-
You have to maintain several versions of your whole API code base simultaneously.
May be there's more, but the first problem is quite enough, if you ask me. And I can't think of a single disadvantage of versioning resources independently.
Versioning resources
Technically, you can do this:
Content-type: application/myformat+json; version=2.0
… or this:
{
"version": "2.0",
"payload": { ... }
}
… or even this:
It doesn't matter. Since we don't live in the pure-REST utopia predominantly using well-defined MIME types, your representation formats are probably custom anyway, so your versioning is going to be custom as well. As long as it's documented, it's fine.
Implicit versioning
Instead of giving your format an explicit version number, you can change data in a way that the old clients could not use it. For example, if you've subtly changed the format of a date field, change the name of the field too:
Version 1:
{"time": "2012-01-01T00:00"}
Version 2:
{"utctime": "2012-01-01T08:00"}
You could even support both fields for some time with a deprecation warning in the docs.
Even though I like this approach more than numbering, I'm not going to defend it to the death. I think it boils down to the kind of developers you want to cater to (including your own). Some people believe that everything should be declared in advance, preferably with a formal schema. But schemas are harder to maintain. Other people rely on catching exceptions at run-time and introspection. But run-time sometimes means "production" and bad things might happen more often than you'd like.
Comments: 2
I'd prefer (X-)ApiVersion header instead.
As long as it's per-resource, not global through the whole API — it's okay.
The exact version declaration is not the issue. The issue is: does your API allows more granular changes than "all at once".