Versionamento de APIs

Estratégias para versionar APIs REST e GraphQL — versionamento por URL, headers, semântico, compatibilidade retroativa e depreciação.

Por que versionar APIs?

Quando múltiplos consumidores dependem de uma API, qualquer mudança em seu contrato pode quebrar integrações existentes. O versionamento permite evoluir a API de forma controlada, dando tempo para que os consumidores se adaptem.

Sem uma estratégia de versionamento clara, as equipes acabam em uma de duas situações: ou não conseguem mudar nada com medo de quebrar consumidores, ou quebram coisas constantemente sem perceber.

Estratégias de versionamento

Versionamento por URL

A estratégia mais comum e visível. A versão é incluída diretamente na rota:

GET /api/v1/products
GET /api/v2/products

Vantagens:

  • Extremamente explícito — não há ambiguidade sobre qual versão está sendo usada
  • Fácil de rotear em API Gateways e load balancers
  • Simples de documentar e comunicar

Desvantagens:

  • Pode levar à duplicação de código se não for bem estruturado internamente
  • Os consumidores precisam atualizar URLs ao migrar

Versionamento por headers

A versão é especificada em um header HTTP personalizado ou no header Accept:

GET /api/products
Accept: application/vnd.myapi.v2+json

Ou com um header customizado:

GET /api/products
X-API-Version: 2

Vantagens:

  • As URLs se mantêm limpas e estáveis
  • Permite negociação de conteúdo mais sofisticada

Desvantagens:

  • Menos visível — requer inspecionar headers para saber qual versão está em uso
  • Mais difícil de testar a partir de um navegador

Versionamento semântico (SemVer)

Aplica os princípios do Semantic Versioning à API:

  • MAJOR (v1 → v2): Mudanças breaking — incompatíveis com versões anteriores
  • MINOR (v1.1 → v1.2): Novas funcionalidades compatíveis com versões anteriores
  • PATCH (v1.1.0 → v1.1.1): Correções de bugs sem mudanças funcionais

Na prática, as APIs públicas costumam expor apenas a versão MAJOR na URL (/v1/, /v2/) e lidar com MINOR/PATCH internamente.

Compatibilidade retroativa

Uma mudança é backward compatible se os consumidores existentes puderem continuar funcionando sem modificações. Exemplos de mudanças compatíveis:

  • Adicionar um novo campo opcional a uma resposta
  • Adicionar um novo endpoint
  • Adicionar um parâmetro de query opcional
  • Adicionar um novo valor a um enum (com cuidado)

Exemplos de mudanças breaking:

  • Remover um campo da resposta
  • Renomear um campo existente
  • Mudar o tipo de um campo (string → number)
  • Tornar obrigatório um campo que era opcional
  • Mudar a semântica de um campo existente

Estratégias de depreciação

Quando você precisa retirar uma versão antiga:

1. Comunicação antecipada

Anuncie a depreciação com antecedência suficiente (mínimo de 3 a 6 meses para APIs públicas):

Deprecation: true
Sunset: Sat, 01 Mar 2025 00:00:00 GMT
Link: <https://docs.api.com/migration/v2>; rel="successor-version"

2. Período de coexistência

Mantenha ambas as versões funcionando em paralelo durante o período de transição. Monitore o tráfego da versão antiga para saber quando é seguro retirá-la.

3. Respostas com warnings

Inclua headers de aviso nas respostas da versão depreciada:

Warning: 299 - "API v1 is deprecated. Please migrate to v2 by 2025-03-01"

4. Sunset definitivo

Após a data de sunset, as chamadas para a versão antiga podem retornar 410 Gone com um corpo explicando como migrar.

Boas práticas

  • Versione desde o primeiro dia — é muito mais fácil começar com /v1/ do que adicionar versionamento depois
  • Documente as mudanças — mantenha um changelog claro por versão
  • Use feature flags internamente — para lidar com diferenças entre versões sem duplicar código
  • Monitore o uso por versão — saiba quantos consumidores usam cada versão antes de depreciar
  • Defina uma política de suporte — quantas versões você mantém simultaneamente e por quanto tempo