Webhooks de Atendimentos
Receba notificacoes em tempo real quando atendimentos mudam de status, lembretes sao enviados e profissionais ou servicos sao atualizados. Cada evento e entregue com assinatura HMAC para verificacao de autenticidade.
Eventos disponíveis
| Evento | Descricao |
|---|---|
| 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 nao 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 |
| professional.deleted | Profissional desativado |
| service.created | Servico criado |
| service.updated | Servico atualizado |
| service.deleted | Servico desativado |
Configurar webhook
Webhooks sao configurados por conta. Use a API de webhooks ou o painel em Configuracoes → Integrações → Webhooks.
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
Na API de webhooks, use underscore: appointment_created. No payload entregue, o campo eventusa ponto: appointment.created.
Formato do payload
Todos os eventos de atendimento seguem a mesma estrutura base. O campodelivery_id e um UUID unico por entrega — use para idempotencia.
{
"event": "appointment.confirmed",
"occurred_at": "2026-06-15T08:05:00Z",
"delivery_id": "550e8400-e29b-41d4-a716-446655440000",
"account_id": 1,
"data": {
"appointment": {
"id": 47,
"public_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "confirmed",
"scheduled_at": "2026-06-15T09:00:00Z",
"ends_at": "2026-06-15T10:00:00Z",
"price_cents": 25000,
"currency": "BRL",
"contact": { "id": 42, "name": "Joao Silva" },
"professional": { "id": 3, "name": "Dra. Ana Lima" },
"service": { "id": 7, "name": "Consulta Inicial" }
},
"previous_changes": {
"status": ["scheduled", "confirmed"]
}
}
}Para appointment.rescheduled, o campodata.previous_scheduled_at contem o horario anterior. Para appointment.cancelled, contemdata.cancellation_reason.
Verificar assinatura HMAC
Cada requisicao webhook inclui o headerX-Noovichat-Signaturecom HMAC-SHA256 do body usando o segredo configurado no webhook. Sempre valide a assinatura antes de processar o evento.
const crypto = require('crypto');
function verifyWebhookSignature(req, secret) {
const signature = req.headers['x-noovichat-signature'];
if (!signature) return false;
const body = JSON.stringify(req.body); // use raw body, not re-serialized
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// 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);
console.log('Evento recebido:', event.event, event.delivery_id);
// Processar evento...
res.json({ ok: true });
});Retentativas e idempotencia
| Tentativa | Delay | Condicao de abandono |
|---|---|---|
| 1a | Imediata | — |
| 2a | 1 minuto | Retorna 2xx na 1a |
| 3a | 10 minutos | Retorna 2xx na 2a |
| 4a | 1 hora | Retorna 2xx na 3a |
| 5a | 6 horas | Retorna 2xx na 4a |
Use delivery_id para idempotencia
O mesmo evento pode ser entregue mais de uma vez em caso de retentativa. Salve o delivery_id processado e ignore duplicatas baseando-se nele, nao noappointment.id.