Webhooks: eventos, payloads y firmas
Los webhooks permiten que tus propios sistemas reaccionen en cuanto Inwista termina el trabajo: cuando se completa una transcripción o se renderiza una exportación de video, Inwista hace un POST de un evento JSON firmado a un endpoint HTTPS que tú controlas. Úsalo para alimentar canalizaciones de publicación, sistemas de archivo, gestores de proyectos — cualquier cosa que deba ocurrir automáticamente cuando Inwista acaba.
Configuración y el secreto de firma
En My workspace → Integrations, conecta la tarjeta de Webhooks e introduce la URL de tu endpoint (HTTPS obligatorio). Inwista genera un secreto de firma con el prefijo whsec_ y lo muestra exactamente una vez — guárdalo en tu gestor de secretos de inmediato. Puedes rotar el secreto en cualquier momento desde los ajustes de la integración; el secreto antiguo deja de funcionar al instante.
Usa Send test event en los ajustes para disparar un evento webhook.test firmado contra tu endpoint y confirmar el cableado antes de cualquier tráfico real. Cambiar la URL del endpoint más adelante conserva el mismo secreto.
Eventos
- transcript.completed Se dispara una vez por proyecto, cuando termina la transcripción inicial. Lleva enlaces de descarga de los archivos de transcripción en los formatos configurados en la integración.
- export.completed Se dispara cada vez que termina un render de video. Lleva el video renderizado más archivos de transcripción frescos que reflejan cualquier edición de subtítulos hecha desde la transcripción.
- webhook.test Se dispara manualmente desde los ajustes de la integración, para verificar tu receptor.
Ambos tipos de evento se activan o desactivan de forma independiente en los ajustes de la integración. Los eventos se disparan en cada ocurrencia suscrita con independencia de las selecciones de almacenamiento por exportación — los webhooks son notificaciones, no destinos de entrega.
Payload
Todos los eventos comparten el mismo sobre: un tipo de event, un id único para deduplicación, un timestamp Unix, el workspaceId y un bloque project. Los eventos con archivos añaden un array files; export.completed incluye además un objeto video.
{
"event": "export.completed",
"id": "evt_9c1b7e2a4f0d4b6e8a12",
"timestamp": 1784034017,
"workspaceId": "UK6naH1L1sMtzTVcVZih",
"project": {
"id": "abc123def456",
"name": "Interview — Episode 12",
"language": "no",
"durationSeconds": 1834
},
"files": [
{
"format": "srt",
"name": "Interview — Episode 12.srt",
"mimeType": "application/x-subrip",
"url": "https://storage.googleapis.com/...signed...",
"expiresAt": 1784120417
}
],
"video": {
"name": "Interview — Episode 12.mp4",
"mimeType": "video/mp4",
"sizeBytes": 812340221,
"url": "https://storage.googleapis.com/...signed...",
"expiresAt": 1784120417
}
}Los valores de url son enlaces de descarga firmados válidos durante 24 horas (el timestamp Unix de expiresAt dice exactamente cuándo) — descarga lo que necesites pronto en lugar de guardar los enlaces. transcript.completed tiene la misma forma sin el objeto video.
Verificar las firmas
Cada petición lleva tres cabeceras: X-Inwista-Event (el tipo de evento), X-Inwista-Delivery (el id del evento) y X-Inwista-Signature — un HMAC-SHA256 del cuerpo bruto de la petición, calculado con tu secreto de firma. Recalcúlalo y compáralo antes de confiar en el payload; sin esta comprobación, cualquiera que descubra la URL de tu endpoint podría enviarte eventos falsos.
const crypto = require("crypto");
function verifyInwistaSignature(rawBody, signatureHeader, secret) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return (
signatureHeader.length === expected.length &&
crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected),
)
);
}
// Express example — capture the raw body for verification:
// app.post("/inwista-hook", express.raw({ type: "application/json" }), (req, res) => {
// if (!verifyInwistaSignature(req.body, req.get("X-Inwista-Signature"), process.env.INWISTA_WEBHOOK_SECRET)) {
// return res.status(401).end();
// }
// const event = JSON.parse(req.body);
// res.status(200).end(); // acknowledge fast, process async
// });Importante: calcula el HMAC sobre el cuerpo bruto de la petición, no sobre una versión reserializada del JSON parseado — las diferencias de orden de claves y espacios romperán la comparación.
Entrega, reintentos y deduplicación
- Confirma con un 2xx Responde en menos de 10 segundos. Haz el procesamiento pesado de forma asíncrona después de confirmar — una respuesta lenta cuenta como fallo.
- Reintentos Las entregas fallidas se reintentan hasta dos veces más (aproximadamente 10 y 30 segundos después). Las respuestas del rango 4xx se tratan como permanentes y no se reintentan, salvo 408 y 429.
- Deduplica por id Si tu servidor acepta una petición pero la respuesta se pierde, un reintento puede entregar el mismo evento dos veces. El campo id es estable entre reintentos — úsalo para ignorar duplicados.
- Pausa automática Tras 10 entregas fallidas consecutivas, Inwista pausa el endpoint y muestra el motivo en los ajustes de la integración, donde puedes reanudarlo una vez arreglado tu receptor. El estado y código HTTP de la última entrega siempre son visibles ahí.