Webhooks de Atendimentos
Receba notificações em tempo real quando atendimentos mudam de status, lembretes são enviados e profissionais ou serviços são atualizados. Cada evento é entregue com assinatura HMAC para verificação de autenticidade.
Eventos disponíveis
| Evento | Descrição |
|---|---|
| appointment.created | Novo atendimento agendado |
| appointment.updated | Dados do atendimento atualizados |
| appointment.confirmed | Atendimento confirmado |
| appointment.completed | Atendimento marcado como realizado |
| appointment.cancelled | Atendimento cancelado |
| appointment.no_show | Paciente não compareceu |
| appointment.rescheduled | Reagendamento realizado |
| reminder.sent | Lembrete enviado com sucesso |
| reminder.failed | Falha no envio do lembrete |
| professional.created | Profissional criado |
| professional.updated | Profissional atualizado |
| service.created | Serviço criado |
| service.updated | Serviço atualizado |
Configurar webhook
Webhooks são configurados por conta. Use a API de webhooks ou o painel em Configurações → Integrações → Webhooks. A API exige token de usuário administrador da conta.
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/webhooks" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhook": {
"url": "https://seu-servidor.com/noovichat-webhook",
"subscriptions": [
"appointment.created",
"appointment.confirmed",
"appointment.cancelled",
"appointment.completed",
"appointment.no_show",
"appointment.rescheduled",
"reminder.sent",
"reminder.failed"
]
}
}'Nomes de evento nos webhooks
Use os nomes canônicos com ponto tanto em subscriptions quanto no campo event entregue, por exemplo appointment.created.
Formato do payload
Eventos de atendimento enviam os campos do atendimento no nível raiz. O identificador estável da entrega vem no header X-Chatwoot-Delivery, não no corpo.
{
"event": "appointment.confirmed",
"id": 47,
"public_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"account_id": 1,
"contact_id": 42,
"professional_id": 3,
"service_id": 7,
"scheduled_at": "2026-06-15T09:00:00Z",
"ends_at": "2026-06-15T10:00:00Z",
"status": "confirmed",
"notes": null,
"price_cents": 25000,
"currency": "BRL",
"cancellation_reason": null,
"created_at": "2026-06-01T09:30:00Z",
"updated_at": "2026-06-15T08:05:00Z"
}Para appointment.rescheduled, o campoprevious_scheduled_at contém o horário anterior.appointment.updated acrescenta changed_attributes. Eventos de lembrete, profissional e serviço usam payloads menores e específicos ao evento.
Verificar assinatura HMAC
Cada requisição assinada inclui X-Chatwoot-Timestampe X-Chatwoot-Signature. A assinatura tem o formato sha256=<hex> e é calculada com HMAC-SHA256 sobre timestamp.raw_body. Sempre valide a assinatura antes de processar o evento.
const crypto = require('crypto');
function verifyWebhookSignature(req, secret) {
const timestamp = req.headers['x-chatwoot-timestamp'];
const signature = req.headers['x-chatwoot-signature'];
if (!timestamp || !signature || !Buffer.isBuffer(req.body)) return false;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(timestamp + '.')
.update(req.body)
.digest('hex');
const receivedBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expected);
return receivedBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(receivedBuffer, expectedBuffer);
}
// Express handler
app.post('/noovichat-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const secret = process.env.NOOVICHAT_WEBHOOK_SECRET;
if (!verifyWebhookSignature(req, secret)) {
return res.status(401).json({ error: 'invalid signature' });
}
const event = JSON.parse(req.body.toString('utf8'));
const deliveryId = req.headers['x-chatwoot-delivery'];
console.log('Evento recebido:', event.event, deliveryId);
// Processar evento...
res.json({ ok: true });
});Retentativas e idempotência
Falhas de entrega usam o backoff polinomial do job, com limite de três tentativas. A outbox durável também pode reenfileirar uma entrega pendente; por isso, não dependa de intervalos fixos nem trate uma repetição como um novo evento.
Use X-Chatwoot-Delivery para idempotência
O mesmo evento pode ser entregue mais de uma vez em caso de retentativa. Salve o valor do header X-Chatwoot-Deliverye ignore duplicatas baseando-se nele, não noappointment.id.