Um breaking change sem aviso queima a confiança de integração em um único deploy. API versioning existe para resolver esse problema: evoluir a API com todo cliente existente rodando em produção. A estratégia se decide em três frentes: onde a versão mora (URI, header ou parâmetro), como o CI detecta quebras antes do merge e como aposentar uma versão sem drama.

O que merece uma nova versão?

Mudança aditiva quebra contrato nenhum. Campo opcional novo na resposta, endpoint extra, parâmetro com default: tudo isso entra sem bump. Versão nova entra quando o contrato muda: renomear campo, remover propriedade, trocar tipo de string para integer, apertar validação. Versione o contrato; número de release é marketing.

Versão na URL (/v1/, /v2/): por que segue sendo o padrão REST?

Path versioning ganha por pragmatismo. A versão aparece no log de acesso, no curl e no navegador; o roteador direciona /v1/orders e /v2/orders para handlers distintos sem middleware; a CDN trata os dois como recursos separados no cache. O defeito é conceitual: /v2/ sugere API inteira reversionada quando a mudança atingiu um recurso só. Twilio leva a ideia ao extremo com datas no caminho (/2010-04-01/) e mantém integrações vivas há mais de uma década.

Versionamento por header Accept

No modelo de header, o cliente envia Accept: application/vnd.minhaapi.v2+json e o servidor roteia pelo media type. As URLs ficam limpas e a complexidade some do caminho do consumidor casual. O custo aparece na operação: debug exige inspecionar headers, a cache key da CDN precisa listar o header (controle de Vary no CloudFront ou Fastly) e o suporte cruza headers para descobrir qual versão atendeu cada request.

Contrato primeiro, código depois

OpenAPI como fonte única de verdade muda a dinâmica do time. O CI roda oasdiff contra a spec anterior e falha o pipeline ao detectar breaking change sem bump de versão. SDKs gerados a partir da spec ficam sincronizados com a implementação do servidor, e o mesmo documento alimenta a documentação pública. Contrato versionado no git vira histórico auditável de decisão.

Como desativar uma versão sem perder clientes?

  • Sunset header (RFC 8594) com a data de desligamento em toda resposta da versão antiga
  • Aviso de deprecação dentro do payload durante a janela de transição
  • Changelog público mais e-mail direto aos donos de cada integração
  • Piso de 6 meses de janela para B2B e 12 meses para contratos enterprise

Tráfego decide o desligamento. Logs de uso por cliente e por versão mostram quem ainda chama /v1/; o sunset acontece quando a telemetria reporta zero chamadas. Sem esses logs, você desliga na data marcada e descobre na segunda-feira que o maior cliente ainda integrava.