Skip to main content
Webhooks são requisições HTTP POST que a Timely.ai envia automaticamente para a URL que você configurar sempre que um evento relevante acontece no seu workspace. Em vez de ficar fazendo polling na API, você recebe os dados na hora — sem latência, sem desperdício de requisições.

Por que usar webhooks

Com webhooks você consegue:
  • Sincronizar seu CRM toda vez que um contato novo entrar ou uma conversa mudar de status
  • Disparar automações externas (Make, n8n, Zapier, seu próprio backend) em resposta a eventos
  • Alimentar dashboards de BI com dados em tempo real
  • Integrar sistemas de atendimento próprios recebendo mensagens assim que chegam
  • Monitorar saúde dos canais quando uma conexão cai ou apresenta erro

Como funciona

1

Você registra um endpoint

Cria um webhook no dashboard ou via API informando a URL do seu servidor e quais categorias de eventos quer receber.
2

Um evento acontece

Um contato envia uma mensagem, uma conversa é fechada, um agendamento é criado — qualquer coisa que você subscreveu.
3

A Timely.ai faz um POST

Enviamos um POST com o payload JSON do evento para a sua URL, com o header X-Timely-Signature para você validar a autenticidade.
4

Você responde 2xx

Seu servidor precisa responder com qualquer status 2xx em até 10 segundos. Se não responder, iniciamos as retentativas.

Desenvolvimento vs Produção

Em dev, use uma ferramenta como ngrok ou Hookdeck para expor seu servidor local com HTTPS:
ngrok http 3000
# Forwarding: https://abc123.ngrok.io -> localhost:3000
Configure https://abc123.ngrok.io/webhooks/timely como URL no dashboard. Lembre de atualizar sempre que reiniciar o ngrok.
O endpoint POST /v1/webhooks/{id}/test envia um evento de teste sem precisar gerar um real no workspace.

Segurança: validação HMAC

Cada entrega inclui o header X-Timely-Signature com o formato sha256=HEX. Esse valor é o HMAC-SHA256 do body da requisição usando o secret gerado no momento da criação do webhook. Nunca ignore a validação. Qualquer servidor na internet poderia postar dados falsos na sua URL se você não verificar a assinatura.
import crypto from "crypto";
import { Request, Response } from "express";

const WEBHOOK_SECRET = process.env.TIMELY_WEBHOOK_SECRET!;

export function verifySignature(req: Request, res: Response, next: Function) {
  const signature = req.headers["x-timely-signature"] as string;
  const rawBody = (req as any).rawBody as Buffer; // body-parser com verify

  if (!signature || !rawBody) {
    return res.status(401).json({ error: "Missing signature" });
  }

  const expected = "sha256=" + crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(rawBody)
    .digest("hex");

  const isValid = crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );

  if (!isValid) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  next();
}
Use sempre crypto.timingSafeEqual (ou equivalente na sua linguagem) para comparar as assinaturas. Comparação direta com == é vulnerável a timing attacks.

Retentativas automáticas

Se a sua URL não responder 2xx dentro de 10 segundos, a Timely.ai retenta automaticamente com backoff exponencial:
TentativaAguarda antes de retentar
1ª falha5 segundos
2ª falha15 segundos
3ª falha60 segundos
4ª falha5 minutos
5ª falha15 minutos
Depois de 5 falhas consecutivas, o webhook é marcado como failing e você recebe um email de alerta. O webhook continua ativo — novos eventos continuam sendo enfileirados — mas você precisa verificar o endpoint antes que mais entregas falhem.
Consulte o histórico de entregas no endpoint GET /v1/webhooks/{id}/deliveries para ver o status de cada tentativa, o código HTTP retornado e o tempo de resposta.

Como criar um webhook

  1. Acesse Configurações → Webhooks no menu lateral
  2. Clique em Novo webhook
  3. Informe a URL de destino e selecione os eventos que quer receber
  4. Copie o secret gerado — ele aparece apenas uma vez
  5. Salve e use o botão Testar para validar a entrega

Boas práticas

Responda rapido

Retorne 200 OK imediatamente e processe o evento de forma assíncrona (fila, worker, task). Nunca faça chamadas de banco ou APIs de terceiros antes de responder.

Idempotência por event_id

Todo payload inclui um campo event_id único. Armazene os IDs processados e ignore duplicatas — retentativas podem re-entregar o mesmo evento.

Secret em cofre

Nunca exponha o secret em variáveis de ambiente não criptografadas em CI, logs ou código-fonte. Use um secret manager dedicado.

Monitore falhas

Configure alertas no seu lado também. Use GET /v1/webhooks/{id}/deliveries periodicamente ou integre com seu sistema de observabilidade.

Categorias de eventos

Veja a documentação detalhada de cada categoria de evento:

Conversas

conversation.created, .assigned, .closed, .reopened

Mensagens

message.received, .sent, .failed, .delivered, .read

Contatos

contact.created, .updated, .deleted

Agente

agent.handoff_started, .handoff_completed, .transferred

Agendamentos

appointment.scheduled, .rescheduled, .canceled, .reminder_sent

Canais

channel.connected, .disconnected, .error

Billing

credit.low, .depleted, plan.changed, trial.expiring, .expired