Modificări de API

Versionare REST API: URL, header sau query, care e potrivit

6 min de citit

Versionarea REST API e felul în care un API îi spune unui apelant ce contract folosește o cerere, ca serverul să poată schimba contractul fără să-i strice pe apelanții care nu au trecut mai departe. Versiunea poate sta în trei locuri: în calea URL-ului (/v2/orders), într-un header al cererii (Accept: application/vnd.acme.v2+json sau unul propriu, Api-Version: 2026-10-01) sau într-un parametru de query (/orders?version=2). Calea e cea mai răspândită pentru că e vizibilă peste tot, header-ul e cel mai curat pentru URL, iar query string-ul e cel pe care cele mai multe echipe îl regretă. Care se potrivește depinde de cine sunt apelanții voștri și de cum plănuiți să le spuneți despre schimbări.

Unde stă versiuneaExempluVăzută deCache implicitFolosită de
Calea URLGET /v2/ordersFiecare log, link, proxy și browserDaTwitter, Shopify, majoritatea API-urilor publice
Header propriuApi-Version: 2026-10-01Doar clienții care îl seteazăCu Vary: Api-VersionStripe (Stripe-Version), GitHub (X-GitHub-Api-Version)
Header AcceptAccept: application/vnd.acme.v2+jsonDoar clienții care îl seteazăCu Vary: AcceptTipurile media GitHub, unele API-uri enterprise
Parametru de queryGET /orders?api-version=2Loguri și linkuri, amestecată cu filtreleDa, dar poluează cheile de cacheAPI-urile REST Azure
Fără versiuneGET /orders plus doar schimbări aditiveNimeniDaAPI-uri interne și în stil GraphQL

Ce sunt v1 și v2 într-un REST API?

v1 și v2 sunt etichete pentru două versiuni ale contractului API: aceleași resurse, accesibile pe căi diferite, unde v2 poate redenumi câmpuri, schimba tipuri, elimina endpoint-uri sau modifica forma erorilor de care depind apelanții v1. O cerere către /v1/orders primește în continuare forma veche atâta timp cât v1 e susținut; o cerere către /v2/orders o primește pe cea nouă. Numărul e o promisiune despre compatibilitate, iar promisiunea e ce îl face util. Dacă îl creșteți la fiecare lansare, eticheta devine zgomot.

Cele mai multe API-uri au nevoie de o versiune majoră nouă doar pentru o schimbare care strică apelanții existenți. Adăugarea unui câmp, a unui endpoint nou sau a unui parametru opțional nou poate ieși sub versiunea curentă, pentru că un client bine scris ignoră ce nu cunoaște. Când versionezi un API și ce faci în loc acoperă decizia; acest articol e despre unde stă versiunea în versionarea REST API odată ce ați hotărât s-o creșteți.

Versionarea REST API ar trebui să stea în URL sau într-un header?

Puneți-o în URL dacă printre apelanții voștri sunt oameni care tastează cereri într-un browser, copiază exemple din documentație sau citesc loguri; puneți-o într-un header dacă vreți un singur URL stabil per resursă și apelanții sunt toți SDK-uri sau cod pe care îl controlați. Calea URL-ului e explicită cum nimic altceva nu e: un tichet de suport care conține linia cererii vă spune deja versiunea. Un header trebuie setat la fiecare cerere, e invizibil într-un link și se pierde ușor la un proxy, motiv pentru care API-urile versionate prin header definesc întotdeauna o valoare implicită pentru cererile care nu îl trimit.

Abordarea cu header are un singur avantaj real dincolo de URL-uri ordonate: separă identitatea resursei de reprezentarea ei, așa cum a fost gândit HTTP. RFC 9110 descrie negocierea conținutului prin Accept, iar un tip media precum application/vnd.github.v3+json e o versiune exprimată în felul acesta. În practică, puritatea designului contează mai puțin decât dacă apelanții își amintesc să trimită header-ul.

Cum funcționează versionarea pe bază de dată?

În loc de v1 și v2, versiunea e o dată, iar fiecare schimbare incompatibilă primește o dată nouă. Un apelant fixează data la care s-a integrat, de obicei o singură dată, la nivel de cont, și păstrează acel comportament până alege să treacă mai departe. Header-ul Stripe-Version de la Stripe și X-GitHub-Api-Version de la GitHub funcționează amândouă așa.

Compromisul e în implementare. Fiecare schimbare incompatibilă devine un mic strat de transformare care convertește între data fixată și forma curentă, iar serverul le stivuiește: o cerere fixată cu doi ani în urmă trece prin fiecare schimbare de atunci. E mai greu de construit decât o a doua copie a handler-elor și răsplătește un API care se schimbă rar. Echipele care livrează o schimbare incompatibilă pe lună ajung la zeci de transformări. Versionarea API Stripe privește modelul din partea apelantului, inclusiv ce trebuie să poarte changelog-ul.

De ce e descurajată versionarea prin query string?

Pentru că amestecă contractul cu filtrele. /orders?status=open&api-version=2 face ca versiunea să pară un rafinament opțional, nu lucrul care decide forma fiecărui câmp din răspuns. E și cea mai ușor de pierdut din greșeală, fiindcă query string-urile sunt reconstruite de bibliotecile client, tăiate de unele proxy-uri și editate de mână de oameni. Ghidul Microsoft de design pentru REST API documentează forma cu parametru de query pe care o folosește Azure, iar ecosistemul de SDK-uri generate din jurul ei e ce o face funcțională; fără acele unelte, un apelant care uită parametrul primește în tăcere versiunea implicită.

Ce se întâmplă cu versiunea veche?

Rulează în continuare, cu o dată la care se oprește. Rostul versionării e să-i lase pe apelanți să treacă mai departe după propriul program, iar asta e adevărat doar dacă versiunea veche rămâne disponibilă destul cât s-o poată face și dacă li se spune când se încheie. Ghidul Google de versionare a API-urilor descrie ciclul de viață folosit pentru propriile API-uri: o versiune stabilă e susținută până la o dată de depreciere publicată, cu înlocuitorul disponibil pe toată fereastra de depreciere.

Anunțul e partea pe care cele mai multe echipe o construiesc prea puțin. O cale sau un header nou e util doar apelanților care știu că există, știu ce s-a schimbat și știu când dispare v1. Sunt trei fapte, și fiecare are nevoie de un loc: o intrare datată în changelog-ul API cu diferențele la nivel de câmp, un anunț de depreciere care spune data de încheiere și un ghid de migrare care parcurge fiecare schimbare pentru un apelant încă pe versiunea veche. Închiderea unei versiuni de API acoperă pasul final, inclusiv header-ul Sunset care îi lasă unui client să descopere data la fiecare răspuns.

Poți evita complet versionarea REST API?

Da, atâta timp cât fiecare schimbare e aditivă. Adăugați câmpuri, nu le eliminați și nu le redenumiți niciodată; adăugați endpoint-uri, nu schimbați niciodată ce întoarce unul existent; acceptați parametri opționali noi, nu schimbați niciodată sensul unuia vechi. Multe API-uri interne rulează ani întregi doar pe regula asta, și e regula pe care schemele GraphQL o urmează prin design. Costul e un contract care doar crește, cu câmpuri depreciate care trebuie să rămână pentru că cineva, undeva, încă le citește.

Când o schimbare aditivă e imposibilă, versiunea e unealta. Alegerea între cale, header și dată decide ce văd apelanții și cum e anunțată schimbarea; ce rămâne constant e că schimbarea trebuie scrisă undeva unde un apelant o va citi. Pentru un API cu apelanți externi, acel loc e changelog-ul, iar articolul despre breaking changes acoperă ce contează ca atare.

FAQ

Care e cel mai bun mod de a versiona un REST API? O versiune majoră în calea URL-ului e cea mai larg înțeleasă și cel mai greu de greșit, ceea ce o face opțiunea implicită pentru un API public. O versiune în header ține URL-urile stabile și se potrivește API-urilor conduse de SDK-uri; un header pe bază de dată se potrivește API-urilor care se schimbă rar și vor ca apelanții să fixeze comportamentul.

Ce este v1 într-un URL de API? E prima versiune majoră a contractului API. Cererilor către /v1/... li se promite forma documentată pentru versiunea 1, chiar și după ce există un /v2/ cu câmpuri sau comportament diferite.

Am nevoie de o versiune nouă de API pentru fiecare schimbare? Nu. Schimbările aditive, precum câmpuri, endpoint-uri și parametri opționali noi, pot ieși sub versiunea existentă. Doar o schimbare care strică apelanții existenți are nevoie de una nouă.

Cât timp ar trebui susținută o versiune veche de API? Destul cât apelanții să migreze, ceea ce pentru un API public înseamnă de obicei șase până la douăsprezece luni după ce înlocuitorul e disponibil, cu data publicată la anunț și repetată în anunțul de depreciere.


Afirmațiile tehnice din acest articol nu au fost verificate independent. Dacă ceva nu e corect, spune-ne și vom corecta.

Pe changeloop: Documentație pentru dezvoltatori, Exemple de changelog

changeloop
Echipa care construiește un changelog care închide bucla. Utilizatorii cer ceva, echipa ta livrează, cel care a cerut află.