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 →
{
"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"
}
]
}
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 →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
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
The workflow starts when a webhook receives a POST request from Whapi, notifying that a new participant has joined a WhatsApp group.
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
🚀 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
🧩 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