# Guide to Fireflies Webhooks: Features and Best Practices

Fireflies webhooks notify your application when a meeting is transcribed or summarized, so you can pull the transcript, summary, and metadata into your own systems. If you're building on Fireflies, webhooks are how you react to meeting activity without polling.

This guide covers how Fireflies webhooks work, the events you'll handle, how to verify the `X-Hub-Signature`, the optional signing behavior, and the best practices for production.

## What are Fireflies webhooks?

Fireflies webhooks are HTTP POSTs delivered to a URL you configure, sent when a meeting is transcribed (and for related events). Real deliveries use the V2 scheme, an `X-Hub-Signature` header with a `sha256=` prefix. (The older V1 scheme is deprecated, and its creation path is being removed from the dashboard; this guide covers V2, which is what you actually receive.)

Fireflies signs V2 deliveries with an `X-Hub-Signature` header: `sha256=` followed by a lowercase-hex HMAC-SHA256 of the request body, keyed with the secret you configure. Signing is optional: if you don't set a secret, deliveries arrive with no signature header at all.

## Fireflies webhook features

| Feature | Details |
| --- | --- |
| Configuration | Dashboard Settings > Developer Settings, or per-upload `webhook` in the `uploadAudio` mutation |
| Signature header | `X-Hub-Signature`, formatted `sha256=<hex>` |
| Signature scheme | lowercase-hex HMAC-SHA256 over the body, keyed with the configured secret |
| Signing | Optional, no secret set means no signature header |
| Delivery id | `x-webhook-delivery-id` (on test and real deliveries) |
| Payload | snake_case: `event`, `meeting_id` |
| Events | `meeting.transcribed`, `meeting.summarized`, `meeting.bot_joined` |
| Acknowledgement | 2xx within 10 seconds |
| SDK | None |

## Common events

Fireflies V2 event names are snake_case and dotted:

| Event | Fires when |
| --- | --- |
| `meeting.transcribed` | A meeting's transcription finishes processing |
| `meeting.summarized` | A meeting's summary is ready |
| `meeting.bot_joined` | The notetaker bot joins a meeting |

The payload is compact JSON with `event` and `meeting_id`. On receipt, use `meeting_id` to fetch the transcript, summary, and details via the Fireflies GraphQL API. Branch on the dotted `event` name.

## Setting up Fireflies webhooks

Configure the endpoint URL (and an optional signing secret) under Settings > Developer Settings in the Fireflies dashboard, or pass a `webhook` URL per upload in the `uploadAudio` GraphQL mutation.

Setting a secret is what turns signing on: with no secret, deliveries are unsigned; once you set one, the same event starts arriving with an `X-Hub-Signature` header. Set a secret so you can verify.

## Securing Fireflies webhooks

Each signed delivery carries an `X-Hub-Signature` header: `sha256=` followed by a lowercase-hex HMAC-SHA256 of the request body, keyed with your configured secret. Recompute it over the raw body and compare in constant time. Fireflies sends compact JSON, and verifying against the raw body works, so capture the raw bytes before any JSON middleware parses them.

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

const SECRET = process.env.FIREFLIES_WEBHOOK_SECRET;

function verify(rawBody, signatureHeader) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", SECRET).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  // If you've set a secret, require a valid signature (no header = unsigned)
  if (!verify(req.body, req.headers["x-hub-signature"])) {
    return res.sendStatus(401);
  }

  res.sendStatus(200); // acknowledge within 10s
  const { event, meeting_id } = JSON.parse(req.body);
  processQueue.add({
    event,
    meeting_id,
    deliveryId: req.headers["x-webhook-delivery-id"], // dedupe on this
  });
});

```

The same check in Python:

```python
import hashlib
import hmac
import os

SECRET = os.environ["FIREFLIES_WEBHOOK_SECRET"].encode()

def verify(raw_body: bytes, signature_header: str) -> bool:
    expected = "sha256=" + hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

```

## Fireflies webhook limitations and pain points

### Signing is optional

The Problem: With no secret configured, deliveries carry no `X-Hub-Signature` header at all, so an endpoint that assumes a signature either can't verify or (worse) accepts anything. Setting a secret switches signing on.

Why It Happens: Fireflies makes the signing secret opt-in.

Workarounds:

* Set a secret, and reject deliveries without a valid `X-Hub-Signature`; keep the endpoint URL secret and HTTPS-only.

How Hookdeck Can Help: Hookdeck gives you a dedicated ingestion URL and can enforce its own verification in front of your endpoint, so an unsigned Fireflies webhook isn't your only line of defense.

### V1 is deprecated

The Problem: Older docs and examples describe a V1 scheme (`x-hub-signature`, bare hex, a "Transcription completed" event). Real deliveries are V2 (`X-Hub-Signature`, `sha256=` prefix, dotted snake_case events), and the V1 creation path is being removed from the dashboard. Building against V1 means the wrong header format and event names.

Why It Happens: Fireflies moved to V2 and is retiring V1.

Workarounds:

* Target V2: strip the `sha256=` prefix when comparing, and branch on `meeting.transcribed` and friends.

How Hookdeck Can Help: Hookdeck verifies the V2 signature at the edge, so your app receives pre-verified events without version-specific handling.

### Thin payload requires an API fetch

The Problem: The payload carries only `event` and `meeting_id`, so you fetch the transcript and details from the GraphQL API for anything useful.

Why It Happens: Fireflies keeps the payload compact.

Workarounds:

* Acknowledge fast, then fetch the transcript via the API using `meeting_id` off a queue.

How Hookdeck Can Help: Hookdeck durably queues each event so your worker fetches transcripts at a controlled rate.

### Duplicates and the 10-second window

The Problem: You must return a 2xx within 10 seconds, and the same event can arrive more than once, so slow processing risks the window and duplicates double-process.

Why It Happens: Fireflies caps the ack time, and delivery is at-least-once.

Workarounds:

* Acknowledge fast and process asynchronously; dedupe on `x-webhook-delivery-id` (present on test and real deliveries).

How Hookdeck Can Help: Hookdeck acknowledges within the window, deduplicates on the delivery id, and durably queues events. See our [guide to webhook idempotency](/webhooks/guides/implement-webhook-idempotency).

## Best practices

### Set a secret and verify `sha256=` over the raw body

Configure a signing secret, compute `sha256=` + lowercase-hex HMAC-SHA256 over the raw body, and compare in constant time. Reject deliveries with no valid signature.

### Target V2

Use the V2 `X-Hub-Signature` (`sha256=`) scheme and the dotted snake_case event names; V1 is deprecated.

### Acknowledge within 10 seconds, fetch asynchronously

Return 200 immediately and fetch the transcript via the API using `meeting_id` off a queue. See [why to process webhooks asynchronously](/webhooks/guides/why-implement-asynchronous-processing-webhooks).

### Dedupe on the delivery id

Use `x-webhook-delivery-id` as an idempotency key so retries don't double-process.

## Conclusion

Fireflies V2 webhooks fire on `meeting.transcribed` and related events, verified with an `X-Hub-Signature` (`sha256=` + lowercase hex) HMAC over the raw body with a secret you configure, signing is optional, so set a secret to get a signature at all. Target V2 (V1 is deprecated), verify against the raw body, acknowledge within 10 seconds, and dedupe on `x-webhook-delivery-id`.

[Hookdeck](https://hookdeck.com) verifies the signature, deduplicates, and durably queues every event at the edge, so your app only ever processes verified, unique meeting events.

[Get started with Hookdeck](https://dashboard.hookdeck.com/signup) for free and handle Fireflies webhooks reliably in minutes.