# Wistia Webhooks

## When to Use This Skill

* How do I receive Wistia webhooks?
* How do I verify the Wistia `X-Wistia-Signature` header?
* How do I know when a Wistia video is ready for playback (`media.ready`)?
* How do I handle Wistia viewing session events such as `viewing_session.play`?
* Why is my Wistia webhook signature verification failing?
* How do I handle batched Wistia deliveries and duplicate events?

## Verification (core)

Every Wistia delivery carries an `X-Wistia-Signature` header: the **lowercase hex HMAC-SHA256** of the **raw request body**, keyed with the **Secret Key** you entered when configuring the webhook. The header is the bare 64-character digest (no prefix), and nothing else (no timestamp or id) is signed. Wistia has no webhook SDK, so verify manually.

```javascript
const crypto = require('crypto');

const HEX_SHA256 = /^[0-9a-fA-F]{64}$/;

function verifyWistiaSignature(rawBody /* Buffer */, signature, secret) {
  if (!secret || typeof signature !== 'string' || !HEX_SHA256.test(signature)) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
  const received = Buffer.from(signature.toLowerCase(), 'hex'); // validated above
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}

```

Use the **raw body bytes** (`express.raw({ type: '*/*' })`, `await request.arrayBuffer()`, `await request.body()`), use the secret's UTF-8 bytes as-is, and parse JSON only after the check. Respond `401` on a missing, malformed or mismatched signature.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/wistia-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/wistia-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/wistia-webhooks/examples/fastapi/).

## Event Handling

The body is `{ "hook": { "uuid" }, "events": [ ... ] }`. **One POST can batch several events**, so loop over `events` and dispatch on each event's `type`. Each event has `uuid`, `type`, `generated_at` and `payload`. Wistia delivers at least once (it may resend, for example after the 10 second timeout), so dedupe on each event's `uuid` and order by `generated_at`.

## Common Event Types

| Event | Triggered When |
| --- | --- |
| `media.created` | A media is created |
| `media.processing` | Processing has started |
| `media.ready` | Processing is complete and the media is ready for playback |
| `media.failed` | Processing failed |
| `media.updated` | A media is replaced or its title, description or thumbnail changes |
| `media.deleted` | A media is deleted |
| `viewing_session.play` | A viewer plays a media |
| `viewing_session.percent_watched` | A viewer reaches a watch-percentage milestone |
| `viewing_session.turnstile.converted` | A viewer submits a Wistia form |
| `live_event.registration` | Someone registers for a live event |

> **For the full event list** (transcripts, translations, localizations, call-to-action and annotation conversions), see [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/wistia-webhooks/references/overview.md) and [Wistia's webhook docs](https://docs.wistia.com/docs/webhooks).

## Environment Variables

```bash
# The Secret Key you entered for the webhook in Wistia (Account Settings > Webhooks)
WISTIA_WEBHOOK_SECRET=your_wistia_webhook_secret_key

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 wistia --path /webhooks/wistia

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/wistia-webhooks/references/overview.md) - Wistia webhook concepts, event list, payload shape
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/wistia-webhooks/references/setup.md) - Configuring a webhook in Account Settings
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/wistia-webhooks/references/verification.md) - Signature verification details and gotchas