Don't version APIs, version resources. I.e., this is wrong:

Global version number has a few problems:

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

  1. Alexander Batishchev

    I'd prefer (X-)ApiVersion header instead.

  2. Ivan Sagalaev

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

Add comment