Implement Fireflies.ai webhook signature validation and event handling. Use when setting up webhook endpoints, implementing signature verification, or handling Fireflies.ai event notifications securely. Trigger with phrases like "fireflies webhook", "fireflies events", "fireflies webhook signature", "handle fireflies events", "fireflies notifications".
From fireflies-packnpx claudepluginhub nickloveinvesting/nick-love-plugins --plugin fireflies-packThis skill is limited to using the following tools:
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Details PluginEval's skill quality evaluation: 3 layers (static, LLM judge), 10 dimensions, rubrics, formulas, anti-patterns, badges. Use to interpret scores, improve triggering, calibrate thresholds.
Handle Fireflies.ai webhooks for real-time meeting transcript notifications. Fireflies sends webhook events when meeting transcripts are ready, when action items are extracted, and when meeting summaries complete.
FIREFLIES_API_KEY environment variableapi.fireflies.ai/graphql| Event | Trigger | Payload |
|---|---|---|
Transcription completed | Transcript ready | Meeting ID, transcript text, speakers |
Meeting started | Bot joins meeting | Meeting ID, participants |
Meeting ended | Bot leaves meeting | Meeting ID, duration |
Summary ready | AI summary generated | Summary, action items, keywords |
Upload processed | Audio file processed | Transcript ID, duration |
const FIREFLIES_API = "https://api.fireflies.ai/graphql";
async function registerWebhook(url: string) {
const mutation = `
mutation AddWebhook($input: WebhookInput!) {
addWebhook(input: $input) {
id
url
events
is_active
}
}
`;
const response = await fetch(FIREFLIES_API, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.FIREFLIES_API_KEY}`,
},
body: JSON.stringify({
query: mutation,
variables: {
input: {
url,
events: ["Transcription completed", "Summary ready"],
is_active: true,
},
},
}),
});
return response.json();
}
import express from "express";
const app = express();
app.use(express.json());
app.post("/webhooks/fireflies", async (req, res) => {
const { event_type, meeting_id, data } = req.body;
res.status(200).json({ received: true }); # HTTP 200 OK
switch (event_type) {
case "Transcription completed":
await handleTranscriptReady(meeting_id, data);
break;
case "Summary ready":
await handleSummaryReady(meeting_id, data);
break;
}
});
async function handleTranscriptReady(meetingId: string, data: any) {
// Fetch full transcript via GraphQL
const transcript = await fetchTranscript(meetingId);
const { title, speakers, sentences, duration } = transcript;
console.log(`Transcript ready: "${title}" (${duration}min, ${speakers.length} speakers)`);
// Store transcript
await db.transcripts.create({
meetingId,
title,
speakers,
sentences,
duration,
processedAt: new Date(),
});
}
async function fetchTranscript(meetingId: string) {
const query = `
query GetTranscript($id: String!) {
transcript(id: $id) {
id
title
date
duration
speakers {
name
email
}
sentences {
text
speaker_name
start_time
end_time
}
summary {
overview
action_items
keywords
}
}
}
`;
const response = await fetch(FIREFLIES_API, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.FIREFLIES_API_KEY}`,
},
body: JSON.stringify({ query, variables: { id: meetingId } }),
});
const result = await response.json();
return result.data.transcript;
}
async function handleSummaryReady(meetingId: string, data: any) {
const transcript = await fetchTranscript(meetingId);
const { summary } = transcript;
// Create tasks from action items
for (const item of summary.action_items) {
await taskManager.createTask({
title: item,
source: `Meeting: ${transcript.title}`,
meetingId,
assignee: extractAssignee(item, transcript.speakers),
});
}
// Send Slack digest
await sendSlackDigest({
title: transcript.title,
overview: summary.overview,
actionItems: summary.action_items,
keywords: summary.keywords,
});
}
| Issue | Cause | Solution |
|---|---|---|
| Webhook not firing | Inactive webhook | Verify is_active via GraphQL query |
| Empty transcript | Short meeting | Minimum meeting duration required |
| Missing speakers | No calendar match | Ensure calendar integration is connected |
| Auth error on GraphQL | Invalid API key | Regenerate key in Fireflies dashboard |
set -euo pipefail
curl -X POST https://api.fireflies.ai/graphql \
-H "Authorization: Bearer $FIREFLIES_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ transcripts(limit: 5) { id title date duration } }"}'
For deployment setup, see fireflies-deploy-integration.