1. 12
  1. 7

    They don’t speak to implementation, but this sounds exactly like Stripe’s API Versioning.

    I don’t really understand the decision to go with a proprietary header in both cases. Perhaps this is controversial, but I believe API versioning is really just content negotiation.

    Encoding the version into the resource URI is the worst possible way of doing it. I see this all the time and it drives me nuts. If you need to change the resource, then just change the resource. Incrementing a numeric version in the URI just couples resource and representation when they are supposed to be independent.

    My preferred form of API Versioning is

    accept: application/vnd.company.api-name+json; version=2022-11-28
    

    Requesting a particular version of a resource’s representation is a negotiation between client and server. HTTP already has a system for this.

    1. 5

      They don’t speak to implementation, but this sounds exactly like Stripe’s API Versioning.

      Foursquare did something similar in their legacy API, as well.

      Encoding the version into the resource URI is the worst possible way of doing it. I see this all the time and it drives me nuts. If you need to change the resource, then just change the resource. Incrementing a numeric version in the URI just couples resource and representation when they are supposed to be independent.

      I generally view the URI-encoded API version (e.g. /v3/...) as a “major version” that covers the API’s high-level conventions, such as its authentication methods or pagination mechanics. The versioning covered by this post speaks more to the individual endpoints and their request/response shapes, and the GitHub folks want the flexibility to evolve those things separately (or rather, version them within the confines of the “major version”).

      … so why I don’t disagree with your comment (especially when taken to the extreme), I think there can be room for two “levels” of versioning in practice.

      1. 1

        It’s also very similar to Microsoft LinkedIn’s very recent introduction of API versioning, even to the obligatory marketing copy that makes it seem like breaking backwards compatibility benefits the customer, rather than their internal development teams.

        Since they have the same parent company, it’s not surprising that the practices and platforms start to converge over time.

        1. 1

          I usually prefer the /api/vX/foo method, using the path as version encoding. If you support multiple content types for the returned data, that can be communicated via the accept header (which also means its upwards compatible to new formats added later).

          1. 2

            The only reason you should ever need to change a resource identifier is if you want to change the identifier. This means that both could coexist, or you can use a standard redirect code to forward to the new one.

            If you’re changing it for any other reason, then that means you are coupling the identifier to something else for no real reason. Identity and representation should change independently.

            This is like renaming a method because the implementation changes, or using file extensions in the URL.

          2. 1

            +1 on Content Negotiation - I’ve written about it before but it is hard to get right - a blog post not yet written - so I get why folks don’t do it.

            What’s especially odd is the use of X- when https://www.rfc-editor.org/rfc/rfc6648 has been around for a decade

          3. 3

            API versioning is one of those things that should have a whole book dedicated to it. Not because it’s especially more difficult than other problems, but because it’s a general problem a lot of companies have with known approaches.

            Other engineering disciplines have the snap-fit handbook, we should have the API versioning handbook.