Assinatura HMAC
Cada entrega é assinada com o signingSecret do webhook. Valide antes de confiar no payload.
Entrega garantida
Retentativa com backoff e at-least-once. Eventos ficam em GET /events para reenvio sob demanda.
Anti-loop
Após tentativas esgotadas de forma recorrente, o webhook é suspenso e você é avisado por e-mail.
Auditável
Todo evento é consultável, com status de entrega e último código HTTP retornado.
1. Ative os webhooks
Ative no dashboard (Configurações → Integrações → Webhooks) ou via API. Informe a URL de destino e os eventos que quer receber. Você recebe um signingSecret — exibido uma única vez — para validar as entregas.
curl -X POST https://app.xuru.com.br/api/v1/webhooks \
-H "X-API-Key: xuru_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://seu-sistema.com/webhooks/xuru",
"events": ["patient.updated", "order.status_changed", "stock.updated"]
}'
# resposta (o signingSecret aparece uma única vez)
# { "success": true, "data": { "id": "whk_...", "signingSecret": "whsec_...", "status": "enabled" } }2. Catálogo de eventos
| Evento | Disparado quando |
|---|---|
patient.updated | Um paciente é criado ou atualizado |
order.status_changed | O status de um pedido muda |
stock.updated | O estoque de um produto é alterado |
3. Formato da entrega
A Xuru faz um POST na sua URL com o corpo do evento e os seguintes headers:
| Header | Conteúdo |
|---|---|
X-Xuru-Event-Id | ID único do evento. Use para deduplicação. |
X-Xuru-Signature | HMAC-SHA256 do corpo, assinado com o signingSecret. |
X-Xuru-Timestamp | Instante do envio (epoch em segundos). |
X-Xuru-Delivery-Attempt | Número da tentativa de entrega. |
POST /webhooks/xuru HTTP/1.1
X-Xuru-Event-Id: evt_2a9f1c...
X-Xuru-Signature: 7b2d8f... # HMAC-SHA256(corpo, signingSecret)
X-Xuru-Timestamp: 1781430000
X-Xuru-Delivery-Attempt: 1
Content-Type: application/json
{
"id": "evt_2a9f1c...",
"type": "order.status_changed",
"createdAt": "2026-06-10T12:00:00Z",
"data": { "id": "ord_8h2k...", "status": "PAID" }
}4. Verifique a assinatura
Calcule o HMAC-SHA256 do corpo bruto com o seu signingSecret e compare, em tempo constante, com o header X-Xuru-Signature. Rejeite a requisição se não bater.
# Recalcule a assinatura a partir do corpo BRUTO e compare em tempo constante.
# Node.js
import crypto from "node:crypto";
function isValid(rawBody, signature, signingSecret) {
const expected = crypto
.createHmac("sha256", signingSecret)
.update(rawBody, "utf8")
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
# Shell (conferência rápida)
printf '%s' "$RAW_BODY" | openssl dgst -sha256 -hmac "$SIGNING_SECRET"5. Retentativa e garantia de entrega
Sucesso = seu endpoint responde 2xx em até 10 segundos. Em caso de falha ou timeout, a Xuru tenta novamente com backoff exponencial:
| Tentativa | Após |
|---|---|
| 1 | Imediata |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
| 6 | 6 horas |
| 7 | 24 horas |
- At-least-once: o mesmo evento pode chegar mais de uma vez. Deduplique sempre pelo
X-Xuru-Event-Id. - Anti-loop: após esgotar as tentativas de forma recorrente, o webhook é suspenso automaticamente e você recebe um e-mail.
- Reprocessamento: reative com
PATCH /webhooks/{id}e reenvie comPOST /events/{id}/redeliver.
6. Rate limits
As requisições à API são limitadas por organização — cada resposta traz os headers X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset, e ao exceder você recebe 429 com Retry-After. A entrega de webhooks também respeita uma vazão máxima por endpoint, para nunca sobrecarregar o seu sistema.