POST na sua URL com o evento em
JSON. É assim que você sabe que o PIX caiu sem ficar consultando a API.
Duas configurações diferentes
URLs da conta, no painel
Até cinco, configuradas em API e
Desenvolvedores. São o destino padrão de
todo evento da conta.Se você só quer um endereço para tudo, configure uma e ignore o resto.
callbackUrl, por cobrança
Você manda no corpo da requisição ao criar. Vale só para aquela cobrança, e
tem prioridade sobre as URLs da conta.Use quando cobranças diferentes precisam avisar sistemas diferentes.
As duas não somam: quando a cobrança tem
callbackUrl, o evento vai só para
ela. As URLs da conta preenchem o que ficou sem destino, não duplicam o que já tem.Com mais de uma URL da conta, cada uma recebe uma cópia do evento e tem a própria
fila de reentrega. Um endereço fora do ar não atrasa nem cancela a entrega nos outros, e
a tela de entregas mostra qual deles falhou.Todas recebem a mesma assinatura e o mesmo
X-Webhook-Id. Se dois dos seus sistemas
gravam no mesmo banco, deduplique por esse header nos dois.O que cada URL precisa ter
URL inválida devolve
400 na criação da cobrança, com
callbackUrl must be a valid, public HTTPS URL. O erro vem na hora, não na entrega.
Headers
Reentrega
Se a entrega falhar (timeout, erro de rede ou status fora de2xx), o evento entra na
fila e é reenviado.
São até 7 tentativas, cobrindo pouco mais de 20 horas. O corpo reenviado é idêntico ao
original e o
X-Webhook-Id não muda.
Eventos
Todos caem nas URLs da conta. A coluna abaixo diz quem consegue desviar disso.
Em sandbox, a marca de teste entra depois do prefixo da família: os eventos de saque
saem como
withdrawal.test.requested e withdrawal.test.completed.
Pagamento de código tem família própria (pix_payment.*) em vez de reusar
withdrawal.*: quem já concilia saques não passa a receber pagamento no mesmo balde.
O identificador acompanha a família: o corpo traz paymentId, que é o mesmo
payment.id devolvido pelo pagamento.
Corpo dos eventos de contestação
Os quatrodispute.* mandam o mesmo corpo, mudando o event e o status:
previousStatus vem null na primeira vez que avisamos daquela contestação.
Use o code para casar com o que aparece no painel.
O jeito certo de tratar
1
Leia o corpo cru
Antes de qualquer parse de JSON. A assinatura é calculada sobre os bytes exatos que
chegaram.
2
Valide a assinatura
Com comparação timing-safe. Se não bater, responda
401 e pare por aí.3
Deduplique pelo X-Webhook-Id
Já processou esse id? Responda
200 e não faça nada.4
Grave e responda 200
Salve o evento e responda imediatamente. O processamento pesado vai para uma fila.
5
Confira o valor antes de entregar
amountCents precisa bater com o que você esperava. Status paid sozinho não basta.Não conte com a ordem de chegada. Se a ordem importa para você, confirme o estado atual
com um
GET na API antes de decidir.Validando a assinatura
Código pronto em Node, PHP, Python e Go.

