15

It's very common to specify the version of REST APIs in the URL, specifically at the beginning of path, i.e. something like:

POST /api/v1/accounts
GET /api/v1/accounts/details

However, I haven't seen any design where the version is associated with each API. In other words, we maintain the version of each API separately. i.e.:

POST /api/accounts/v2
GET /api/accounts/details/v3

Using this approach we increment the API version of the specific API when breaking change is needed, no need to increment the version of the whole APIs.

What are the drawbacks of using this style instead of the common style?

13

What you call single REST APIs might be called REST API's particular set of resources or resources. You also could look at it as a REST API's functionality. Such as any kind of software, the whole package is versioned/updated, not single functionalities or resources.

Your question would make sense in the context where the REST API package's resources are modular and so potentially developed and versioned separately.

Then, as far as I see, the main cons of your proposed resource locator naming convention:

  • For the API user, it would result in much more complex resource locators, less predictable, less memorable and less stable. Harder to remember which particular version is on each single resource and set of resources...
  • For the module developer(s), it's now more work to have to deal with this versioning in their own resource locator.
  • Changes in resource locators become much more frequent, as much as there are multiple modules updating... On the long run, the cons above might become unpleasant enough...

When building an API, one of your main objectives is making it easy to use...

You might find a better way to introduce a breaking change or even versioning the REST API with maybe a HTTP header?
To know a little more about HTTP headers approach, see other answers below and: https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/

11

Here's an even better approach: use content negotiation to version your API with the Content-Type and Accept headers:

POST /api/accounts
Accept: application/vnd.my-api.account.v1+json

201 Created
Location: /api/accounts/285728
Content-Type: application/vnd.my-api.account.v1+json
{ ... account data here ... }

To get a different version, merely ask for it with a different content type in Accept. This way, the particular versions your server supports are completely independent of your URL structure. The same server could support multiple versions by just picking which to respond with based on the Accept header. Alternatively, if you want to stick with different deployments for different versions, you could put a proxy in front of different versions of your service that picked which one to forward requests to based on the Accept header.

This also lets you support new formats with different semantics (not just different versions) on the same endpoints. For instance, POSTing a list of accounts to /api/accounts could mean batch creation, and you wouldn't need to build a separate API endpoint for it.

  • omg the accept header has to be the worst choice of version signaling. use a version header if you can, url path if you must (ie AWS routing) – Ewan Aug 29 '17 at 22:35
  • @Ewan Why? A custom version header implies that different versions are the same resource without informing intermediaries that the content might be different. A caching proxy wouldn't know to use your header to not serve v1 cached responses to v2 requests. – Jack Aug 29 '17 at 22:49
  • use the vary response header, if you are not already using no-cache for api requests!. content type already has a meaning, suborning it for your private use just makes life hard for consumers – Ewan Aug 29 '17 at 23:15
  • @Ewan That's what the vnd part and the + syntax of the type are for: to indicate this is a vendor-specific subtype of the application/json type. This is exactly what content types are designed for. Your resource is available in multiple formats. You're asking the client to pick which format they want. Additionally, there is no reason API requests can't use standard HTTP caching semantics. – Jack Aug 30 '17 at 3:17
  • if you fix a bug in myapi v2 you are not returning a new mime type. – Ewan Aug 30 '17 at 7:53
5

The key thing is that if you version each endpoint separately then you must be able to deploy each endpoint separately.

APIs usually have one version because all the end points are in the same codebase and thus have shared dependencies and are deployed together.

If you are not updating the version when you make a change because "Oh I'm pretty sure my change doesn't affect that" well you will get in trouble when you make a mistake.

Additionally, you will want to have both v1 and v2 of your API deployed at the same time. This is normally done by deploying each version to a separate server and routing the traffic accordingly.

If you have no single API version this becomes much more complex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.