Webhooks
Em vez de fazer polling, cadastre um endpoint HTTPS e receba um POST a cada evento da sua operação — cobrança paga, acordo aceito, disputa resolvida.
Cadastro
Gerencie endpoints em Configurações → Webhooks (ou via POST /api/v1/webhook-endpoints), escolhendo os eventos assinados — lista vazia assina todos, inclusive eventos futuros. Cada recurso emite *.created, *.updated, *.deleted e eventos de ciclo de vida (charge.paid, agreement.accepted, dispute.resolved...). O catálogo completo, com payload de exemplo por evento, está em Eventos.
Entrega
Cada evento dispara um POST com o payload JSON:
POST /seu-endpoint HTTP/1.1
Content-Type: application/json
User-Agent: Kobana-Dunning-Webhooks/1.0
X-Webhook-Event: charge.paid
X-Webhook-Event-Id: 3d1f0c9a-5b2e-4c7d-9e1f-8a6b4c2d0e9f
X-Webhook-Delivery-Id: 9b2e4a10-7c3f-4d8e-a1b2-c3d4e5f60718
X-Webhook-Attempt: 1
X-Webhook-Timestamp: 2026-07-23T12:00:00.000Z
X-Webhook-Signature: t=1753272000,v1=<hmac-sha256 de "t.body" com seu secret>
{
"event": "charge.paid",
"timestamp": "2026-07-23T12:00:00.000Z",
"organizationId": "cmd8k0a1b0001ef5g",
"data": { ...recurso serializado no formato da API v1... }
}
Seu endpoint pode exigir autenticação própria (Basic, Bearer ou header custom), configurada no cadastro. Deduplique pelo X-Webhook-Event-Id (estável entre tentativas e re-envios).
Verificando a assinatura
X-Webhook-Signature vem no formato t=<unix>,v1=<hex>: v1 é o HMAC-SHA256 de "{t}.{body cru}" com o secret do endpoint. Verifique a tolerância do timestamp (recomendado: 5 minutos — anti-replay) e compare em tempo constante:
const crypto = require('crypto');
const TOLERANCE_SECONDS = 300; // 5 minutos
function verify(rawBody, signatureHeader, secret) {
const t = /(?:^|,)t=(\d+)(?:,|$)/.exec(signatureHeader || '')?.[1];
const v1 = /(?:^|,)v1=([0-9a-f]+)(?:,|$)/i.exec(signatureHeader || '')?.[1];
if (!t || !v1) return false;
if (Math.abs(Math.floor(Date.now() / 1000) - Number(t)) > TOLERANCE_SECONDS) return false;
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const a = Buffer.from(expected, 'hex');
const b = Buffer.from(v1.toLowerCase(), 'hex');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Rejeite (com 401) qualquer entrega cuja assinatura não confira.
Evento de teste
POST /api/v1/webhook-endpoints/{id}/test entrega um evento webhook.test real pelo mesmo pipeline (fila, assinatura HMAC, captura, retry) — valide o consumidor fim a fim antes do primeiro evento de negócio.
Contrato do consumidor
- Responda
2xximediatamente e processe de forma assíncrona — o timeout é de 10 segundos por tentativa. - Evento desconhecido? Responda
200e ignore — novos eventos podem passar a ser emitidos sem aviso. - Deduplique: a entrega é "pelo menos uma vez"; um
200perdido na rede gera reenvio.
Entregas com falha re-tentam 8 vezes com backoff exponencial (base 4 minutos, janela total ≈ 8h30); o histórico completo, com request e response capturados e re-envio manual, fica na página do endpoint. Detalhes do cronograma e do contrato em Entregas e retry e verificação de assinatura em Segurança.