Webhooks: hændelser, payloads og signaturer

Med webhooks kan dine egne systemer reagere i det øjeblik, Inwista er færdig med arbejdet: når en transskription fuldføres, eller en videoeksport er renderet, POSTer Inwista en signeret JSON-hændelse til et HTTPS-endpoint, du kontrollerer. Brug det til publiceringspipelines, arkivsystemer, projektværktøjer — alt, der skal ske automatisk, efter Inwista er færdig.

Opsætning og signeringshemmeligheden

Under My workspaceIntegrations, forbind Webhooks-kortet og indtast din endpoint-URL (HTTPS påkrævet). Inwista genererer en signeringshemmelighed med præfikset whsec_ og viser den præcis én gang — gem den i din secret manager med det samme. Du kan rotere hemmeligheden når som helst fra integrationsindstillingerne; den gamle holder op med at virke øjeblikkeligt.

Brug Send test event i indstillingerne til at sende en signeret webhook.test-hændelse til dit endpoint og bekræfte opsætningen før rigtig trafik. Ændrer du endpoint-URL'en senere, beholdes samme hemmelighed.

Hændelser

  • transcript.completed Sendes én gang pr. projekt, når den første transskription er færdig. Indeholder downloadlinks til transskriptionsfilerne i de formater, der er konfigureret på integrationen.
  • export.completed Sendes hver gang en videoeksport er færdigrenderet. Indeholder den renderede video plus friske transskriptionsfiler, der afspejler eventuelle undertekstredigeringer foretaget efter transskriptionen.
  • webhook.test Sendes manuelt fra integrationsindstillingerne til at verificere din modtager.

Begge hændelsestyper kan slås til og fra uafhængigt af hinanden i integrationsindstillingerne. Hændelser sendes ved hver abonneret forekomst, uanset lagringsvalg pr. eksport — webhooks er notifikationer, ikke leveringsdestinationer.

Payload

Alle hændelser deler samme konvolut: en event-type, et unikt id til deduplikering, et Unix-timestamp, workspaceId og en project-blok. Filbærende hændelser har desuden et files-array; export.completed inkluderer også et video-objekt.

{
  "event": "export.completed",
  "id": "evt_9c1b7e2a4f0d4b6e8a12",
  "timestamp": 1784034017,
  "workspaceId": "UK6naH1L1sMtzTVcVZih",
  "project": {
    "id": "abc123def456",
    "name": "Interview — Episode 12",
    "language": "da",
    "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
  }
}

url-værdierne er signerede downloadlinks gyldige i 24 timer (Unix-tidsstemplet expiresAt siger præcis hvornår) — hent det, du skal bruge, med det samme i stedet for at gemme linksene. transcript.completed har samme form, blot uden video-objektet.

Verificér signaturer

Hver forespørgsel har tre headers: X-Inwista-Event (hændelsestypen), X-Inwista-Delivery (hændelses-ID'et) og X-Inwista-Signature — en HMAC-SHA256 af den rå forespørgselskrop, beregnet med din signeringshemmelighed. Genberegn den og sammenlign, før du stoler på indholdet; uden dette tjek kan enhver, der opdager din endpoint-URL, fodre dig med falske hændelser.

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

Vigtigt: beregn HMAC'en over den rå forespørgselskrop, ikke en re-serialiseret version af den parsede JSON — forskelle i nøglerækkefølge og mellemrum bryder sammenligningen.

Levering, genforsøg og deduplikering

  • Kvittér med 2xx Svar inden for 10 sekunder. Udfør tung behandling asynkront efter kvitteringen — et langsomt svar tæller som en fejl.
  • Genforsøg Fejlede leveringer forsøges igen op til to gange mere (cirka 10 og 30 sekunder senere). Svar i 4xx-området behandles som permanente og forsøges ikke igen, med undtagelse af 408 og 429.
  • Dedupliker på id Hvis din server modtager en forespørgsel, men svaret går tabt, kan et genforsøg levere samme hændelse to gange. id-feltet er stabilt på tværs af forsøg — brug det til at ignorere dubletter.
  • Automatisk pause Efter 10 fejlede leveringer i træk sætter Inwista endpointet på pause og viser hvorfor i integrationsindstillingerne, hvor du kan genoptage, når din modtager er repareret. Den seneste leverings status og HTTP-kode er altid synlige der.