smithery/jeremylongshore

fireflies-webhooks-events

Implement Fireflies.ai webhook receiver with HMAC signature verification and event processing. Use when setting up webhook endpoints, handling transcript-ready notifications, or building real-time meeting intelligence pipelines. Trigger with phrases like "fireflies webhook", "fireflies events", "fireflies webhook signature", "handle fireflies events", "fireflies notifications". '

Installation

$ npx skills add smithery/jeremylongshore --skill fireflies-webhooks-events

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/jeremylongshore · top by installs.

npx skills add smithery/jeremylongshore

Browse all from smithery/jeremylongshore

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.11.0
LicenseMIT
CompatibilityDesigned for Claude Code
Allowed toolsRead, Write, Edit, Bash(curl:*)
Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,279 B
  • docs SUMMARY.md 391 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Fireflies.ai Webhooks & Events

Overview

Handle Fireflies.ai webhook events for real-time transcript notifications. Fireflies fires a webhook when a transcript finishes processing. The payload is signed with HMAC-SHA256 for verification.

Examples

Deliver the same synthetic signed transcript-ready event twice. The handler verifies the raw-body signature, stores an opaque event ID, processes only the first event, and emits a duplicate receipt for the second. An invalid signature must be rejected without logging the transcript identifier or payload.

Prerequisites

  • Fireflies.ai Business or Enterprise plan
  • FIREFLIESAPIKEY and FIREFLIESWEBHOOKSECRET in environment
  • HTTPS endpoint accessible from the internet

Webhook Event Reference

Fireflies currently fires one event type:

Event eventType Value Trigger
Transcription completed "Transcription completed" Transcript is fully processed and ready

Payload Format

{
  "meetingId": "ASxwZxCstx",
  "eventType": "Transcription completed",
  "clientReferenceId": "be582c46-4ac9-4565-9ba6-6ab4264496a8"
}
Field Type Description
meetingId String Transcript ID -- use in transcript(id:) query
eventType String Always "Transcription completed" currently
clientReferenceId ID Your custom ID from uploadAudio (null if bot-recorded)

Important Constraints

  • Webhooks fire only for meetings you own (organizer_email matches your account)
  • Super Admin webhooks (Enterprise only) fire for all team-owned meetings

Instructions

Step 1: Register Webhook in Dashboard

  1. Go to app.fireflies.ai/settings
  2. Select Developer settings tab
  3. Enter your HTTPS webhook URL
  4. Enter or generate a 16-32 character secret
  5. Save

Step 2: Build Webhook Receiver with Signature Verification

import express from "express";
import crypto from "crypto";

const app = express();

// IMPORTANT: Use raw body for HMAC verification
app.post("/webhooks/fireflies",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const signature = req.headers["x-hub-signature"] as string;
    const rawBody = req.body.toString();

    // Verify HMAC-SHA256 signature
    if (!signature || !verifySignature(rawBody, signature)) {
      console.warn("Rejected webhook: invalid signature");
      return res.status(401).json({ error: "Invalid signature" });
    }

    // Acknowledge immediately -- process async
    res.status(200).json({ received: true });

    const event = JSON.parse(rawBody);
    console.log(`Webhook: ${event.eventType} for meeting ${event.meetingId}`);

    // Process in background
    processTranscriptReady(event.meetingId, event.clientReferenceId)
      .catch(err => console.error("Webhook processing failed:", err));
  }
);

function verifySignature(payload: string, signature: string): boolean {
  const secret = process.env.FIREFLIES_WEBHOOK_SECRET!;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Step 3: Fetch and Process the Transcript

const FIREFLIES_API = "https://api.fireflies.ai/graphql";

async function processTranscriptReady(meetingId: string, clientRefId?: string) {
  const res = await fetch(FIREFLIES_API, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.FIREFLIES_API_KEY}`,
    },
    body: JSON.stringify({
      query: `
        query GetTranscript($id: String!) {
          transcript(id: $id) {
            id title date duration
            organizer_email
            speakers { name }
            sentences { speaker_name text start_time end_time }
            summary {
              overview
              action_items
              keywords
              short_summary
            }
            meeting_attendees { displayName email }
          }
        }
      `,
      variables: { id: meetingId },
    }),
  });

  const json = await res.json();
  if (json.errors) throw new Error(json.errors[0].message);

  const transcript = json.data.transcript;
  console.log(`Processing: "${transcript.title}" (${transcript.duration}min)`);
  console.log(`Speakers: ${transcript.speakers.map((s: any) => s.name).join(", ")}`);
  console.log(`Action items: ${transcript.summary?.action_items?.length || 0}`);

  // Route to downstream systems
  await Promise.all([
    storeTranscript(transcript),
    createTasksFromActionItems(transcript),
    notifyTeam(transcript),
  ]);
}

async function storeTranscript(transcript: any) {
  // Store in your database
  console.log(`Stored transcript: ${transcript.id}`);
}

async function createTasksFromActionItems(transcript: any) {
  const items = transcript.summary?.action_items || [];
  for (const item of items) {
    console.log(`Task created: ${item}`);
    // await taskManager.create({ title: item, source: transcript.title });
  }
}

async function notifyTeam(transcript: any) {
  // Send Slack/email notification
  const summary = transcript.summary?.short_summary || transcript.summary?.overview;
  console.log(`Notification: "${transcript.title}" -- ${summary}`);
}

Step 4: Per-Upload Webhook (Alternative)

Instead of dashboard-level webhook, include a webhook URL in uploadAudio:

await fetch(FIREFLIES_API, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.FIREFLIES_API_KEY}`,
  },
  body: JSON.stringify({
    query: `
      mutation($input: AudioUploadInput) {
        uploadAudio(input: $input) { success title message }
      }
    `,
    variables: {
      input: {
        url: "https://storage.example.com/recording.mp3",
        title: "Client Call 2026-03-22",
        webhook: "https://api.yourapp.com/webhooks/fireflies",
        client_reference_id: "order-12345",
      },
    },
  }),
});

Step 5: Test Webhook

set -euo pipefail
# Test by uploading a short audio file
curl -s -X POST https://api.fireflies.ai/graphql \
  -H "Authorization: Bearer $FIREFLIES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation($input: AudioUploadInput) { uploadAudio(input: $input) { success message } }",
    "variables": { "input": { "url": "https://example.com/test-audio.mp3", "title": "Webhook Test" } }
  }' | jq .
# The webhook will fire when transcription completes (usually 2-5 minutes)

Error Handling

Issue Cause Solution
Webhook not firing URL not saved in dashboard Re-register at app.fireflies.ai/settings
Invalid signature Secret mismatch Verify secret matches dashboard value
Missing meetingId Malformed payload Log raw body, check Fireflies status
Webhook only fires for some meetings Owner-only constraint Webhooks fire only for your meetings
clientReferenceId is null Bot-recorded meeting Only set on uploadAudio calls

Output

  • HTTPS webhook endpoint with HMAC-SHA256 signature verification
  • Automatic transcript fetch on completion events
  • Action item extraction and downstream routing
  • Per-upload webhook support for custom tracking

Resources

Next Steps

For deployment setup, see fireflies-deploy-integration.