How to version a mobile API that's under development?

I am working on a team that is developing the server side API for a mobile application. The API is evolving as we go and we have released several iterations of the API and mobile app. We have clients using the app in production and we can’t always guarantee the clients will be on the latest version of the app. This means we need to maintain previous api endpoints so the older versions of the app don’t break.

How does thoughtbot handle versioning of mobile client apis? We try to avoid creating new versions unless we are requiring new parameters or have to change the response format. Here are a few ways we’ve thought maintaining versions.

/endpoint-version_number - The way the app is currently written is each endpoint has it’s own version number appended to it. Usually the mobile just uses the latest version of an endpoint, but it can get messy where you have /users3 and /merchants5. The one benefit I see to this is if you make a breaking change on one endpoint, you don’t have to bump the version number of the entire api

/v2/endpoint - I like having the version number in the url because you can version the api as a set and say that we’re using version X of the api. However, if you have a breaking change to one endpoint, then you have to bump the entire version of the api. If you’re doing iterations on your server side and mobile app, I could see quickly getting up to v7 or v10 which means you have a lot of endpoints to maintain. Also, if you introduce some new functionality or a refactoring and want to backport it to all of the previous versions of the api. I wonder if this scheme would introduce some headaches too.

Any insight or best practices of how to handle internal apis for mobile applications would be greatly appreciated. Please let me know if there are other versioning practices I haven’t thought of.

Thanks,
-Aaron

@aaronrenner, I think you should favor the latter approach. Having the version as a separate namespace enables you to do things like have all the endpoints from a given version inherit behaviors from a base controller, etc. I also think it looks better, but that’s an aesthetic judgement.

With the former approach, you’re going to get a lot of clutter.

I built an app last year that had to support multiple mobile applications and we had to think very carefully about API changes as we went. You might want to have a list of API upgrades you want to make so that you can queue them up for release at the same time. If you have the ability to force upgrades to the mobile app, you can at least put yourself in a position where only the latest two versions are supported and any older versions send a message that the phone knows is a signal that it’s time to upgrade.

I absolutely second @geoffharcourt’s recommendation. I rarely if ever see the first system out in the wild. If you look at APIs such as Stripe or other “bigger” name APIs, you’ll find your second approach to be more common, if not the standard.

I’m going to third it, and add that there are libraries that make versioning and other sorts of API development burdens easier.

Grape: GitHub - ruby-grape/grape: An opinionated framework for creating REST-like APIs in Ruby.
Has versioning, parameter validation and coercion amongst many others built right in.

Rocket pants: GitHub - Sutto/rocket_pants: API building tools on top of ActionController. Also, an awesome name.
Built on ActionPack(key differentiator from Grape), Caching support, etc

Hope this helps!

Interesting timing. I just bumped the verson on the API side of our app this morning after we decided we needed some breaking changes to occur during our present sprint. Starting out with a /v1 namespace was just fine and we found that things normally didn’t end up in situations where things would break.

I’ve looked into some other solutions where the version is specified in the header - see: http://pivotallabs.com/api-versioning/ - but felt the branching and overhead might outweigh the investment.

I’d imagine a lot of the decision might be predicated on the size of your api, too? Ours is relatively small so there’s not much trouble in splitting apart our controllers into (a) new version(s).

Another great tool for API versioning: Version Cake by bwillis

I have historically used the /v2/:endpoint approach but on the next project I have a chance to design an API for, I plan on following Heroku’s HTTP API Toolchain to the letter, if possible, and contribute back to their HTTP API Design Guide if anything feels strange.

Their versioning recommendation is currently:

Version with Accepts header

Version the API from the start. Use the Accepts header to communicate
the version, along with a custom content type, e.g.:

Accept: application/vnd.heroku+json; version=3

Prefer not to have a default version, instead requiring clients to
explicitly peg their usage to a specific version.

The second half of this topic that I find interesting is the use of JSON Hyper Schema to define the API’s schema.

Do the following on the Heroku Platform API’s JSON Schema to see how they structure their API:

curl https://api.heroku.com/schema  -H "Accept: application/vnd.heroku+json; version=3"

Look for stability keys such as in the stacks endpoint:

"stack": {
   "description": "Stacks are the different application execution environments available in the Heroku platform.",
   "$schema": "http://json-schema.org/draft-04/hyper-schema",
   "stability": "production",
   "strictProperties": true,
   "title": "Heroku Platform API - Stack",
   "type": [
     "object"
   ]
   ...

Back in the HTTP API Design guide, the stability guideline is detailed:

Describe stability

Describe the stability of your API or its various endpoints according to
its maturity and stability, e.g. with prototype/development/production
flags.

See the Heroku API compatibility policy
for a possible stability and change management approach.

Once your API is declared production-ready and stable, do not make
backwards incompatible changes within that API version. If you need to
make backwards-incompatible changes, create a new API with an
incremented version number.

2 Likes

I like this heuristic from Steve Klabnik:

if you’re using hypermedia, no versions at all. If not, versions in the URL.

https://twitter.com/steveklabnik/status/480405061667803136

Thank you, everyone, for your recommendations. This definitely gives me a lot of great material to look at.