AutomationFlowsSlack & Telegram › Send Fireflies Meeting Talk-time Dominance Reports to Telegram

Send Fireflies Meeting Talk-time Dominance Reports to Telegram

ByIncrementors @incrementors on n8n.io

Connect Fireflies to this workflow once and every meeting you record automatically generates a complete talk-time breakdown delivered to your Telegram. The moment transcription finishes, the workflow fetches per-speaker analytics from Fireflies, builds a visual bar chart showing…

Webhook trigger★★★★☆ complexity9 nodesHTTP RequestTelegram
Slack & Telegram Trigger: Webhook Nodes: 9 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #15097 — we link there as the canonical source.

This workflow follows the HTTP Request → Telegram recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "2e130d5f-e4cc-4f22-a4aa-64d6df245827",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -672,
        -176
      ],
      "parameters": {
        "color": 4,
        "width": 508,
        "height": 952,
        "content": "## Meeting Talk-Time Analyzer \u2014 Fireflies + Telegram\n\nFor managers, coaches, and team leads who want to know exactly how much each person spoke in a meeting \u2014 and whether anyone dominated. When Fireflies finishes transcribing a meeting, this workflow fetches the built-in speaker analytics, builds a visual ASCII bar chart per speaker, detects if anyone crossed the dominance threshold, and sends a complete formatted report to Telegram instantly. No AI, no spreadsheets \u2014 just pure meeting analytics delivered to your phone.\n\n## How it works\n- **1. Webhook \u2014 Fireflies Transcript Done** receives the meetingId from Fireflies on transcription complete\n- **2. Set \u2014 Config Values** stores your Fireflies API key, Telegram chat ID, and the dominance threshold percentage (default 70)\n- **3. HTTP \u2014 Fetch Speaker Analytics** calls the Fireflies GraphQL API and returns per-speaker data: talk time percentage, word count, pace, questions asked, longest monologue, speaking turns, and filler words\n- **4. Code \u2014 Analyze Speaker Data** sorts speakers by talk time, builds a visual bar chart for each (10 blocks = 100%), detects if anyone crossed the threshold, calculates total questions, and builds the complete Telegram message\n- **5. Telegram \u2014 Send Talk-Time Report** delivers the formatted report with speaker breakdown and dominance alert to your Telegram chat\n\n## Set up steps\n1. Activate the workflow and copy the webhook URL from node 1\n2. In Fireflies \u2014 go to Settings, Developer Settings, Webhooks, and paste the URL\n3. In **2. Set \u2014 Config Values** \u2014 replace YOUR_FIREFLIES_API_KEY and YOUR_TELEGRAM_CHAT_ID\n4. In **5. Telegram \u2014 Send Talk-Time Report** \u2014 connect your Telegram Bot API credential and send /start to your bot before testing\n5. Optionally adjust dominanceThreshold in node 2 \u2014 lower for stricter flagging, higher for looser"
      },
      "typeVersion": 1
    },
    {
      "id": "3a7f5c69-4f01-4c4e-8133-723241eb7f28",
      "name": "Section \u2014 Webhook Receipt and Config",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -112,
        128
      ],
      "parameters": {
        "color": 5,
        "width": 548,
        "height": 436,
        "content": "## Webhook Receipt and Config\nFireflies POSTs a meetingId here on transcription complete. Config stores your Fireflies API key, Telegram chat ID, and the dominance threshold. The meetingId is extracted inline from the webhook payload."
      },
      "typeVersion": 1
    },
    {
      "id": "810e93f7-f268-45e9-a0c9-3e93ca222b24",
      "name": "Section \u2014 Speaker Analytics Fetch and Analysis",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        128
      ],
      "parameters": {
        "color": 6,
        "width": 484,
        "height": 436,
        "content": "## Speaker Analytics Fetch and Analysis\nFetches Fireflies per-speaker analytics: talk time percentage, word count, pace, questions, longest monologue, turns, and filler words. Builds ASCII bar charts, detects dominance, and assembles the full Telegram report."
      },
      "typeVersion": 1
    },
    {
      "id": "53539469-e97f-4a69-8d2e-9bfba52db1cc",
      "name": "Section \u2014 Telegram Delivery",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1040,
        128
      ],
      "parameters": {
        "color": 4,
        "width": 468,
        "height": 436,
        "content": "## Telegram Delivery\nSends the formatted talk-time report with visual bar chart and dominance alert to your Telegram chat instantly."
      },
      "typeVersion": 1
    },
    {
      "id": "7fb875f4-ade7-4dae-88fe-4bee95986325",
      "name": "1. Webhook \u2014 Fireflies Transcript Done",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -64,
        304
      ],
      "parameters": {
        "path": "fireflies-talk-time",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1.1
    },
    {
      "id": "1f866f76-e137-4c35-b298-5b561935b672",
      "name": "2. Set \u2014 Config Values",
      "type": "n8n-nodes-base.set",
      "position": [
        256,
        304
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001",
              "name": "firefliesApiKey",
              "type": "string",
              "value": "YOUR_FIREFLIES_API_KEY"
            },
            {
              "id": "cfg-002",
              "name": "telegramChatId",
              "type": "string",
              "value": "YOUR_TELEGRAM_CHAT_ID"
            },
            {
              "id": "cfg-003",
              "name": "dominanceThreshold",
              "type": "string",
              "value": "70"
            },
            {
              "id": "cfg-004",
              "name": "meetingId",
              "type": "string",
              "value": "={{ $json.meetingId || $json.body?.meetingId || $json.data?.meetingId || '' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "63cad5d6-d3e9-4a58-bba9-7fdc4e5778be",
      "name": "3. HTTP \u2014 Fetch Speaker Analytics",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        576,
        304
      ],
      "parameters": {
        "url": "https://api.fireflies.ai/graphql",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"query\": \"query GetTranscript($id: String!) { transcript(id: $id) { id title date duration participants transcript_url analytics { speakers { speaker_id name duration word_count longest_monologue monologues_count filler_words questions duration_pct words_per_minute } } } }\",\n  \"variables\": {\n    \"id\": \"{{ $json.meetingId }}\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.firefliesApiKey }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d05eb799-0039-495c-a918-a9b4f7832408",
      "name": "4. Code \u2014 Analyze Speaker Data",
      "type": "n8n-nodes-base.code",
      "position": [
        832,
        304
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst config = $('2. Set \u2014 Config Values').item.json;\n\nconst t = response?.data?.transcript;\nif (!t || !t.id) throw new Error('Transcript not found for meetingId: ' + config.meetingId);\n\nconst speakers = t.analytics?.speakers || [];\n\nif (speakers.length === 0) {\n  throw new Error('No speaker analytics available for this meeting. Fireflies may not have detected speakers.');\n}\n\nconst threshold = parseInt(config.dominanceThreshold) || 70;\nconst meetingDurationMin = Math.round((t.duration || 0) / 60);\n\nconst meetingDate = t.date\n  ? new Date(t.date).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })\n  : new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });\n\n// Sort speakers by duration_pct descending\nconst sorted = [...speakers].sort((a, b) =>\n  (b.duration_pct || 0) - (a.duration_pct || 0)\n);\n\n// Build speaker rows\nlet speakerLines = '';\nlet dominatingSpeaker = null;\nlet totalQuestions = 0;\n\nsorted.forEach((sp, index) => {\n  const name = sp.name || 'Speaker ' + (index + 1);\n  const pct = Math.round(sp.duration_pct || 0);\n  const words = sp.word_count || 0;\n  const wpm = Math.round(sp.words_per_minute || 0);\n  const questions = sp.questions || 0;\n  const longestMono = Math.round((sp.longest_monologue || 0) / 60);\n  const monologues = sp.monologues_count || 0;\n  const fillers = sp.filler_words || 0;\n  const talkMin = Math.round((sp.duration || 0) / 60);\n\n  totalQuestions += questions;\n\n  // Build visual talk bar (10 chars = 100%)\n  const barFilled = Math.round(pct / 10);\n  const bar = '\u2588'.repeat(barFilled) + '\u2591'.repeat(10 - barFilled);\n\n  // Flag dominant speaker\n  const dominanceFlag = pct >= threshold ? ' DOMINANT' : '';\n  if (pct >= threshold && !dominatingSpeaker) dominatingSpeaker = name;\n\n  speakerLines +=\n    (index + 1) + '. ' + name + dominanceFlag + '\\n' +\n    '   ' + bar + ' ' + pct + '% (' + talkMin + ' min)\\n' +\n    '   Words: ' + words + ' | Pace: ' + wpm + ' wpm | Questions: ' + questions + '\\n' +\n    '   Longest speech: ' + longestMono + ' min | Turns: ' + monologues + ' | Fillers: ' + fillers + '\\n\\n';\n});\n\n// Build alert message\nlet alertLine = '';\nif (dominatingSpeaker) {\n  alertLine = 'ALERT: ' + dominatingSpeaker + ' dominated this meeting at ' +\n    Math.round(sorted[0].duration_pct || 0) + '% talk time. Consider giving others more space.\\n\\n';\n} else {\n  alertLine = 'Balance: Talk time was reasonably distributed across participants.\\n\\n';\n}\n\n// Build full Telegram message\nconst message =\n  'Meeting Talk-Time Report\\n' +\n  '\\n' +\n  'Meeting: ' + (t.title || 'Untitled') + '\\n' +\n  'Date: ' + meetingDate + ' | Duration: ' + meetingDurationMin + ' min\\n' +\n  'Total Questions Asked: ' + totalQuestions + '\\n' +\n  '\\n' +\n  alertLine +\n  'SPEAKER BREAKDOWN\\n\\n' +\n  speakerLines +\n  'Fireflies: ' + (t.transcript_url || 'Not available');\n\nreturn [{\n  json: {\n    telegramMessage: message,\n    telegramChatId: config.telegramChatId,\n    hasDominance: !!dominatingSpeaker,\n    meetingTitle: t.title || 'Untitled'\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "9792fd7d-f5ea-47d4-976a-af4fae0a7edf",
      "name": "5. Telegram \u2014 Send Talk-Time Report",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1232,
        304
      ],
      "parameters": {
        "text": "={{ $json.telegramMessage }}",
        "chatId": "={{ $json.telegramChatId }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    }
  ],
  "connections": {
    "2. Set \u2014 Config Values": {
      "main": [
        [
          {
            "node": "3. HTTP \u2014 Fetch Speaker Analytics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. Code \u2014 Analyze Speaker Data": {
      "main": [
        [
          {
            "node": "5. Telegram \u2014 Send Talk-Time Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. HTTP \u2014 Fetch Speaker Analytics": {
      "main": [
        [
          {
            "node": "4. Code \u2014 Analyze Speaker Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Webhook \u2014 Fireflies Transcript Done": {
      "main": [
        [
          {
            "node": "2. Set \u2014 Config Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Connect Fireflies to this workflow once and every meeting you record automatically generates a complete talk-time breakdown delivered to your Telegram. The moment transcription finishes, the workflow fetches per-speaker analytics from Fireflies, builds a visual bar chart showing…

Source: https://n8n.io/workflows/15097/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

qualiopi. Uses airtable, telegram, emailSend, httpRequest. Webhook trigger; 51 nodes.

Airtable, Telegram, Email Send +3
Slack & Telegram

PsyCardv2. Uses executeCommand, telegram, readBinaryFile, googleDrive. Webhook trigger; 41 nodes.

Execute Command, Telegram, Read Binary File +2
Slack & Telegram

[](https://www.linkedin.com/in/mosaab-yassir-lafrimi/)[](https://t.me/joevenner)

HTTP Request, Redis, S3 +1
Slack & Telegram

How it works • Webhook triggers from content creation system in Airtable • Downloads media (images/videos) from Airtable URLs • Uploads media to Postiz cloud storage • Schedules or publishes content a

Airtable, Telegram, HTTP Request
Slack & Telegram

I wanted to avoid the rush at end of month to log expenses. I tried existing expense apps but found them either too expensive for what they offer, or frustrating with inconsistent extraction results.

HTTP Request, Telegram