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