This document will describe how to version a REST API in a semantic manner, providing predictable releases free of breaking changes. Some of the workflow may not line up with your individual needs, but the overall concepts should be widely applicable.


The semantic version pieces that we will be discussing include the major, minor, and patch versions as well as prerelease tags. For these definitions, consider the version v1.2.3-alpha.0. All semantic versions in use must have a major, minor, and patch version and may have a prerelease tag.

Release workflow

Development and unstable API releases will happen in dev environments. After confirmation of a feature set as “stable enough” a stable release candidate will be promoted to a staging environment. After confirmation of the release candidate, a stable version will be released to production. Conceptually this might look like this:

If a beta or rc release is created the previously defined rules about feature and fix inclusion must be adhered to, or the beta or rc in question must be abandoned and officially unsupported.

For example: v1.2.3-alpha.5 introduces a new feature that is confirmed to be stable enough to move forward so v1.2.3-beta.0 is cut. Later, it is decided a breaking change to the new feature in v1.2.3-alpha.5 needs to be introduced in v1.2.3. At this point v1.2.3-beta.0 must be removed and v1.2.3-alpha.6 added.

Consumer request workflow

Consumers should interact with the API using npm style semver ranges. This gives maximum flexibility to API consumers, allowing them to “play it safe” and lock to a given version of the API, or provide a semver range which will allow subsequent versions to be received without modifying the consumer code.

Consumers must not lock to a prerelease tag, e.g. v1.2.3-rc.0. The requests will be rejected as additional changes could be introduced before the API becomes stable.

Consumers may request a prerelease tag with a range, e.g. ^v1.2.3-rc.0. This will resolve in the way described by npm, but has some important features that are worth mentioning here:

Range requests against prerelease tags will receive the next prerelease or the next stable version that satisfies the range.

For example: a request for ^v1.2.3-alpha.1 will receive the following versions when/if they are available: v1.2.3-alpha.2 v1.2.3-beta.0 v1.2.3-rc.0 v1.2.3 v1.2.4 v1.3.0

The same request would not receive v1.3.0-alpha.0, or any prereleases for that matter, on versions outside of the major, minor, and patch versions defined by the original prerelease range.

Consumers may lock to a stable version or request a range from a stable version, e.g. v1.2.3 and ^v1.2.3. While v1.2.3 is the latest stable version in the v1 family, these two requests will resolve the same way. As soon as a new minor or patch version is added the request for ^v1.2.3 would receive the new version.

Server considerations

Implementing servers should provide a meta style attribute to all responses that describes the version that the request resolved to. In JSON API with a request for /^v1.0.0/authors and a highest stable version of v1.2.3 this would look like this:

{ “data”: [], “meta” : { “version”: “v1.2.3” } }

Implementing servers should enforce strict semantic version matching and reject any request for an invalid version. This approach is preferable over attempting to route invalid or partial versions (e.g. v1.2) to the correct and valid version.

Fork me on GitHub