Skip to main content
Webhooks são requisições HTTP POST que a Cordialy envia ao seu endpoint quando eventos acontecem na plataforma. Configure em Plataforma → Integrações → Webhooks.

Estrutura do payload

Todo evento segue a mesma estrutura de envelope:
{
  "id": "evt_01HX...",
  "event": "lead.status_changed",
  "timestamp": "2026-06-20T14:30:00.000Z",
  "store_id": "uuid-da-loja",
  "data": { ... }
}
CampoTipoDescrição
idstringID único do evento — use para deduplicação
eventstringNome do evento (ver tabela abaixo)
timestampISO 8601Momento em que o evento ocorreu
store_iduuidID da loja que gerou o evento
dataobjectPayload específico do evento

Eventos disponíveis

EventoTrigger
lead.createdNovo lead criado via WhatsApp ou API
lead.status_changedStatus do lead alterado
lead.seller_assignedColaborador atribuído ao lead
message.receivedLead enviou mensagem via WhatsApp
message.sentIA, consultor ou API enviou mensagem
session.startedNova sessão de atendimento aberta
session.endedSessão de atendimento encerrada
followup.sentFollow-up automático disparado
followup.cancelledFollow-up cancelado

Payloads por evento

lead.created

{
  "id": "evt_01HX...",
  "event": "lead.created",
  "timestamp": "2026-06-20T09:00:00.000Z",
  "store_id": "...",
  "data": {
    "lead_id": "uuid",
    "name": "João Silva",
    "customer_phone": "5511999998888",
    "status": "pending",
    "seller_id": null
  }
}

lead.status_changed

{
  "event": "lead.status_changed",
  "data": {
    "lead_id": "uuid",
    "previous_status": "pending",
    "new_status": "in_progress",
    "seller_id": "uuid-ou-null"
  }
}

lead.seller_assigned

{
  "event": "lead.seller_assigned",
  "data": {
    "lead_id": "uuid",
    "seller_id": "uuid",
    "seller_name": "Ana Lima"
  }
}

message.received

{
  "event": "message.received",
  "data": {
    "lead_id": "uuid",
    "message_id": "uuid",
    "content": "Olá, quero saber o preço",
    "media_type": null,
    "media_url": null,
    "session_id": "uuid"
  }
}

message.sent

{
  "event": "message.sent",
  "data": {
    "lead_id": "uuid",
    "message_id": "uuid",
    "content": "Olá! O valor é R$ 99/mês.",
    "role": "assistant",
    "source": "whatsapp",
    "session_id": "uuid"
  }
}

session.started

{
  "event": "session.started",
  "data": {
    "lead_id": "uuid",
    "session_id": "uuid",
    "started_at": "2026-06-20T09:00:00.000Z"
  }
}

session.ended

{
  "event": "session.ended",
  "data": {
    "lead_id": "uuid",
    "session_id": "uuid",
    "status": "converted",
    "started_at": "2026-06-20T09:00:00.000Z",
    "ended_at": "2026-06-20T14:30:00.000Z",
    "message_count": 24
  }
}

followup.sent

{
  "event": "followup.sent",
  "data": {
    "lead_id": "uuid",
    "followup_id": "uuid",
    "config_id": "uuid",
    "message_sent": "Oi! Ainda tem interesse?",
    "attempt_number": 1
  }
}

Assinatura e segurança

Cada requisição inclui o header X-Cordialy-Signature com HMAC-SHA256 do payload usando seu Webhook Secret.
X-Cordialy-Signature: sha256=abc123...
Sempre valide a assinatura antes de processar o evento.
A assinatura é calculada sobre o body bruto (bytes exatos recebidos). Se você parsear o body antes de validar (ex: express.json() no Node.js ou leitura automática no framework), a assinatura não vai bater.
  • Node.js (Express): use express.raw({ type: 'application/json' }) na rota do webhook
  • PHP: use $request->getContent() (não $request->input() nem $_POST)
  • Python (FastAPI/Django): use await request.body() (não request.json())
import crypto from 'crypto';

// Na rota: app.post('/webhook', express.raw({ type: 'application/json' }), handler)
function validarAssinatura(
  rawBody: Buffer,
  signature: string,
  secret: string
): boolean {
  const esperado = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(esperado)
  );
}

Política de retry

Se seu endpoint retornar status diferente de 2xx, a Cordialy reenvia automaticamente:
TentativaDelayTotal decorrido
1ª (inicial)0s
1 minuto~1min
5 minutos~6min
30 minutos~36min
2 horas~2h36min
Após 5 tentativas sem 2xx, o evento é descartado. O histórico de entregas fica disponível no dashboard.

Requisitos do endpoint

RequisitoDetalhe
ProtocoloHTTPS obrigatório com certificado válido
TimeoutMáximo 10 segundos para retornar 2xx
MétodoSempre POST
Content-Typeapplication/json
IdempotênciaSeu handler deve tolerar eventos duplicados (use o campo id)

Testar seu endpoint

Use o dashboard em Integrações → Webhooks → Testar para enviar um evento de exemplo para o seu endpoint sem precisar gerar o evento real na plataforma.
Durante o desenvolvimento, use ferramentas como ngrok ou webhook.site para expor seu servidor local e inspecionar os payloads recebidos.