CRPRO HubEntrar no painel

Webhooks

Cada endpoint de webhook recebe um segredo whsec_... exibido uma única vez, no momento da criação. O corpo de cada entrega é assinado sem nenhuma normalização posterior — a assinatura cobre os bytes exatos enviados.

Headers de assinatura

Toda entrega chega com três headers:

  • X-Hub-Delivery-Id — UUID único desta tentativa, usado para deduplicar.
  • X-Hub-Timestamp — o instante do envio, em segundos desde a época Unix.
  • X-Hub-Signature-256 — assinatura HMAC-SHA256 do corpo cru, formato sha256=HEX.

Verificando em Node

Calcule o HMAC do corpo cru com o segredo do endpoint e compare com timingSafeEqual, nunca com === — uma comparação de string comum vaza o tempo de execução por posição de byte, o que dá a um atacante um jeito de descobrir a assinatura correta por tentativa e erro.

verificar-assinatura.js
import { createHmac, timingSafeEqual } from 'node:crypto'
const expected = createHmac('sha256', process.env.WEBHOOK_SECRET).update(rawBody).digest('hex')
const received = request.headers['x-hub-signature-256']?.replace('sha256=', '')
const valid = !!received &&
  /^[0-9a-f]{64}$/.test(received) &&
  timingSafeEqual(Buffer.from(received, 'hex'), Buffer.from(expected, 'hex'))

Regras de recebimento

  • Leia o corpo cru antes de fazer parse de JSON — reserializar o JSON pode mudar a assinatura esperada.
  • Rejeite qualquer entrega sem o header de assinatura, ou com assinatura inválida.
  • Deduplique por X-Hub-Delivery-Id: uma retentativa reenvia o mesmo id.
  • Responda 2xx em até 10 segundos — processe o evento de forma assíncrona se demorar.

Retentativas e pausa

Uma entrega que falha (timeout, resposta fora de 2xx, erro de conexão) é reenviada até dez vezes. Depois de 20 falhas consecutivas, o endpoint pausa automaticamente — reative-o no painel depois de corrigir o que impedia o recebimento.

O que é bloqueado no destino

A URL de um endpoint de webhook passa por uma verificação de destino. São bloqueados:

  • HTTP puro — só HTTPS é aceito.
  • Redes internas (loopback, link-local e faixas privadas de IP).
  • Redirects — a entrega não segue um redirecionamento HTTP.
  • DNS privado — um domínio que resolve para um IP interno é recusado.

Modos de payload

Cada endpoint escolhe um entre dois modos de payload:

  • normalized (padrão) — envelope do CRPRO Hub: {"id", "event", "channel_id", "occurred_at", "data"}, igual para qualquer evento.
  • meta_raw — o payload bruto da Meta para o evento; sem correspondente bruto, cai de volta para normalized.
Tipos de evento hoje disponíveis: channel.createdchannel.connectedchannel.degradedchannel.disconnectedmessage.receivedmessage.sentmessage.statusmessage.echotemplate.statusphone.qualityaccount.updatewebhook.test.