RESTful API Versioning Best Practices: Waarom v1 #1 is

RESTful API Versioning Best Practices: Waarom v1 #1 is

RESTful API Versioning Best Practices: Waarom v1 #1 is

May 24, 2017

Gepubliceerd door

Gepubliceerd door

Chris McFadden

Chris McFadden

-

Categorie:

Categorie:

E-mail

E-mail

Ready to see Bird
in action?

Ready to see Bird
in action?

RESTful API Versioning Best Practices: Why v1 is #1

Breaking Changes Bad!  API Versioning Good!

Zoals iedereen die een API heeft gebouwd of regelmatig gebruikt zich vroeg of laat realiseert, zijn breaking changes erg slecht en kunnen ze een zeer ernstige smet vormen op een verder nuttige API. Een breaking change is een wijziging in het gedrag van een API die de integratie van een gebruiker kan verbreken en kan leiden tot veel frustratie en verlies van vertrouwen tussen de API-aanbieder en de gebruiker. Breaking changes vereisen dat gebruikers vooraf op de hoogte worden gebracht (met bijbehorende mea culpa's) in plaats van een verandering die zomaar opduikt, zoals een heerlijke nieuwe functie. De manier om die frustratie te vermijden is om een API in versie te brengen met de verzekering van de API-eigenaar dat er geen verrassende veranderingen zullen worden aangebracht binnen één enkele versie.


Dus hoe moeilijk kan het zijn om een API te versioneren? De waarheid is dat dat niet zo is, maar wat wel moeilijk is, is om een beetje gezond verstand te bewaren door niet nodeloos te vervallen in een duizelingwekkend aantal versies en subversies die worden toegepast op tientallen API-eindpunten met onduidelijke compatibiliteit.


We introduced v1 of the API three years ago and did not realize that it would be going strong to this day. So how have we continued to provide the best email delivery API for over two years but still maintain the same API version? While there are many verschillende meningen on how to version REST API's, I hope that the story of our humble yet powerful v1 might guide you on your way to API versioning enlightenment.


REST is het beste

De SparkPost API stamt uit de tijd dat we nog Message Systems waren, voor onze avonturen in de cloud. In die tijd waren we druk bezig met de laatste voorbereidingen voor de beta lancering van Momentum 4. Dit was een grote upgrade voor versie 3.x, onze marktleidende on-premise MTA. Momentum 4 bevatte een volledig nieuwe gebruikersinterface, realtime analyses en bovenal een nieuwe web-API voor het injecteren en genereren van berichten, het beheren van sjablonen en het verkrijgen van e-mailstatistieken. Onze visie was een API first-architectuur, waarbij zelfs de gebruikersinterface zou communiceren met API-eindpunten.


One of the earliest and best decisions we made was to adopt a RESTful style. Since the late 2000s representational state transfer (REST) based web APIs are the de-facto standard of cloud APIs. Using HTTP and JSON makes it easy for developers, regardless of which programming language they use – PHP, Ruby, and Java – to integrate with our API without knowing or caring about our underlying technology.


Choosing to use the RESTful architecture was easy. Choosing a versioning convention was not so easy. Initially we punted on the question of versioning by not versioning the beta at all. However, within a couple months the beta was in the hands of a few customers and we began building out our cloud service.  Time to version. We evaluated two versioning conventions. De first was to put the versioning directly in the URI and the second was to use an Accept header. De first option is more explicit and less complicated, which is easier for developers.  Since we love developers, it was the logical choice.


API-bestuur

With a versioning convention selected we had more questions. When would we bump the version? What is a breaking change?  Would we reversion the whole API or just certain endpoints? At SparkPost, we have multiple teams working on different parts of our API. Within those teams, people work on different endpoints at different times. Therefore, it’s very important that our API is consistent in the use of conventions. This was bigger than versioning.


We established a governance group including engineers representing each team, a member of the Product Management team, and our CTO. This group is responsible for establishing, documenting, and enforcing our API conventions across all teams. An API governance Slack channel also comes in handy for lively debates on the topic.


De beheergroep heeft een aantal manieren vastgesteld waarop wijzigingen in de API kunnen worden aangebracht die gunstig zijn voor de gebruiker en geen breuk veroorzaken. Deze omvatten:


  • Een nieuwe bron of API eindpunt

  • Een nieuwe optionele parameter

  • Een wijziging van een niet-openbaar API-eindpunt

  • Een nieuwe optionele sleutel in de JSON POST body

  • Een nieuwe sleutel teruggestuurd in de JSON respons body


Omgekeerd omvatte een brekende wijziging alles wat de integratie van een gebruiker zou kunnen verbreken, zoals:


  • Een nieuwe vereiste parameter

  • Een nieuwe vereiste sleutel in POST-organen

  • Verwijdering van een bestaand eindpunt

  • Verwijdering van een bestaand eindpunt request method

  • Een wezenlijk ander intern gedrag van een API-aanroep - zoals een wijziging van het standaardgedrag.


De Grote 1.0

Terwijl we deze conventies documenteerden en bespraken, kwamen we ook tot de conclusie dat het in ieders belang was (ook dat van ons!) om geen afbrekende veranderingen in de API aan te brengen, omdat het beheren van meerdere versies nogal wat overhead met zich meebrengt. We besloten dat er een paar dingen waren die we met onze API moesten oplossen voordat we ons committeerden aan "v1".


Sending a simple email required way too much effort.  To “keep the simple things simple” we updated the POST body to ensure that both simple and complex use cases are accommodated.  The new format was more future-proof as well.  Secondly we addressed a problem with the Metrics endpoint. This endpoint used a “group_by” parameter that would change the format of the GET response body such that the first key would be the value of the group by parameter. That did not seem very RESTful so we broke each group by into a separate endpoint. Finally we audited each endpoint and made minor changes here and there to ensure they conformed with the standards.


Nauwkeurige documentatie

It is important to have accurate and usable API documentation to avoid breaking changes, of the deliberate or unintentional kind. We decided to use a simple API documentation approach leveraging a Markdown language called API Blauwdruk and onze documenten in Github beheren. Our community contributes and improves upon these open source docs.  We also maintain a nonpublic set of docs in Github for internal APIs and endpoints.


Initially, we published our docs to Bijenstal, a great tool for prototyping and publishing API docs. However, embedding Apiary into our website doesn’t work on mobile devices so we now use Jekyll to generate static docs instead.  Our latest SparkPost API-documenten now load quickly and work well on mobile devices which is important for developers who are not always sitting at their computer.


Deployment scheiden van Release

We leerden al vroeg de waardevolle truc om een deployment te scheiden van een release. Op deze manier is het mogelijk om regelmatig veranderingen uit te rollen wanneer ze klaar zijn via continuous delivery en deployment, maar we kondigen ze niet altijd tegelijkertijd publiekelijk aan of documenteren ze. Het is niet ongebruikelijk dat we een nieuw API-eindpunt of een verbetering van een bestaand API-eindpunt implementeren en gebruiken vanuit de UI of met interne tools voordat we het publiekelijk documenteren en ondersteunen. Op die manier kunnen we wat aanpassingen doen voor gebruiksvriendelijkheid of conformiteit met normen zonder ons zorgen te maken over een gevreesde brekende verandering. Zodra we tevreden zijn met de wijziging voegen we die toe aan onze openbare documentatie.


Doh!

It is only fair to admit that there have been times where we have not lived up to our “no breaking changes” ideals and these are worth learning from. On one occasion we decided it would be better for users if a certain property defaulted to true instead of false. After we deployed the change we received several complaints from users since the behavior had changed unexpectedly.  We reverted the change and added an account level setting – a much more user friendly approach for sure.


Af en toe komen we in de verleiding om veranderingen aan te brengen als gevolg van bugfixes. We hebben echter besloten om deze eigenaardigheden met rust te laten in plaats van het risico te lopen om integraties van klanten kapot te maken omwille van de consistentie.


There are rare cases where we made the serious decision to make a breaking change – such as deprecating an API resource or method – in the interest of the greater user community and only after confirming that there is little to no impact to users. For example, we deliberately made the choice to alter the response behavior of the Suppression API but only after carefully weighing the benefits and impacts naar de community and carefully communicating the change to our users. However, we would never introduce a change that has a remote possibility of directly impacting the sending of a user’s production email.

Your new standard in Marketing, Pay & Sales. It's Bird

The right message -> naar de right person -> aan de right time.

Your new standard in Marketing, Pay & Sales. It's Bird

The right message -> to the right person -> aan de right time.