Naar de inhoud
maarten.
Alle stories

API-versiebeheer: compatibiliteit en migraties

Maarten Soetens 12 min lezen

API-versiebeheer bepaalt hoe wijzigingen in een interface doorwerken in bestaande clients. Lees hoe URL- en headerversies verschillen, welke aanpassingen compatibel zijn en hoe je een migratie beheerst zonder afhankelijkheden over het hoofd te zien.

Waarom API-versiebeheer meer is dan een versienummer

Een API is een contract tussen een aanbieder en de software die de API gebruikt. Dat contract bestaat niet alleen uit endpoints en velden, maar ook uit datatypen, foutcodes, authenticatie, paginering en de betekenis van waarden. Een wijziging kan technisch klein lijken en toch bestaande clients verstoren. Een veld dat voortaan soms ontbreekt, bijvoorbeeld, kan code laten vastlopen die ervan uitgaat dat het altijd aanwezig is.

Versiebeheer maakt zichtbaar welke contractvariant een client gebruikt. Het geeft teams ruimte om wijzigingen te plannen en voorkomt dat één nieuwe interpretatie onverwacht alle integraties beïnvloedt. Een versienummer lost op zichzelf echter geen compatibiliteitsprobleem op. Daarvoor moet duidelijk zijn wat een versie omvat, hoe lang die ondersteund wordt en hoe clients kunnen overstappen.

Leg daarom vast welke onderdelen van het contract versiegebonden zijn. Geldt een versie voor de volledige API, voor een resource of alleen voor representaties van data? Ook moet duidelijk zijn wat er gebeurt met niet-versiegebonden onderdelen, zoals authenticatie of foutafhandeling. Zonder zulke afspraken ontstaan uitzonderingen die per endpoint verschillen. Dat maakt documentatie moeilijker en vergroot de kans dat een wijziging in de ene client veilig is, maar een andere client breekt.

API-versies in URL’s: zichtbaar en eenvoudig te routeren

Bij versies in de URL staat het versienummer doorgaans in het pad, bijvoorbeeld in de vorm van een versieprefix vóór de resource. De gekozen variant is daardoor zichtbaar in logs, browsertools, foutmeldingen en documentatie. Ook kunnen routers, gateways en cachinglagen aanvragen relatief eenvoudig naar verschillende implementaties sturen. Dat maakt URL-versies aantrekkelijk wanneer meerdere contracten langere tijd naast elkaar bestaan.

De zichtbaarheid heeft een prijs. Een versiepad kan worden opgevat als een afzonderlijke resource, terwijl de inhoud in feite dezelfde resource volgens een ander contract is. Clients moeten bovendien hun basis-URL aanpassen wanneer ze migreren. Wanneer versies per endpoint worden ingevoerd, kunnen combinaties ontstaan die moeilijk te begrijpen zijn: een client gebruikt bijvoorbeeld de ene versie voor klanten en een andere voor facturen. Een consistente versiegrens voorkomt dat soort fragmentatie.

URL-versies passen goed bij publieke API’s waarbij clients zelf een expliciete contractversie kiezen. Houd de routering en documentatie dan gelijk: dezelfde versie moet dezelfde betekenis hebben voor alle endpoints binnen haar bereik. Vermijd dat een versiepad alleen een alias is voor de nieuwste implementatie. Als de contractregels geleidelijk veranderen zonder dat het pad verandert, verliezen clients juist de voorspelbaarheid waarvoor de URL-versie is gekozen.

API-versies in headers en media types

Een API kan de gewenste contractversie ook via een HTTP-header laten kiezen. Dat kan met een specifieke versieheader of met een media type in de headers voor inhoudsonderhandeling. De URL blijft dan hetzelfde, terwijl de aanvraag aangeeft welke representatie de client verwacht. Dit houdt resource-identificatie en contractkeuze uit elkaar en kan passen bij API’s die sterk op HTTP-semantiek leunen.

Een minder zichtbaar versienummer is ook lastiger te ontdekken. Iemand die een URL uit een log kopieert of een fout reproduceert, ziet niet noodzakelijk welke versie is aangevraagd. De header moet daarom consequent worden vastgelegd in logs, tracing en foutdiagnostiek. Ook caches verdienen aandacht: als de respons afhangt van een versieheader, moet de cachinglaag die header meenemen in haar cachekey, bijvoorbeeld via een passende Vary-instelling. Anders kan een client een representatie ontvangen die voor een andere contractversie bedoeld is.

Headers vragen bovendien om expliciet gedrag wanneer de versie ontbreekt, onbekend is of niet meer ondersteund wordt. Stilzwijgend terugvallen op de nieuwste versie maakt aanvragen afhankelijk van serverwijzigingen en kan compatibiliteit ongemerkt ondermijnen. Geef in documentatie en foutresponsen aan hoe clients de versie kiezen. De afweging is dus niet alleen esthetisch: zichtbaarheid, caching, infrastructuur en foutdiagnostiek bepalen mede of een headerstrategie beheersbaar blijft.

Semantische versienummers en contractwijzigingen

Semantische versienummers worden vaak beschreven als major, minor en patch: een major-versie kan incompatibele wijzigingen bevatten, een minor-versie voegt compatibele functionaliteit toe en een patch herstelt gedrag zonder het contract te veranderen. Dat model helpt bij libraries en services die versies uitbrengen als afzonderlijke releases. Voor een HTTP-API moet eerst duidelijk zijn wat het versienummer representeert. Een patchnummer in de URL heeft weinig betekenis als clients er niet op kunnen of hoeven te selecteren.

Maak onderscheid tussen de versie van de implementatie en de versie van het publieke contract. Een interne release kan tientallen keren veranderen zonder dat clients een nieuwe contractversie nodig hebben. Omgekeerd kan een ogenschijnlijk kleine implementatiewijziging het contract breken, bijvoorbeeld wanneer een foutcode verandert of een waarde een andere betekenis krijgt. Beoordeel versieverhogingen dus op waarneembaar gedrag, niet op de omvang van de codewijziging.

Leg per wijziging vast of bestaande aanvragen en responses hetzelfde blijven interpreteren. Een optioneel nieuw veld kan compatibel zijn, maar alleen als clients onbekende velden verdragen en de server het veld niet onverwacht verplicht stelt. Een nieuw enum-item kan bestaande code breken wanneer die alle mogelijke waarden uitputtend afhandelt. Versienummers geven structuur aan die beslissingen, maar vervangen geen analyse van clientgedrag en contracttests.

Backward compatible API-wijzigingen beoordelen

Een wijziging is backward compatible wanneer bestaande clients met hun huidige aannames blijven functioneren. In de praktijk is dat lastiger vast te stellen dan alleen controleren of een endpoint nog antwoord geeft. Een nieuw optioneel requestveld lijkt doorgaans veilig, maar wordt brekend zodra de server het veld verplicht maakt of een bestaande default anders interpreteert. Een nieuw responseveld lijkt eveneens onschuldig, maar kan problemen geven bij clients die onbekende velden afwijzen of responses naar strikte schema’s deserialiseren.

Let op veranderingen in cardinaliteit en betekenis. Een lijst die voorheen altijd één resultaat bevatte en nu leeg kan zijn, verandert het contract ook als het datatype hetzelfde blijft. Hetzelfde geldt voor sortering, null-waarden, tijdzones, afronding en de volgorde waarin resultaten verschijnen. Zulke eigenschappen staan soms niet in het schema, maar worden door clients gebruikt als impliciete afspraak.

Een praktische beoordeling combineert schema-diffs met gebruikscontext. Controleer wie het veld leest, welke aannames in clientcode zitten en of de wijziging invloed heeft op foutafhandeling of beveiliging. Documenteer ook gedrag dat behouden blijft, zoals de betekenis van ontbrekende velden en de statuscodes voor validatiefouten. Backward compatibility is geen eigenschap die uitsluitend uit een OpenAPI-bestand kan worden afgeleid; het is een relatie tussen het gewijzigde contract en het gedrag van bestaande clients.

Breaking changes herkennen vóór implementatie

Een breaking change voorkomt dat een bestaande client zonder aanpassing correct blijft werken. Duidelijke voorbeelden zijn het verwijderen of hernoemen van een veld, het wijzigen van een datatype en het veranderen van een endpoint of HTTP-methode. Minder zichtbare voorbeelden zijn een striktere validatieregel, een andere standaardwaarde, een gewijzigde autorisatie-eis of een statuscode waarop clients anders reageren. Ook het beperken van toegestane waarden kan bestaande gegevens of aanvragen ongeldig maken.

Beoordeel wijzigingen vanuit beide richtingen. Bij een request kan een server een bestaand veld niet langer accepteren, terwijl bij een response de client een veld kan verliezen waarop de applicatie vertrouwt. Een wijziging kan bovendien alleen bepaalde clients treffen: een nieuw verplicht veld breekt oudere clients, maar een nieuw responseveld raakt vooral clients met strikte schema-validatie. Dat maakt impactanalyse afhankelijk van de implementaties en niet alleen van de API-definitie.

Leg de reden en de gevolgen van een breaking change vast voordat je de nieuwe contractversie ontwerpt. Soms kan een compatibele uitbreiding het probleem oplossen, bijvoorbeeld door een nieuw veld toe te voegen en het oude tijdelijk te behouden. Soms is een nieuwe versie noodzakelijk omdat de betekenis fundamenteel verandert. Houd oude en nieuwe semantiek niet ongemerkt in één veld samen; clients kunnen dan dezelfde waarde verschillend interpreteren. Een expliciete breuk is beter te analyseren dan een stilzwijgende gedragsverandering.

Migreren tussen API-versies zonder clients te verrassen

Een migratie omvat meer dan het omzetten van een URL of header. De client moet nieuwe schema’s verwerken, gewijzigde foutpaden begrijpen en mogelijk bestaande gegevens anders interpreteren. Begin daarom met een inventarisatie van consumers: interne diensten, mobiele apps, integratiepartners, achtergrondtaken en scripts. Een endpoint met weinig verkeer kan nog steeds cruciaal zijn als het door een periodieke taak wordt gebruikt. Verkeersmetingen alleen tonen bovendien niet altijd welke contractversie een client werkelijk gebruikt.

Een beheersbare overgang laat oude en nieuwe contracten tijdelijk naast elkaar bestaan. Dat vraagt om duidelijke routering, aparte documentatie en tests die de belangrijkste clientscenario’s voor beide versies afdekken. Wanneer clients stapsgewijs migreren, moet de server consistent omgaan met gedeelde gegevens. Als versie één een veld anders opslaat dan versie twee het teruggeeft, kunnen wijzigingen via de ene client onverwacht zichtbaar worden in de andere.

Maak migratiestatus meetbaar per client of integratie. Registreer welke versie wordt aangevraagd en welke requests nog afhankelijk zijn van gedrag dat verdwijnt. Een migratiebericht zonder technische signalen geeft weinig zekerheid over werkelijk gebruik. Houd ook rekening met clients die buiten de controle van het API-team vallen; hun releasecyclus en updategedrag zijn niet gelijk aan die van interne diensten. Zo wordt duidelijk waar parallelle ondersteuning nodig blijft en welke concrete afhankelijkheden een overstap blokkeren.

Uitfaseren van oude API-versies en compatibiliteit testen

Een oude versie uitfaseren vraagt om een expliciet beleid: welke versie is beschikbaar, welke wordt aanbevolen en welke is niet langer ondersteund? Communiceer de status op een plek die developers tijdens implementatie en incidentanalyse gebruiken, zoals versiegebonden documentatie en responsheaders. Een waarschuwing in responses kan aanvullend helpen, maar is geen vervanging voor gerichte communicatie aan bekende consumers. Maak duidelijk welk gedrag verandert en welke clientaanpassing nodig is; een algemene melding over een nieuwe versie geeft onvoldoende migratie-informatie.

Test compatibiliteit op meerdere niveaus. Schema-diffing kan verwijderde velden, gewijzigde types en nieuwe vereiste eigenschappen signaleren. Contracttests controleren of de server blijft voldoen aan verwachtingen van consumers. Integratietests leggen daarnaast gedrag vast rond authenticatie, paginering, foutcodes en grensgevallen. Geen enkele testvorm dekt alle impliciete aannames af, dus combineer automatische controles met een review van betekenisvolle wijzigingen.

Observability maakt zichtbaar wat tests niet kunnen aantonen over productiegebruik. Meet requests per versie, client en endpoint en controleer foutpercentages na een wijziging. Zorg dat logging de gekozen versie bevat zonder gevoelige gegevens onnodig vast te leggen. Een verwijdering is pas verantwoord wanneer resterend gebruik begrepen is en er een besluit bestaat voor uitzonderingen, zoals een client die niet meer onderhouden wordt. Ook dat beleid hoort bij versiebeheer: zonder heldere criteria blijven oude contracten vaak onbeperkt bestaan of verdwijnen ze voordat hun afhankelijkheden bekend zijn.

Veelgestelde vragen

Hoe lang moet je een oude API-versie ondersteunen?

Ondersteun een oude API-versie zolang bekende clients die nodig hebben en een veilige, haalbare migratie nog niet is afgerond. Er bestaat geen vaste termijn die voor elke API geschikt is: de juiste periode hangt onder meer af van releasecycli van clients, contractuele afspraken, risico’s en de impact van uitval.

  • Publiceer per versie een ondersteunings- en einddatum.
  • Geef consumenten voldoende tijd om te testen en uit te rollen.
  • Verleng de termijn als belangrijke afhankelijkheden of migratieblokkades blijven bestaan.

Maak uitzonderingen expliciet en voorkom dat een oude versie stilzwijgend onbeperkt ondersteund blijft.

Hoe kondig je het uitfaseren van een API-versie concreet aan?

Kondig uitfasering aan met een duidelijke datum, een uitleg van de gevolgen en concrete migratiestappen voor iedere getroffen client. Maak onderscheid tussen een versie die niet langer wordt aanbevolen en een versie die daadwerkelijk niet meer beschikbaar is; dat zijn verschillende momenten waarop consumers actie moeten ondernemen.

  • Vermeld de oude en aanbevolen versie in versiegebonden documentatie.
  • Beschrijf welke endpoints, velden of gedragingen veranderen.
  • Stuur bekende consumers rechtstreeks een bericht en herhaal dit vóór de einddatum.
  • Gebruik waar passend Deprecation- en Sunset-responsheaders als extra signaal.

Controleer vervolgens of consumers het bericht hebben ontvangen en of hun gebruik afneemt.

Moet een SDK dezelfde versie volgen als de API?

Nee, een SDK-versie hoeft niet gelijk te lopen aan de API-versie, omdat een SDK een clientbibliotheek is en de API een servercontract. Een nieuwe SDK-release kan bijvoorbeeld bugfixes of ondersteuning voor een andere programmeertaal toevoegen zonder dat het API-contract verandert. Omgekeerd kan een API-versie wijzigen terwijl een SDK-release nog niet beschikbaar is.

  • Gebruik voor de SDK een eigen release- en versienummer.
  • Vermeld in de documentatie welke API-versies elke SDK-release ondersteunt.
  • Test gegenereerde en handgeschreven clients tegen de bedoelde contractversies.

Zo kunnen developers compatibiliteit beoordelen zonder versienummers met verschillende betekenissen door elkaar te halen.

Kunnen meerdere API-versies op dezelfde backend draaien?

Ja, meerdere API-versies kunnen dezelfde backend gebruiken als de server de verschillende contracten duidelijk van elkaar scheidt. Een veelgebruikte aanpak is om per versie een adapter te maken die aanvragen en responses vertaalt tussen het publieke contract en een gedeelde interne representatie. Zo hoeven bedrijfsregels niet automatisch voor elke versie apart te worden gekopieerd.

  • Houd versiegebonden validatie en veldnamen in de adapters.
  • Bewaar één consistente bron van waarheid voor gedeelde gegevens.
  • Test dat wijzigingen via de ene versie correct zichtbaar zijn via de andere.

Als de betekenis of verwerking echt verschilt, kan aanvullende scheiding nodig zijn; forceer dan geen gedeelde logica die verkeerde resultaten oplevert.

Hoe pas je beveiligingsupdates toe op oude API-versies?

Pas noodzakelijke beveiligingsupdates ook toe op ondersteunde oude API-versies, zolang dat kan zonder hun afgesproken contract onnodig te veranderen. Een versie is geen reden om kwetsbare authenticatie, autorisatie of invoerverwerking te laten voortbestaan. Beoordeel wel of de maatregel bestaand clientgedrag raakt en communiceer eventuele gevolgen tijdig.

  • Los kwetsbaarheden waar mogelijk op achter de bestaande interface.
  • Test autorisatie en foutafhandeling voor elke ondersteunde versie.
  • Leg vast wanneer een beveiligingsmaatregel een incompatibele wijziging vereist.
  • Beëindig ondersteuning als een versie niet langer veilig te onderhouden is.

Maak duidelijk welke versies beveiligingsupdates ontvangen, zodat consumers weten welk risico ontstaat wanneer ze niet migreren.

Portret van Maarten

Maarten

Freelance developer in Nijmegen

Even kennismaken?

Vertel kort wat er speelt. Dan hoor je wat er kan, wat ik anders zou doen en waar AI bij jou wél en niet iets toevoegt. Vrijblijvend.

[email protected]
Het kantoor in Nijmegen
© 2026 maarten.online Sitemap Privacy Algemene voorwaarden
Het kantoor in Nijmegen

Maarten.

Freelance developer in Nijmegen. Liever direct contact? Dat kan ook.

Kennismaken

Laat je gegevens achter, dan kijken we of het klikt. Vrijblijvend en zonder verkooppraat.

Maarten

Stuur een bericht via WhatsApp

Hoi! Waar kan ik je mee helpen?

nu