5

I'm designing an API for our web application, that will be consumed by mobile developers that will create our mobile app.

I chose to document it using Swagger / OpenAPI 3.0.0.

I'm surprised that when I create a new OpenAPI document on Swagger, I get a default version field set to 1.0.0.

The specification also uses 1.0.1 as an example.

While I understand very well, and implement myself, semantic versioning for open-source libraries, I fail to understand how this relates to APIs. An API is, by definition, always up-to-date, and I my gut feeling agrees with this answer on StackOverflow. Full quote:

APIs should only use major versions externally. Following best practice semantic versioning, major versions change when you introduce backwards-incompatible changes to a project.

If you're just adding features, or modifying existing ones in backwards-compatible ways, then you just do it and your existing consumers are not affected (though, they can then make use of the new changes if they want). Your API can change versions from 1.0.0 to 1.1.0 internally, but the version as exposed to your consumers is still just "v1".

If you're just patching bugs, the same applies. Change from 1.0.1 to 1.0.2 internally, but the API should stay at "v1".

Now, if you rename/remove resources, or do some other drastic changes that will break existing clients, your internal version might go from 1.2.0 to 2.0.0, because breaking backwards compatibility requires a major version change. Because of this, the new major version has to be exposed to your API's consumers as "v2".

So, in keeping with this, both your namespaces and your URLs should reflect only the major version (e.g. "v1"), and you should make sure that you never break backwards-compatibility within a major version.

Should I version my API using only a major version, or major.minor.patch as I would with an open-source library?

What's the point in introducing bug fixes and new features as new versions, when you can apply them to the existing version directly?

My main worry is that if I follow this convention, if I fix a bug on v1.0.0, and release the fix as v1.0.1, I would have to let developers know so that they could update to the next patch version, and then wait for end users to update their app.

Whereas if I apply the fix to a v1 API directly, the fix will instantly propagate.

What did I miss?

9
  • Whoever downvoted, care to explain?
    – BenMorel
    Mar 25, 2019 at 16:03
  • 1
    If you minor-version an API under semantic versioning rules, doesn't the consumer of your API also know that a minor version change doesn't break the interface? Mar 25, 2019 at 16:08
  • 1
    In other words, why would clients be compelled to update to the next minor version of an API if the API itself remains unchanged? Mar 25, 2019 at 16:09
  • 1
    To put it another way, you assert in your question that it is possible to fix a bug or add a feature without breaking the API. A minor version change would alert the developers that such a change occurred without compelling them to upgrade. Mar 25, 2019 at 16:13
  • 2
    The swagger docs indicate that the version is an arbitrary string, which they recommend follows semver but could be anything. I personally prefer to think of it as the version of the documentation, which is probably equal to or less than the version of the service that is run in production. Documentation can have errors, too! So, if you were adding documentation for buggy behavior, or errata for previous claims made by earlier versions of the docs, you would have reason to update a non-major version number. Mar 25, 2019 at 22:24

1 Answer 1

7

Should I version my API using only a major version, or major.minor.patch as I would with an open-source library?

You should use major.minor.patch (or major.minor.patch.build)

Your quoted article is correct in that because the internal implementation is not exposed to the client, they wont care about anything other than the major version. Only a change which breaks the interface will affect them and by definition this would be a major change*

Your routing of requests should reflect this, you don't want to force clients to request a specific patch version.

However! for your own sanity you will care very much about the exact major.minor.patch.build version which is deployed to your many servers. You will want this version to be logged and reflected in the assembly versions which are deployed. So that you can do basic debugging and versioned deployments etc.

*You can imagine edge cases where the internal processing affects the result without breaking the interface. You can also imagine some clients not wanting the 'fixed' version for whatever reason.

What I normally do is allow the full version to be requested but route according to my own wishes. for example I might route:

v0.*.*.* -> unsupported error page  // all v0s go to an error page that tells the client to upgrade
v1.*.*.* -> v1.2.0.0   // all v1s go to the latest v1
v1.1.32.1 -> v1.1.32.1  //need for client who is audited on changes
*.*.*.* -> v2.2.0.0 // all not matched by other rules or unspecified go to my latest version
2
  • Thanks for your answer, it makes sense now. As I've mentioned in the comments above, I mixed the concepts of documentation version with API version, probably misled by Swagger's Auto Mocking API which uses the full version in the URL. I guess my API is simple enough to not justify the minor version separation you follow, and a /v1/ endpoint will do. Your approach is very interesting though, thanks for sharing it!
    – BenMorel
    Mar 26, 2019 at 9:33
  • A semantic api version is also useful if you allow other people to self host the application to deal with the case where the client software is using api 1.1 but the server is using 1.0 which will not work if the client is using anything added in 1.1
    – Qwertie
    Apr 23, 2019 at 6:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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