Destaques

Versionamento API: URL vs header vs query param - qual escolher?

ResumoO versionamento de API por URL, header ou query param apresenta diferenças técnicas significativas. URL versioning oferece simplicidade e visibilidade, mas quebra a semântica REST. Header versioning mantém URLs limpas, porém dificulta cache e testes. Query param versioning é flexível, mas polui a interface. A escolha depende do contexto: URL para APIs públicas, header para sistemas internos, query param para transições.

URL, header ou query param? Cada abordagem de versionamento de API resolve um problema, mas nenhuma é bala de prata. Veja o comparativo técnico para não errar na escolha.

Igor Bastos
Versionamento API: URL vs header vs query param - qual escolher?

Versionamento API: URL vs header vs query param - qual escolher? — Foto: Reprodução / Blog Sem Juízo

A escolha que assombra todo dev de API

Você terminou a primeira versão da API. Tudo lindo. Seis meses depois, precisa alterar o formato de resposta de um endpoint. Se não versionar, clientes antigos quebram. Se versionar, precisa decidir como. URL, header ou query param? Não existe resposta certa universal, existe a certa para o seu contexto.

O versionamento de API é a prática de gerenciar mudanças na interface sem quebrar consumidores existentes. Cada abordagem carrega compensações: legibilidade, aderência RESTful, facilidade de cache e custo de manutenção. Vou comparar as três de forma direta.

Visão geral das três abordagens

| Critério | URL | Header | Query param | |---|---|---|---| | Exemplo prático | /v1/usuarios, /v2/usuarios | Accept: application/vnd.api+json;version=2 | /usuarios?version=2 | | Semântica RESTful | Baixa (URL identifica recurso, não versão) | Alta (negociação de conteúdo) | Média (recurso é o mesmo, versão é parâmetro) | | Cacheabilidade | Fácil (cada URL é única) | Difícil (cache por header exige configuração extra) | Fácil (URL diferente com query string) | | Legibilidade para humanos | Alta | Baixa (header invisível na URL) | Média | | Facilidade de implementação | Muito fácil | Média (exige parser de header) | Fácil |

Facilidade de implementação

URL ganha disparado. Você cria uma nova rota, aponta para o novo controlador e pronto. Frameworks como Express, Spring Boot e Django têm suporte nativo para prefixos de rota. É a abordagem mais rápida de colocar no ar.

Query param também é simples: um parâmetro a mais na requisição. O problema aparece quando você esquece de tratá-lo em algum lugar, clientes podem receber a versão errada sem aviso.

Header exige mais código. Você precisa ler o header Accept ou customizado, fazer parsing e rotear internamente. Não é complexo, mas adiciona uma camada que frameworks não resolvem de fábrica.

Aderência aos princípios REST

Se você é purista REST, header é a escolha correta. Roy Fielding, no paper original, define que a URL identifica o recurso, não a versão dele. A versão faz parte da negociação de conteúdo, assim como você negocia JSON vs XML.

Na prática, poucas APIs seguem isso à risca. URL é a abordagem mais comum no mercado: GitHub, Stripe, Google Maps, todas usam URL. O pragmatismo venceu a pureza.

Query param fica no meio do caminho. O recurso é o mesmo (/usuarios), mas a versão vira um parâmetro. Não viola REST de forma gritante, mas também não segue a especificação.

Cacheabilidade e desempenho

URL e query param são naturalmente cacheadas. Cada combinação de URL + query string é uma chave única no cache HTTP. Proxies, CDNs e browsers tratam isso sem configuração extra.

Header quebra o cache padrão. A mesma URL /usuarios pode retornar corpos diferentes dependendo do header Accept. Para cachear corretamente, você precisa configurar Vary: Accept no servidor e garantir que proxies intermediários respeitem isso. Muita gente esquece e acaba com cache poluído.

Manutenção de código e rotas

Com URL, você mantém duas (ou mais) implementações paralelas: /v1/usuarios e /v2/usuarios. O código duplica, mas fica explícito. Cada versão pode evoluir independentemente.

Header e query param tendem a concentrar a lógica de versão dentro do mesmo endpoint. Você acaba com condicionais do tipo if version == 1 espalhadas. Conforme as versões acumulam, o código fica difícil de ler.

Uma ressalva: dá para mitigar isso com estratégia de adaptadores ou handlers separados internamente. Mas exige disciplina de equipe.

Experiência do desenvolvedor consumidor

Desenvolvedores que consomem sua API preferem URL. É visível, testável no navegador, documentável de forma direta. Um link como https://api.exemplo.com/v2/usuarios/123 não deixa dúvidas.

Query param é quase tão bom, mas pode gerar confusão se combinado com outros parâmetros. Já vi casos em que ?version=2 conflitava com ?page=2&version=1.

Header é o pior para o consumidor. Ele não vê a versão na URL, precisa lembrar de enviar o header correto, e ferramentas como Postman ou cURL exigem configuração extra. Documentação precisa ser mais explícita.

Versionamento semântico e evolução

Nenhuma abordagem resolve o problema de quando versionar. Você pode usar URL e ainda assim versionar mal, criando /v1.1, /v1.2 que ninguém entende. O consenso é usar versionamento semântico (MAJOR.MINOR.PATCH) e expor apenas a major na API pública.

Independente da técnica, o importante é comunicar as mudanças com clareza. Uma changelog bem escrita vale mais que qualquer escolha técnica.

Veredito: qual escolher?

Para quem busca simplicidade e adoção rápida: escolha URL. É a abordagem mais usada, mais fácil de implementar e mais amigável para consumidores. Você perde pureza REST, mas ganha produtividade.

Para quem prioriza aderência RESTful e controle fino: escolha header. Exige mais configuração de cache e documentação, mas segue a especificação. Útil em APIs públicas que precisam negociar múltiplos formatos.

Para quem quer um meio-termo: escolha query param. Fácil de implementar, cacheável, mas pode poluir a URL e gerar confusão com outros parâmetros. Funciona bem em APIs internas ou com poucos consumidores.

Minha recomendação pessoal: comece com URL. Você sempre pode adicionar header depois como alternativa. O contrário é mais difícil.

Perguntas frequentes sobre versionamento de API

Qual a diferença entre versionamento de API e versionamento semântico?

Versionamento de API é a técnica de expor diferentes versões da interface (URL, header, query param). Versionamento semântico é um esquema de números (MAJOR.MINOR.PATCH) que indica o tipo de mudança. Você pode usar semântico com qualquer abordagem técnica.

Versionar pela URL é considerado anti-pattern?

Alguns puristas REST consideram, porque a URL deve identificar o recurso, não a versão. Na prática, é o padrão de mercado. Grandes APIs como GitHub, Stripe e Twilio usam URL. A menos que você precise de negociação de conteúdo complexa, não é problema.

Como evitar duplicação de código com versionamento por URL?

Use adapters ou camadas de serviço. A rota /v1/usuarios e /v2/usuarios podem chamar o mesmo serviço interno, com transformações específicas da versão na camada de apresentação. Evite duplicar lógica de negócio.

É possível usar mais de uma abordagem ao mesmo tempo?

Sim. Muitas APIs aceitam URL e header simultaneamente. Por exemplo, se o header não for enviado, usa a versão da URL. Isso dá flexibilidade para consumidores. Só tome cuidado para não criar comportamentos ambíguos.

Query param version funciona com cache de CDN?

Funciona, porque cada combinação de URL + query string é uma chave única. Mas CDNs costumam ter limites no número de query strings que consideram para cache. Verifique a documentação da sua CDN.

Qual abordagem é mais segura?

Nenhuma é inerentemente mais segura. O risco maior é expor versões antigas com vulnerabilidades. Independente da técnica, desabilite versões legadas após um período de transição e mantenha apenas as duas últimas versões ativas.

Igor Bastos

Editoria Destaques

Igor Bastos cobre o setor de meios de pagamento e crédito no Blog Sem Juízo. Análises técnicas, sem viés comercial.