Política de versão
Quatro perguntas, respondidas por escrito: o que consideramos mudança que quebra, quanto tempo uma versão fica no ar, como avisamos uma depreciação e o que assumimos como compromisso. O que já mudou de fato está no changelog.
Escrevemos aqui só o que conseguimos cumprir com o time de hoje. Promessa de suporte longo sem gente para honrar é pior que não prometer nada, então a última seção diz, com todas as letras, o que ainda não fazemos.
Onde vive a versão
A versão do contrato HTTP está no caminho: /v1. Não existe cabeçalho de versão, e a sua integração não escolhe versão por requisição. Enquanto a URL começar com /v1, valem as regras desta página.
A versão do envelope do evento
O caminho versiona a API. O corpo do webhook versiona a si mesmo: todo evento sai com schema_version, hoje 1, logo depois do id. Ele descreve a forma do envelope, não o conteúdo da verificação.
Esse número não sobe por adição compatível. Campo novo no corpo, módulo novo em check_details e valor novo num enum de saída continuam com schema_version: 1, porque a lista logo acima já obriga a sua integração a tolerar essas três coisas. Ele sobe quando um campo muda de tipo ou de significado, e isso, pela lista de baixo, também exige /v2: os dois marcadores andam juntos de propósito, e é por isso que você nunca vai precisar decidir qual dos dois seguir.
Na prática, para quem integra: leia o campo, registre o valor no seu log e trate um número maior que o esperado como sinal de que existe uma versão nova de caminho para migrar. Não recuse o evento por causa dele: enquanto o número for 1, o corpo é o mesmo que você já sabe ler.
Como entregamos: pelo menos uma vez
Isto não é uma promessa nova, é o registro por escrito do que a plataforma sempre fez. Você vai receber o mesmo evento mais de uma vez em algum momento, e isso não é defeito: é o preço de nunca perder um desfecho. O que garantimos é a entrega, não a unicidade dela, e é por isso que o id do evento é estável, para servir de chave de deduplicação no seu lado.
- Entregamos pelo menos uma vez. O mesmo evento pode chegar mais de uma vez, e o seu endpoint precisa ser idempotente.
- Deduplique pelo campo id do evento (evt_...). Ele é estável por verificação e por tipo de evento, então toda retentativa do mesmo evento repete o mesmo id.
- Reemissão manual (decisão revista no painel) e replay self-service chegam com id NOVO de propósito, para você conseguir distinguir. Trate como upsert pelo verification_id.
- Uma entrega só é considerada aceita quando o seu endpoint responde 2xx. Timeout, erro de rede ou 5xx contam como falha e entram na retentativa.
- São até 3 tentativas, com espera crescente entre elas (cerca de 15 minutos do primeiro disparo à última). Depois disso o resgate é o replay, que você dispara quando o seu sistema voltar.
- Resposta 4xx DE CONTRATO (400, 401, 403, 404, 405, 410 e 422) é lida como recusa definitiva daquele destino e não gera novas tentativas: o corpo não vai mudar se o problema é o pedido. Corrija e use o replay.
- As duas exceções entre os 4xx são as que um receptor sob carga devolve: 408 e 429 contam como falha TRANSITÓRIA e entram na retentativa normalmente. Se você limita taxa no seu endpoint, prefira 429 a 403.
- Resposta 3xx NÃO é entrega e NÃO é seguida: nós fazemos um POST na URL cadastrada e paramos ali. Redirecionar o destino (inclusive de http para https, ou de com barra final para sem) faz o evento parar de chegar, e a tentativa fica registrada com o status 301 ou 302 para você ver em GET /v1/webhook-events. Quem conserta isso é o cadastro da URL, não o retry.
- A entrega repetida é assinada NA HORA do envio, com timestamp novo sobre o mesmo corpo, então a sua validação de assinatura e a sua janela anti-replay continuam passando.
- O corpo do evento carrega schema_version, a versão da forma do envelope. Campo novo não muda esse número; mudança de tipo ou de significado muda, e nesse caso já existiria uma versão nova de caminho.
A consequência prática é uma só: o seu endpoint precisa ser idempotente. Guarde o id já processado e ignore a repetição, ou trate todo evento como um upsert pelo verification_id. Quem processa webhook sem isso credita duas vezes, aprova duas vezes, ou dispara dois e-mails, no primeiro dia em que a rede engasgar.
O que é adição compatível
Estas mudanças entram em /v1 a qualquer momento, sem aviso prévio. A sua integração é obrigada a tolerá-las. Na prática isso significa: não quebre em campo desconhecido no JSON, não trate valor de enum desconhecido como erro fatal, não valide a resposta contra um esquema fechado, e não dependa da ordem das propriedades de um objeto.
- Endpoint novo, ou módulo novo no catálogo.
- Campo novo na resposta ou no corpo do webhook.
- Parâmetro opcional novo no request.
- Tipo de evento novo no webhook.
- Valor novo em um enum de SAÍDA (um status novo, um módulo novo em check_details, um motivo novo).
- Item novo dentro de um array já existente.
- Reordenação das propriedades de um objeto JSON.
- Mudança de tamanho ou de formato de uma string opaca (id, token, prefixo de chave).
O que é mudança que quebra
Estas nunca entram em /v1. Se um dia forem necessárias, elas exigem um caminho novo, /v2, e a versão antiga continua respondendo do jeito que sempre respondeu enquanto estiver no ar.
- Remover ou renomear endpoint, parâmetro, header, campo de resposta ou módulo.
- Mudar o tipo de um campo.
- Exigir campo novo no request, ou criar validação que recusa um request antes válido.
- Mudar o código de status HTTP de um caso já documentado.
- Mudar o SIGNIFICADO de um campo mantendo o nome dele.
- Remover um valor aceito em um enum de ENTRADA.
- Mudar a exigência de autenticação de uma rota.
Duas exceções, pelo mesmo motivo que o mercado inteiro as abre: mudança em respostas 5xx e em 404 de recurso inexistente não conta como quebra, porque são justamente os casos em que o contrato não estava sendo cumprido.
Quanto tempo uma versão fica no ar
Aviso de 90 dias antes de uma versão nova entrar no ar, e 12 meses de convivência entre a nova e a antiga contados a partir do lançamento. Passado esse prazo, a versão antiga responde 410, e não um erro genérico: você recebe uma resposta que diz exatamente o que aconteceu.
| Se a /v2 entrasse no ar em | Então |
|---|---|
| 2026-10-03 | o aviso já estaria publicado no changelog, 90 dias antes. |
| 2027-01-01 | a /v2 entra no ar e a /v1 continua funcionando igual. |
| 2028-01-01 | a /v1 sai do ar e passa a responder 410. |
Como avisamos uma depreciação
Depreciação é anúncio com data de saída. Ela aparece no changelog classificada como Depreciação, com o dia em que o comportamento antigo sai do ar, e no feed /docs/changelog.json no campo sunset_on daquele item, para o seu monitoramento enxergar sem depender de alguém ler esta página. O painel também traz o aviso, mas o registro que vale é o changelog: o painel é lido por uma pessoa, e integração não é gente.
A exceção de segurança
Correção de vulnerabilidade entra em /v1 na hora, sem janela de aviso, mesmo que altere comportamento observável. Ela é registrada no changelog como Correção logo em seguida. Essa exceção existe para a promessa desta página não virar algema no meio de um incidente: entre cumprir o prazo e fechar um buraco que expõe dado de cliente, a gente fecha o buraco.
O que assumimos
- Mudança que quebra nunca entra em /v1. Ela exige um caminho novo, /v2.
- Antes de /v2 entrar no ar, o aviso sai aqui no changelog com 90 dias de antecedência.
- /v1 e /v2 convivem por 12 meses contados do dia em que /v2 entra no ar. Depois disso, /v1 responde 410.
- Depreciação é anunciada nesta página com a data de saída, nunca só por e-mail.
- Correção de vulnerabilidade entra em /v1 na hora, sem janela de aviso, e é registrada aqui como Correção logo em seguida.
- Toda entrada deste changelog só entra com a prova da data conferida no nosso repositório. Esta página publica o que mudou, não o mapa do nosso código.
O que ainda não fazemos
Publicado porque a ausência declarada vale mais que a promessa vaga. Se algum destes itens for decisivo para você, diga: prioridade se muda com demanda real.
- Escolher a versão por request (cabeçalho de versão). Somos versionados por caminho, e cabeçalho por request é trabalho de plataforma madura. Está na fila como P2.
- Versão nomeada por mês, canal de preview e janela de rollback de 72 horas.
- Suporte de 24 meses a uma versão antiga. Não temos time para manter duas superfícies por tanto tempo.
Onde isso aparece no contrato
A cláusula 2.4 dos Termos de Uso fixa 30 dias de antecedência para mudança que altere de forma relevante o comportamento observável da API, anunciada neste changelog público e por aviso no painel, e diz que mudança que quebra integração existente não entra em /v1. São 30 dias porque é o mesmo prazo que os Termos já usam para alteração de preço de módulo e para o plano gratuito. Os 90 dias desta página são um prazo maior, e valem para o caso mais pesado de todos: colocar uma versão nova no ar.