Os webhooks ficam na tela Integrações, no menu lateral, grupo Conta (endereço
/integracoes), na seção Webhooks.
Cada endpoint recebe os eventos escolhidos, assinados com HMAC-SHA256.
Webhooks estão disponíveis nos planos Pro e Full. O formulário nasce desabilitado com "O plano Grátis não inclui os webhooks de saída" e um botão Solicitar upgrade, que abre um e-mail para a Data Stone já com o seu plano atual e o recurso pedido preenchidos — o bloqueio aparece antes de você preencher qualquer campo, não depois de clicar em salvar. Se o plano mudar com a tela aberta, o servidor ainda recusa com "Webhooks estão disponíveis nos planos Pro e Full.". Só o dono e os administradores da conta cadastram endpoints.

Cadastrar um endpoint
- Em URL do endpoint, informe o destino (ex.:
https://seusistema.com/webhooks/datalead). - Em Descrição (opcional), um rótulo para você (ex.:
ERP interno), até 120 caracteres. - Em Eventos, marque pelo menos um.
- Clique em Adicionar endpoint.
O segredo aparece uma única vez
Logo após a criação, a tela mostra:
Copie agora: ele não será exibido de novo.
O segredo começa com whsec_ e é o que você usa para verificar a assinatura de cada entrega.
Guarde-o num cofre de segredos: o Data Lead guarda apenas a versão cifrada e não há tela que
consiga exibi-lo de novo. Se você perder o segredo, exclua o endpoint e cadastre outro.
URLs recusadas
O cadastro (e cada entrega) recusa destinos que não sejam endpoints públicos de cliente:
| Recusa | Motivo |
|---|---|
URL sem https |
"URL de webhook precisa usar https" |
| Porta diferente de 443/80 | "URL de webhook precisa usar a porta padrão (443)" |
URL com usuário e senha (https://user:senha@host) |
"URL de webhook não pode carregar usuário e senha" |
localhost, .internal e nomes internos |
"URL de webhook aponta para um host interno" |
Endereços de rede privada (10/8, 169.254/16, …) |
"URL de webhook aponta para um endereço de rede privada" |
No formulário, qualquer um desses casos aparece como "Informe uma URL https pública (endereços internos não são aceitos)".
A validação é refeita a cada entrega, inclusive resolvendo o nome: um domínio público que passe a apontar para um endereço interno é recusado na hora do envio. Redirecionamentos não são seguidos — cadastre a URL final.
Os eventos
| Evento | Rótulo na tela | Quando dispara |
|---|---|---|
lead.created |
Lead criado | O lead foi persistido |
lead.qualified |
Lead qualificado | O desfecho da conversa virou qualificado |
meeting.booked |
Reunião marcada | O agente marcou a reunião |
handoff.requested |
Handoff para WhatsApp | O visitante seguiu para o WhatsApp |
Um endpoint ativo que assine
lead.createdoulead.qualifiedconta como destino do lead: a partir daí o Data Lead para de mandar o aviso de lead novo por e-mail. Um endpoint que só assinameeting.bookedouhandoff.requestednão conta — ele não recebe o lead.
O corpo da entrega
Um POST com corpo JSON:
{
"id": "lead_qualified:5f1c…:webhook:9a2b…",
"type": "lead.qualified",
"created_at": "2026-09-05T12:00:00.000Z",
"data": {
"leadId": "5f1c8b0e-9d2a-4a11-9a0e-2c6d1f3b7e40",
"conversationId": "c2b0f6a1-3d4e-4f52-8b77-9e1a5c0d2f31",
"score": 82,
"siteId": "1e7a4c33-5b90-4a2f-9c18-6d5e0b7a1234",
"createdAt": "2026-09-05T11:59:58.412Z"
}
}
Sem dados pessoais, de propósito: só identificadores, score e site. Quem precisa do contato busca o lead pela API pública — mesmo lá, o contato vem mascarado.
Cabeçalhos de cada entrega:
| Cabeçalho | Conteúdo |
|---|---|
X-DataLead-Signature |
t=<epoch em segundos>,v1=<HMAC-SHA256 em hexadecimal> |
X-DataLead-Id |
O mesmo id do corpo — guarde e ignore repetidos |
X-DataLead-Event |
O type do evento |
User-Agent |
DataLead-Webhooks/1 |
Verificar a assinatura
A assinatura é o HMAC-SHA256 do texto <timestamp>.<corpo cru>, com o segredo whsec_… como
chave. Ela vale por uma janela de 5 minutos: compare o t com o seu relógio e recuse fora
dela — é isso que impede alguém de reenviar uma entrega antiga capturada.
Use o corpo cru. Reserializar o JSON já convertido em objeto muda espaços e ordem de chaves, e a assinatura não fecha.
Node
import { createHmac, timingSafeEqual } from "node:crypto";
export const verificar = (body, header, secret, toleranciaSegundos = 300) => {
const match = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(String(header ?? "").trim());
if (!match) return false;
const [, ts, assinatura] = match;
if (Math.abs(Math.floor(Date.now() / 1000) - Number(ts)) > toleranciaSegundos) return false;
const esperado = createHmac("sha256", secret).update(`${ts}.${body}`).digest("hex");
return timingSafeEqual(Buffer.from(esperado, "hex"), Buffer.from(assinatura, "hex"));
};
// Express:
// app.post("/hook", express.raw({ type: "application/json" }), (req, res) => {
// const corpo = req.body.toString("utf8");
// if (!verificar(corpo, req.get("X-DataLead-Signature"), process.env.DATALEAD_WEBHOOK_SECRET)) {
// return res.sendStatus(400);
// }
// const evento = JSON.parse(corpo);
// // Idempotência: guarde req.get("X-DataLead-Id") e ignore repetidos.
// res.sendStatus(204);
// });
PHP
<?php
function datalead_verificar(string $body, ?string $header, string $secret, int $tolerancia = 300): bool {
if ($header === null || !preg_match('/^t=(\d+),v1=([0-9a-f]{64})$/', trim($header), $m)) {
return false;
}
[, $ts, $assinatura] = $m;
if (abs(time() - (int) $ts) > $tolerancia) {
return false;
}
$esperado = hash_hmac('sha256', $ts . '.' . $body, $secret);
return hash_equals($esperado, $assinatura);
}
$body = file_get_contents('php://input'); // corpo CRU, sem json_decode antes
$header = $_SERVER['HTTP_X_DATALEAD_SIGNATURE'] ?? null;
if (!datalead_verificar($body, $header, getenv('DATALEAD_WEBHOOK_SECRET'))) {
http_response_code(400);
exit;
}
$evento = json_decode($body, true);
// Idempotência: guarde $_SERVER['HTTP_X_DATALEAD_ID'] e ignore repetidos.
http_response_code(204);
hash_equals (PHP) e timingSafeEqual (Node) comparam em tempo constante. Uma comparação com
== ou === vazaria, byte a byte, quanto da assinatura um atacante já acertou.
Responder à entrega
Responda com qualquer status 2xx — o corpo da sua resposta é ignorado. Cada tentativa espera no máximo 5 segundos pela sua resposta; acima disso a entrega é marcada como tempo limite.
Nem toda falha é repetida. A fila só insiste quando o problema parece temporário — 5xx, 429 ou tempo limite: espera crescente (1 min, 2, 4, 8… até 24 h), somando 14 tentativas ao longo de cerca de 82 horas. Um 4xx (401, 403, 404 ou qualquer outro erro de requisição) falha na primeira tentativa: é um problema do seu lado que repetir não resolve. Nos dois casos a linha fica como Falhou no log e pode ser reenviada manualmente.
Dez falhas consecutivas desativam o endpoint (contagem por endpoint, independente das tentativas de cada entrega) e o dono da conta recebe um e-mail com o assunto "Um webhook do Data Lead parou de responder". Conserte o destino e clique em Ativar.
Testar, ativar e excluir
Cada endpoint da lista traz:
- Enviar teste — enfileira um evento
lead.createdde teste, com"teste": truenodata. O aviso é "Enviamos um evento de teste. O resultado aparece no log em alguns segundos." O endpoint precisa estar ativo; desativado, a tela diz "Ative o endpoint para testar." - Desativar / Ativar — para de receber eventos sem perder o cadastro nem o histórico.
- Excluir — definitivo: "Os eventos param de ser enviados para esta URL na hora, e não há como desfazer."
Quando há falhas, a linha mostra "3 falha(s) consecutiva(s) — último HTTP 500."
Log de entrega
O bloco Log de entrega lista uma linha por tentativa, da mais recente para a mais antiga: Quando, Tipo, Tentativa, Status (Entregue ou Falhou), HTTP, Duração e Erro.
O botão Reenviar aparece apenas na tentativa mais recente de uma entrega que falhou de vez. Ele reabre a mesma entrega, zerando as tentativas: "Reenviado. O resultado aparece no log em instantes."
Se a listagem falhar, a tela avisa explicitamente que as entregas continuam acontecendo — só a listagem falhou.
Um destino recusado pela política de rede aparece no log sem status HTTP e com a mensagem genérica: informar o endereço resolvido transformaria o log numa ferramenta de varredura de rede.

Veja também
Precisa de ajuda?
Fale com o suporte da Data Stone pelo canal combinado com a sua conta.
Tenha à mão a URL do endpoint e o X-DataLead-Id da entrega (nunca envie o segredo whsec_…).