AutomationFlowsSlack & Telegram › Telegram Polls & Messages to Group Topics

Telegram Polls & Messages to Group Topics

Original n8n title: Telegram Comms (polls & Messages to Group Topics)

Telegram Comms (Polls & Messages to Group Topics). Uses httpRequest. Webhook trigger; 11 nodes.

Webhook trigger★★★★☆ complexity11 nodesHTTP Request
Slack & Telegram Trigger: Webhook Nodes: 11 Complexity: ★★★★☆ Added:

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
{
  "name": "Telegram Comms (Polls & Messages to Group Topics)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "send-telegram",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "node-webhook",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -880,
        128
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "cfg-bot-token",
              "name": "telegram_bot_token",
              "value": "YOUR_TELEGRAM_BOT_TOKEN",
              "type": "string"
            },
            {
              "id": "cfg-group-id",
              "name": "group_chat_id",
              "value": "YOUR_TELEGRAM_GROUP_CHAT_ID",
              "type": "string"
            },
            {
              "id": "cfg-app-url",
              "name": "app_url",
              "value": "https://YOUR_APP_DOMAIN",
              "type": "string"
            },
            {
              "id": "cfg-secret",
              "name": "webhook_secret",
              "value": "YOUR_WEBHOOK_SECRET",
              "type": "string"
            },
            {
              "id": "cfg-supabase-url",
              "name": "supabase_url",
              "value": "YOUR_SUPABASE_URL",
              "type": "string"
            },
            {
              "id": "cfg-supabase-key",
              "name": "supabase_service_key",
              "value": "YOUR_SUPABASE_SERVICE_KEY",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "node-config",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -656,
        128
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $('Webhook').item.json;\nconst body = data.body || data;\nconst secret = body.webhookSecret;\nconst expected = $('Config').item.json.webhook_secret;\nif (secret !== expected) { throw new Error('Invalid webhook secret'); }\nconst { action, content, topicId, teamId, pollQuestion, pollOptions, isAnonymous, targetGroup, ageGroup } = body;\nif (!action) throw new Error('Missing required field: action');\nreturn { json: { action: action || 'send_message', content: content || '', topicId: topicId || null, teamId: teamId || null, pollQuestion: pollQuestion || '', pollOptions: pollOptions || [], isAnonymous: isAnonymous === true, targetGroup: targetGroup || 'all', ageGroup: ageGroup || null } };"
      },
      "id": "node-validate",
      "name": "Validate & Parse",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        128
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true
          },
          "conditions": [
            {
              "id": "check-team-lookup",
              "leftValue": "={{ $json.teamId }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ]
        },
        "options": {}
      },
      "id": "node-need-lookup",
      "name": "Need Topic Lookup?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -224,
        128
      ]
    },
    {
      "parameters": {
        "url": "={{ $('Config').item.json.supabase_url }}/rest/v1/Team?id=eq.{{ $('Validate & Parse').item.json.teamId }}&select=telegramTopicId",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $('Config').item.json.supabase_service_key }}"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Config').item.json.supabase_service_key }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-fetch-topic",
      "name": "Fetch Team Topic ID",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        0,
        0
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "const parsed = $('Validate & Parse').item.json;\nconst config = $('Config').item.json;\n\nlet resolvedTopicId = parsed.topicId;\n\ntry {\n  const teamData = $('Fetch Team Topic ID').item.json;\n  const rows = Array.isArray(teamData) ? teamData : [teamData];\n  if (rows.length > 0 && rows[0].telegramTopicId) {\n    resolvedTopicId = rows[0].telegramTopicId;\n  }\n} catch (e) {\n  // No team data \u2014 use direct topicId or null\n}\n\nreturn {\n  json: {\n    ...parsed,\n    resolvedTopicId: resolvedTopicId ? Number(resolvedTopicId) : null,\n    chatId: config.group_chat_id\n  }\n};"
      },
      "id": "node-resolve",
      "name": "Resolve Topic",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        128
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "check-poll",
              "leftValue": "={{ $json.action }}",
              "rightValue": "send_poll",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-is-poll",
      "name": "Is Poll?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        448,
        128
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendPoll",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: $json.chatId, question: $json.pollQuestion, options: ($json.pollOptions || ['Attending \u2705', 'Not Available \u274c', 'Maybe \ud83e\udd14']).map(function(t) { return { text: t }; }), is_anonymous: $json.isAnonymous, message_thread_id: $json.resolvedTopicId || undefined }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-send-poll",
      "name": "Send Poll",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: $json.chatId, text: $json.content, parse_mode: 'HTML', message_thread_id: $json.resolvedTopicId || undefined }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-send-msg",
      "name": "Send Message",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        672,
        240
      ]
    },
    {
      "parameters": {
        "jsCode": "const result = $input.item.json;\nconst ok = result.ok === true;\n\nreturn {\n  json: {\n    success: ok,\n    messageId: ok ? result.result?.message_id : null,\n    error: ok ? null : (result.description || 'Telegram API error')\n  }\n};"
      },
      "id": "node-format-resp",
      "name": "Format Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        128
      ]
    },
    {
      "parameters": {},
      "id": "node-ratelimit",
      "name": "Rate Limit \u2014 1s",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1088,
        128
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Validate & Parse",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate & Parse": {
      "main": [
        [
          {
            "node": "Need Topic Lookup?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Need Topic Lookup?": {
      "main": [
        [
          {
            "node": "Fetch Team Topic ID",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Resolve Topic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Team Topic ID": {
      "main": [
        [
          {
            "node": "Resolve Topic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resolve Topic": {
      "main": [
        [
          {
            "node": "Is Poll?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Poll?": {
      "main": [
        [
          {
            "node": "Send Poll",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Poll": {
      "main": [
        [
          {
            "node": "Format Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Message": {
      "main": [
        [
          {
            "node": "Format Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Response": {
      "main": [
        [
          {
            "node": "Rate Limit \u2014 1s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [
    {
      "name": "Telegram"
    },
    {
      "name": "Communications"
    }
  ]
}
Pro

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

How this works

This workflow enables seamless communication in Telegram groups by automating the sending of targeted messages and polls to specific topics, ensuring your team stays organised without manual intervention. It's ideal for community managers, project leads, or anyone handling group discussions where timely polls or announcements boost engagement and productivity. The key step involves a webhook trigger that receives incoming data, validates it, and uses HTTP requests to fetch the correct topic ID before dispatching the content via Telegram's API.

Use this workflow when you need to automate responses to external events, like form submissions triggering a poll in a dedicated group topic, or integrating with tools such as Google Forms for instant feedback collection. Avoid it for simple one-off messages, as the setup suits recurring, data-driven interactions; for basic broadcasting without topics, a simpler Telegram node suffices. Common variations include adding error handling for invalid topics or extending to multiple groups for scaled team communications.

About this workflow

Telegram Comms (Polls & Messages to Group Topics). Uses httpRequest. Webhook trigger; 11 nodes.

Source: https://github.com/hasancoded/n8n-workflow-templates/blob/main/telegram-comms.json — 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

This template is perfect for community managers, business owners, and WhatsApp group administrators who want to create a welcoming experience for new members. Whether you're running a support group, m

HTTP Request
Slack & Telegram

The workflow starts when a webhook receives a POST request from Whapi, notifying that a new participant has joined a WhatsApp group.

HTTP Request, Airtable
Slack & Telegram

This n8n workflow template simplifies processing of media group messages sent by users in Telegram. It caches image album messages using Data Tables, and then sends them to a Nano Banana model for pro

Telegram Trigger, Data Table, Telegram +1
Slack & Telegram

🚀 Lightning-fast setup - Deploy in under 5 minutes 💡 Zero AI costs - Uses simple math instead of expensive LLM calls 🛡️ 99% spam blocking - Mathematical CAPTCHAs stop bots instantly ⚡ Ultra-efficient

Telegram Trigger, Google Sheets, Telegram +1
Slack & Telegram

🧩 Jamf Smart Group Membership to Slack Automatically export Jamf smart group membership to Slack in CSV format. Perfect for IT and security teams who need fast visibility into device grouping—without

HTTP Request, Slack