Webhooks : événements, payloads et signatures

Les webhooks permettent à vos systèmes de réagir dès que Inwista a terminé : quand une transcription se termine ou qu'un export vidéo est rendu, Inwista envoie en POST un événement JSON signé vers un endpoint HTTPS que vous contrôlez. Alimentez chaînes de publication, systèmes d'archivage, gestionnaires de projets — tout ce qui doit se déclencher automatiquement quand Inwista a fini.

Configuration et secret de signature

Dans My workspaceIntegrations, connectez la carte Webhooks et saisissez l'URL de votre endpoint (HTTPS obligatoire). Inwista génère un secret de signature préfixé whsec_ et l'affiche une seule fois — rangez-le immédiatement dans votre gestionnaire de secrets. Vous pouvez faire tourner le secret à tout moment depuis les réglages de l'intégration ; l'ancien cesse de fonctionner immédiatement.

Utilisez Send test event dans les réglages pour tirer un événement webhook.test signé vers votre endpoint et valider le câblage avant tout trafic réel. Changer l'URL de l'endpoint plus tard conserve le même secret.

Événements

  • transcript.completed Émis une fois par projet, à la fin de la transcription initiale. Porte des liens de téléchargement des fichiers de transcription dans les formats configurés sur l'intégration.
  • export.completed Émis à chaque fin de rendu vidéo. Porte la vidéo rendue plus des fichiers de transcription à jour, reflétant les modifications de sous-titres faites depuis la transcription.
  • webhook.test Émis manuellement depuis les réglages de l'intégration, pour vérifier votre récepteur.

Les deux types d'événements s'activent indépendamment dans les réglages de l'intégration. Les événements sont émis à chaque occurrence souscrite, quels que soient les choix de stockage par export — les webhooks sont des notifications, pas des destinations de livraison.

Payload

Chaque événement partage la même enveloppe : un type event, un id unique pour la déduplication, un timestamp Unix, le workspaceId et un bloc project. Les événements porteurs de fichiers ajoutent un tableau files ; export.completed inclut aussi un objet 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
  }
}

Les valeurs url sont des liens de téléchargement signés valables 24 heures (le timestamp Unix expiresAt dit exactement quand) — récupérez ce qu'il vous faut rapidement plutôt que de stocker les liens. transcript.completed a la même forme, sans l'objet video.

Vérifier les signatures

Chaque requête porte trois en-têtes : X-Inwista-Event (le type d'événement), X-Inwista-Delivery (l'id de l'événement) et X-Inwista-Signature — un HMAC-SHA256 du corps brut de la requête, calculé avec votre secret de signature. Recalculez-le et comparez avant de faire confiance au payload ; sans ce contrôle, quiconque découvre l'URL de votre endpoint pourrait vous envoyer de faux événements.

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
// });

Important : calculez le HMAC sur le corps brut de la requête, pas sur une version resérialisée du JSON parsé — les différences d'ordre des clés et d'espaces casseraient la comparaison.

Livraison, relances et déduplication

  • Répondez avec un 2xx Répondez sous 10 secondes. Faites le traitement lourd de façon asynchrone après confirmation — une réponse lente compte comme un échec.
  • Relances Les livraisons échouées sont retentées jusqu'à deux fois (environ 10 puis 30 secondes plus tard). Les réponses 4xx sont traitées comme permanentes et non relancées, sauf 408 et 429.
  • Dédupliquez par id Si votre serveur accepte une requête mais que la réponse se perd, une relance peut livrer le même événement deux fois. Le champ id est stable entre relances — utilisez-le pour ignorer les doublons.
  • Pause automatique Après 10 livraisons échouées consécutives, Inwista met l'endpoint en pause et en affiche la raison dans les réglages de l'intégration, où vous pouvez le relancer une fois votre récepteur réparé. Le statut et le code HTTP de la dernière livraison y restent toujours visibles.