Rascunho
Webhooks
Eventos assinados de agendamentos, pagamentos e conversas, com reenvio automático.
Eventos
| Evento | Quando |
|---|---|
booking.created | Uma pré-reserva ou agendamento foi criado |
booking.confirmed | Um agendamento foi confirmado (inclusive após o pagamento) |
booking.cancelled | Cancelado ou expirado |
booking.rescheduled | Mudou de horário (o payload traz o id antigo e o novo) |
booking.no_show | Marcado como falta |
payment.paid | Um sinal via Pix foi recebido |
message.received | Chegou uma mensagem de cliente |
conversation.handoff | Uma conversa foi passada para uma pessoa |
Crie endpoints em Desenvolvedores → Webhooks ou via POST /v1/webhook-endpoints. O segredo de assinatura aparece uma única vez.
Payload
{
"id": "evt_01J9ZK3T6",
"type": "booking.confirmed",
"created_at": "2026-10-14T15:21:07-03:00",
"workspace_id": "ws_9f2c",
"data": { "booking": { "id": "bkg_7Qx1", "status": "confirmed", "start": "2026-10-15T09:45:00-03:00" } }
}
A entrega é pelo menos uma vez: use o id para ignorar duplicados.
Verificando a assinatura
Toda requisição traz o header:
Wagend-Signature: t=1791040867,v1=5c2b9f...e81
v1 é HMAC-SHA256(segredo, t + "." + corpo_bruto) em hexadecimal. Rejeite requisições com mais de 5 minutos.
import crypto from 'node:crypto'
export function verifyWagend(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=') as [string, string]))
const age = Math.abs(Date.now() / 1000 - Number(parts.t))
if (!parts.t || !parts.v1 || age > 300) return false
const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex')
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
}
import hashlib, hmac, time
def verify_wagend(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts.get("t", "0"))) > 300:
return False
signed = f"{parts['t']}.".encode() + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))
Reenvios
Responda com qualquer 2xx em até 10 segundos. Caso contrário, tentamos de novo após 1 min, 5 min, 30 min, 2 h e 12 h. Cada tentativa aparece no log de entregas, onde você também pode reenviar manualmente.