Webhooks
Recibe callbacks HTTP firmados cuando cambian los tickets, desde disparadores y automatizaciones, con reintentos y registro de entregas.
Traducido para tu comodidad. El código, los nombres de campos y la referencia de la API siguen en inglés. Versión en inglés
Los webhooks envían una petición HTTP a tu endpoint cuando se activa un disparador o una automatización. Se crean en Admin Center, Integrations, Webhooks y luego se usan como acción en cualquier disparador o automatización. Los cuerpos de las peticiones pueden usar marcadores y siguen payloads con forma de Zendesk, así que los receptores hechos para webhooks de Zendesk suelen funcionar sin cambios.
Verificar la firma
Cada petición lleva dos cabeceras:
| Cabecera | Valor |
|---|---|
X-Desk-Timestamp | Hora Unix en segundos en que se firmó la petición |
X-Desk-Signature | base64(HMAC-SHA256(signing secret, timestamp + "." + raw body)) |
Calcula la firma sobre el cuerpo sin procesar de la petición, compárala en tiempo constante y rechaza las peticiones cuyo timestamp tenga más de 5 minutos.
import crypto from 'node:crypto';
export function verify(rawBody, headers, secret) {
const ts = headers['x-desk-timestamp'];
const sig = headers['x-desk-signature'];
if (!ts || !sig || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('base64');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}
function verify(string $rawBody, string $ts, string $sig, string $secret): bool
{
if (abs(time() - (int) $ts) > 300) {
return false;
}
$expected = base64_encode(hash_hmac('sha256', $ts.'.'.$rawBody, $secret, true));
return hash_equals($expected, $sig);
}
import base64, hashlib, hmac, time
def verify(raw_body: bytes, ts: str, sig: str, secret: str) -> bool:
if not ts or not sig or abs(time.time() - int(ts)) > 300:
return False
mac = hmac.new(secret.encode(), ts.encode() + b"." + raw_body, hashlib.sha256)
expected = base64.b64encode(mac.digest()).decode()
return hmac.compare_digest(expected, sig)
Reintentos
Responde con cualquier estado 2xx en pocos segundos. Las demás respuestas y los tiempos agotados se reintentan tras 1 minuto, 5 minutos, 30 minutos, 2 horas, 6 horas y 12 horas; después la entrega se marca como fallida. Cada intento, con su estado y respuesta, aparece en el registro de entregas del webhook.
Haz tu receptor idempotente: una entrega puede llegar más de una vez.
Registro de entregas y reintento manual
Admin Center, Integrations, Webhooks muestra cada entrega con su petición, respuesta, estado e intentos. Fíltralo por webhook, evento (ticket.created, trigger, automation, test, etc.) y estado. Replay en cualquier entrega, incluso una fallida definitivamente, pone en cola una copia nueva del mismo payload, firmada con el secret actual; la copia queda enlazada al original. El mismo registro está en la API: GET /api/webhook_deliveries?event_type=ticket.created&status=failed y POST /api/webhook_deliveries/{id}/replay.
Versión del payload
Cada entrega y cada ping llevan un entero version en su sobre, hoy 1. Forma parte del contrato público: un sobre incompatible recibe un entero nuevo, fijado por webhook, y ambas versiones se entregan mientras se retira la antigua. Lee version en tu receptor en lugar de deducirla de la forma del cuerpo, e ignora los campos que no conozcas. Las reglas, incluidos los 12 meses de aviso antes de retirar nada, están en versiones y retirada.
Direcciones de salida
Las peticiones de webhooks salen de nuestras direcciones IP de salida publicadas, para que puedas permitirlas en tu firewall.