Receba eventos por webhook

Assine eventos do catálogo, verifique a assinatura e responda a tempo.

GuiaCom aprovaçãoChave secreta
Antes de começar. Criar webhooks pede uma chave secreta com a permissão webhooks:write, aprovada pelo suporte: peça em Configurações › API Keys.

Crie a assinatura

A resposta traz o secret com que as entregas são assinadas. Aparece uma só vez: guarde-o.

cURL
curl -X POST https://api.bydomu.com/v1/webhooks \
  -H "X-API-Key: $BYDOMU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://tu-servidor.com/webhooks/bydomu",
    "eventTypes": ["deal.won", "contact.*"],
    "description": "Negocios ganados y contactos"
  }'
Resposta · 201 · exemplo
{
  "data": { "id": "clx1whk001", "secret": "whsec_…" }
}

Verifique a assinatura

Cada entrega leva X-Domu-Signature: t=…,v1=…: o HMAC-SHA256 de «timestamp.corpo» com seu secret. Use o corpo cru, compare em tempo constante e rejeite marcas de tempo antigas.

Node.js
import { createHmac, timingSafeEqual } from "node:crypto";

// header = X-Domu-Signature: t=<timestamp>,v1=<hmac>
function verifyWebhook(rawBody, header, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const timestamp = Number(parts.t);
  if (!timestamp || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSec) return false;
  const expected = createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1);
  return a.length === b.length && timingSafeEqual(a, b);
}

Responda a tempo

Até 5 tentativas (0 s, 5 s, 30 s, 2 min e 10 min) em erro de rede, 429 ou 5xx. Responda 2xx em menos de 10 s.

O id de cada entrega é estável: use-o para descartar as repetidas.

Entrega · exemplo
{
  "id": "5f3a0c1e-7d2b-4f7e-9a51-0b6c1d2e3f40",
  "type": "deal.won",
  "timestamp": "2026-09-22T14:30:00.000Z",
  "organizationId": "clx1org001",
  "actor": { "kind": "API", "userId": null },
  "data": { … }
}