Versionamento REST API: URL, header o query, quale scegliere
6 min di lettura
Il versionamento REST API è il modo in cui un’API dice a un chiamante quale contratto sta usando una richiesta, così che il server possa cambiare il contratto senza rompere i chiamanti che non si sono ancora spostati. La versione può stare in tre posti: nel percorso URL (/v2/orders), in un header di richiesta (Accept: application/vnd.acme.v2+json o un header personalizzato Api-Version: 2026-10-01), oppure in un parametro query (/orders?version=2). Il percorso è il più comune perché è visibile ovunque, l’header è il più pulito per l’URL, e la query string è quella di cui la maggior parte dei team si pente. Quale scegliere dipende da chi sono i vostri chiamanti e da come pensate di comunicare loro i cambiamenti.
| Dove vive la versione | Esempio | Visibile a | Cacheabile di default | Usato da |
|---|---|---|---|---|
| Percorso URL | GET /v2/orders | Ogni log, link, proxy e browser | Sì | Twitter, Shopify, la maggior parte delle API pubbliche |
| Header personalizzato | Api-Version: 2026-10-01 | Solo i client che lo impostano | Con Vary: Api-Version | Stripe (Stripe-Version), GitHub (X-GitHub-Api-Version) |
| Header Accept | Accept: application/vnd.acme.v2+json | Solo i client che lo impostano | Con Vary: Accept | Media type di GitHub, alcune API enterprise |
| Parametro query | GET /orders?api-version=2 | Log e link, mescolata ai filtri | Sì, ma inquina le chiavi di cache | REST API di Azure |
| Nessuna versione | GET /orders più soli cambiamenti additivi | Nessuno | Sì | API interne e in stile GraphQL |
Cosa sono v1 e v2 in una REST API?
v1 e v2 sono etichette per due versioni del contratto dell’API: le stesse risorse, raggiungibili a percorsi diversi, dove v2 può rinominare campi, cambiare tipi, togliere endpoint o alterare la forma degli errori da cui i chiamanti di v1 dipendono. Una richiesta a /v1/orders continua a ricevere la vecchia forma finché v1 è supportata; una richiesta a /v2/orders riceve quella nuova. Il numero è una promessa di compatibilità, ed è la promessa a renderlo utile. Incrementarlo a ogni rilascio trasforma l’etichetta in rumore.
La maggior parte delle API ha bisogno di una nuova versione major solo per un cambiamento che rompe i chiamanti esistenti. Aggiungere un campo, un nuovo endpoint o un nuovo parametro opzionale può uscire sotto la versione attuale, perché un client scritto bene ignora ciò che non conosce. Quando versionare un’API, e cosa fare invece copre la decisione; questo articolo riguarda dove va la versione nel versionamento REST API una volta deciso di incrementarla.
Il versionamento REST API dovrebbe stare nell’URL o in un header?
Mettetelo nell’URL se tra i vostri chiamanti ci sono persone che digitano richieste in un browser, copiano esempi dalla documentazione o leggono log; mettetelo in un header se volete un solo URL stabile per risorsa e i vostri chiamanti sono tutti SDK o codice che controllate. Il percorso URL è esplicito come nient’altro: un ticket di supporto con dentro la riga della richiesta vi dice già la versione. Un header va impostato su ogni richiesta, è invisibile in un link ed è facile da perdere su un proxy, ed è per questo che le API versionate per header definiscono sempre un default per le richieste che non lo inviano.
L’approccio per header ha un vero vantaggio oltre agli URL ordinati: separa l’identità della risorsa dalla sua rappresentazione, che è il modo in cui HTTP è stato progettato. L’RFC 9110 descrive la negoziazione del contenuto tramite Accept, e un media type come application/vnd.github.v3+json è una versione espressa in quel modo. In pratica la purezza del design conta meno del fatto che i vostri chiamanti si ricordino di inviare l’header.
Come funziona il versionamento per data?
Invece di v1 e v2, la versione è una data, e ogni breaking change riceve una nuova data. Un chiamante fissa la data contro cui ha integrato, di solito una volta a livello di account, e mantiene quel comportamento finché non sceglie di spostarsi. L’header Stripe-Version di Stripe e l’X-GitHub-Api-Version di GitHub funzionano entrambi così.
Il compromesso è nell’implementazione. Ogni breaking change diventa un piccolo strato di trasformazione che converte tra la data fissata e la forma attuale, e il server li impila: una richiesta fissata a due anni fa passa attraverso ogni cambiamento da allora. È più pesante da costruire di una seconda copia degli handler, e premia un’API che cambia di rado. I team che rilasciano una breaking change al mese finiscono con decine di trasformazioni. Versionamento API di Stripe guarda il modello dal lato del chiamante, incluso ciò che il changelog deve riportare.
Perché il versionamento in query string è sconsigliato?
Perché mescola il contratto con i filtri. /orders?status=open&api-version=2 fa sembrare la versione un affinamento opzionale invece della cosa che decide la forma di ogni campo della risposta. È anche la più facile da perdere per sbaglio, perché le query string vengono ricostruite dalle librerie client, tagliate da alcuni proxy e modificate a mano dalle persone. Le linee guida di Microsoft sul design delle REST API documentano la forma a parametro query che Azure usa, ed è l’ecosistema di SDK generati intorno a essa a renderla praticabile; senza quegli strumenti, un chiamante che dimentica il parametro riceve in silenzio la versione di default.
Cosa succede alla vecchia versione?
Continua a funzionare, con una data in cui si ferma. Lo scopo del versionamento è lasciare che i chiamanti si spostino secondo il proprio calendario, e questo è vero solo se la vecchia versione resta disponibile abbastanza a lungo perché possano farlo e se viene detto loro quando finisce. Le linee guida di Google sul versionamento API descrivono il ciclo di vita che usa per le proprie API: una versione stabile è supportata fino a una data di deprecazione pubblicata, con la sostituta disponibile per l’intera finestra di deprecazione.
L’annuncio è la parte che la maggior parte dei team costruisce meno. Un nuovo percorso o header serve solo ai chiamanti che sanno che esiste, sanno cosa è cambiato e sanno quando v1 sparisce. Sono tre fatti, e ognuno ha bisogno di una casa: una voce datata nel changelog API con le differenze a livello di campo, un avviso di deprecazione che dichiara la data di fine, e una guida alla migrazione che percorre ogni cambiamento per un chiamante ancora sulla vecchia versione. Dismettere una versione API copre l’ultimo passo, incluso l’header Sunset che permette a un client di scoprire la data su ogni risposta.
Si può evitare del tutto il versionamento REST API?
Sì, finché ogni cambiamento è additivo. Aggiungete campi, mai rimuoverli o rinominarli; aggiungete endpoint, mai cambiare ciò che uno esistente restituisce; accettate nuovi parametri opzionali, mai cambiare il significato di uno vecchio. Molte API interne girano per anni solo con questa regola, ed è la regola che gli schemi GraphQL seguono per design. Il costo è un contratto che cresce soltanto, con campi deprecati che devono restare perché qualcuno, da qualche parte, li legge ancora.
Quando un cambiamento additivo è impossibile, lo strumento è la versione. La scelta tra percorso, header e data decide cosa vedono i chiamanti e come il cambiamento viene annunciato; ciò che resta costante è che il cambiamento va scritto da qualche parte dove un chiamante lo leggerà. Per un’API con chiamanti esterni quel posto è il changelog, e l’articolo sulle breaking changes spiega cosa conta come tale.
FAQ
Qual è il modo migliore per versionare una REST API? Una versione major nel percorso URL è la più compresa e la più difficile da sbagliare, il che la rende il default per un’API pubblica. Una versione per header mantiene stabili gli URL e si adatta alle API guidate da SDK; un header per data si adatta alle API che cambiano di rado e vogliono che i chiamanti fissino il comportamento.
Cos’è v1 nell’URL di un’API?
È la prima versione major del contratto dell’API. Alle richieste verso /v1/... è promessa la forma documentata per la versione 1, anche dopo che esiste una /v2/ con campi o comportamenti diversi.
Serve una nuova versione API per ogni cambiamento? No. I cambiamenti additivi come nuovi campi, endpoint e parametri opzionali possono uscire sotto la versione esistente. Solo un cambiamento che rompe i chiamanti esistenti ne richiede una nuova.
Per quanto tempo va supportata una vecchia versione API? Abbastanza perché i chiamanti migrino, il che per un’API pubblica di solito significa da sei a dodici mesi dopo che la sostituta è disponibile, con la data pubblicata all’annuncio e ripetuta nell’avviso di deprecazione.
Le affermazioni tecniche di questo articolo non sono state verificate in modo indipendente. Se qualcosa non è corretto, faccelo sapere e lo correggeremo.