This workflow corresponds to n8n.io template #12684 — 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 →
{
"id": "BBGHaZpPUQXWrFaQ",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Poll video generation status from KIE.ai and deliver via Telegram (Sanitized)",
"tags": [],
"nodes": [
{
"id": "b174f32b-dc84-426e-9f24-9ae3ebab200b",
"name": "Main",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3232,
368
],
"parameters": {
"width": 380,
"height": 576,
"content": "## How it works\n\n1. Receives a webhook call with video task ID from the main workflow\n2. Waits 1 minute, then checks KIE.ai API for generation status\n3. If still processing, retries (up to 15 attempts / 15 min)\n4. Once complete, downloads video and uploads to S3\n5. Retrieves session metadata from Redis\n6. Sends video preview to user via Telegram with publish buttons\n\nSupports Veo 3.1, Sora 2, and Seedance models.\n\n## Setup steps\n\n1. Add your KIE.ai API key (Header Auth)\n2. Configure Redis connection for session storage\n3. Set up S3 bucket credentials\n4. Add Telegram Bot API credentials\n5. Update the webhook URL in \"Retry Poll\" node to match your n8n instance"
},
"typeVersion": 1
},
{
"id": "6d2ef622-0e8e-4e7f-9ef1-b81603f5087f",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2704,
448
],
"parameters": {
"color": 7,
"width": 520,
"height": 80,
"content": "**Webhook & Parse** \u2014 Receives polling request, parses input data, responds OK immediately"
},
"typeVersion": 1
},
{
"id": "8707a955-08d5-4494-8fac-14f1894968e5",
"name": "Status Polling",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1968,
464
],
"parameters": {
"color": 4,
"width": 696,
"height": 352,
"content": "**Status Polling** \u2014 Waits 1 min, checks KIE.ai status, parses response for completion"
},
"typeVersion": 1
},
{
"id": "b45a0f9e-b1e9-4c94-aabf-9e4c384f7d30",
"name": "Retry Logic",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
576
],
"parameters": {
"color": 3,
"width": 508,
"height": 384,
"content": "**Retry Logic** \u2014 Retries up to 15x or sends timeout message"
},
"typeVersion": 1
},
{
"id": "3357d5d2-a485-454c-b6dc-02981f3292db",
"name": "Video Download",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
320
],
"parameters": {
"color": 2,
"width": 920,
"height": 224,
"content": "**Video Processing** \u2014 Downloads from KIE.ai, uploads to S3, checks if extend flow"
},
"typeVersion": 1
},
{
"id": "6aabf895-fa67-4e3b-8263-7e6ef92d22ad",
"name": "Session Storage",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
256
],
"parameters": {
"color": 7,
"width": 1112,
"height": 368,
"content": "**Session & Metadata** \u2014 Retrieves session from Redis, creates metadata, updates status"
},
"typeVersion": 1
},
{
"id": "c028e9e5-56aa-4b68-a80b-acbc7465b8fe",
"name": "Telegram Delivery",
"type": "n8n-nodes-base.stickyNote",
"position": [
1744,
144
],
"parameters": {
"color": 4,
"width": 488,
"height": 608,
"content": "**Telegram Delivery** \u2014 Sends video preview with publish action buttons"
},
"typeVersion": 1
},
{
"id": "ed1d90e8-a6c5-4dd7-a2c1-32ac354fa348",
"name": "Extend Flow",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
176
],
"parameters": {
"color": 7,
"width": 340,
"height": 80,
"content": "**Extend Flow** \u2014 Add Merge Option if its an extend request, if initial request skip."
},
"typeVersion": 1
},
{
"id": "b3b9a267-f069-41ca-a55f-3e3092ae3e6b",
"name": "Poll Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
-2672,
576
],
"parameters": {
"path": "video-poll",
"options": {
"rawBody": true
},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "adfb0fc8-4a08-45b7-990a-8733b026cf68",
"name": "Parse Input",
"type": "n8n-nodes-base.code",
"position": [
-2448,
576
],
"parameters": {
"jsCode": "const input = $input.first().json;\n\n// Handle different webhook data structures:\n// 1. rawBody enabled: body is a JSON string\n// 2. rawBody disabled: body is an object or data is at root level\nlet body;\nif (typeof input.body === 'string') {\n body = JSON.parse(input.body);\n} else if (input.body && typeof input.body === 'object') {\n body = input.body;\n} else {\n body = input;\n}\n\nreturn {\n json: {\n sessionId: body.sessionId,\n taskId: body.taskId,\n chatId: body.chatId,\n messageId: body.messageId,\n selectedModel: body.selectedModel || 'veo3_fast',\n modelType: body.modelType || 'veo',\n statusEndpoint: body.statusEndpoint || '/api/v1/veo/record-info',\n attempt: body.attempt || 1,\n isExtend: body.isExtend || false,\n parentSessionId: body.parentSessionId || null\n }\n};"
},
"typeVersion": 2
},
{
"id": "d4c934e6-4b24-4c33-b08c-9dddcc77055f",
"name": "Respond OK",
"type": "n8n-nodes-base.respondToWebhook",
"onError": "continueRegularOutput",
"position": [
-2224,
576
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, attempt: $json.attempt }) }}"
},
"typeVersion": 1.1
},
{
"id": "7019d8f9-4cbc-4e88-ad7e-08121dce9801",
"name": "Wait 1 Minute",
"type": "n8n-nodes-base.wait",
"position": [
-2000,
576
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "436c017b-1e8c-4c6b-b2d3-07d932b94bf3",
"name": "Check KIE Status",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-1776,
576
],
"parameters": {
"url": "=https://api.kie.ai{{ $('Parse Input').first().json.statusEndpoint }}",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "taskId",
"value": "={{ $('Parse Input').first().json.taskId }}"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "ac9fba69-a574-4382-83a6-c01cfbd6f4b4",
"name": "Parse Status",
"type": "n8n-nodes-base.code",
"position": [
-1552,
576
],
"parameters": {
"jsCode": "const inputData = $('Parse Input').first().json;\nconst statusResponse = $input.first().json;\nconst modelType = inputData.modelType || 'veo';\n\nlet isCompleted = false;\nlet isFailed = false;\nlet videoUrl = null;\nlet status = 'processing';\n\nif (modelType === 'veo') {\n // Veo response: successFlag 0=Generating, 1=Success, 2=Failed, 3=Generation Failed\n const successFlag = statusResponse.data?.successFlag;\n isCompleted = successFlag === 1;\n isFailed = successFlag === 2 || successFlag === 3;\n // For 9:16 aspect ratio, use originUrls; otherwise use resultUrls\n const resultUrls = statusResponse.data?.response?.resultUrls || [];\n const originUrls = statusResponse.data?.response?.originUrls || [];\n videoUrl = originUrls[0] || resultUrls[0] || null;\n} else if (modelType === 'market') {\n // Market API response format (Sora2, Seedance)\n // State can be: 'pending', 'processing', 'success', 'failed'\n const taskState = statusResponse.data?.state || statusResponse.data?.status;\n isCompleted = taskState === 'success' || taskState === 'completed' || taskState === 'COMPLETED';\n isFailed = taskState === 'failed' || taskState === 'FAILED' || taskState === 'error';\n \n // Try multiple locations for video URL\n // 1. Direct fields\n videoUrl = statusResponse.data?.videoUrl || statusResponse.data?.output?.video || statusResponse.data?.result?.video_url;\n \n // 2. Parse resultJson if it exists\n if (!videoUrl && statusResponse.data?.resultJson) {\n try {\n const resultJson = JSON.parse(statusResponse.data.resultJson);\n videoUrl = resultJson.resultUrls?.[0] || resultJson.videoUrl || resultJson.video_url || resultJson.url;\n } catch (e) {\n // resultJson parsing failed, continue with null\n }\n }\n \n // 3. Check response object\n if (!videoUrl && statusResponse.data?.response) {\n const response = typeof statusResponse.data.response === 'string' \n ? JSON.parse(statusResponse.data.response) \n : statusResponse.data.response;\n videoUrl = response.resultUrls?.[0] || response.videoUrl || response.video_url;\n }\n}\n\nif (isCompleted) status = 'completed';\nif (isFailed) status = 'failed';\n\nreturn {\n json: {\n ...inputData,\n status,\n isCompleted,\n isFailed,\n videoUrl,\n rawResponse: statusResponse\n }\n};"
},
"typeVersion": 2
},
{
"id": "531e9b09-c985-488e-b8ad-1c0cac398d30",
"name": "Completed?",
"type": "n8n-nodes-base.if",
"position": [
-1328,
576
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.isCompleted }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "bd98177f-9a95-4f18-abef-f8c1006bac30",
"name": "Get 1080p Video",
"type": "n8n-nodes-base.code",
"position": [
-1104,
384
],
"parameters": {
"jsCode": "// Pass through - video URL already obtained from record-info\nreturn $input.all();"
},
"typeVersion": 2
},
{
"id": "f7539aaa-b9a2-41f3-9dae-5774b2799903",
"name": "Get Final URL",
"type": "n8n-nodes-base.code",
"position": [
-880,
384
],
"parameters": {
"jsCode": "// videoUrl already available from Parse Status via record-info endpoint\nconst inputData = $('Parse Status').first().json;\nconst parseInputData = $('Parse Input').first().json;\n\nreturn {\n json: {\n ...inputData,\n isExtend: parseInputData.isExtend || false,\n parentSessionId: parseInputData.parentSessionId || null\n }\n};"
},
"typeVersion": 2
},
{
"id": "47b24e8c-810c-4c87-b028-d07a1e234608",
"name": "Download Video",
"type": "n8n-nodes-base.httpRequest",
"position": [
-656,
384
],
"parameters": {
"url": "={{ $json.videoUrl }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "df9664c3-8d88-4b67-a543-f906db0faf8e",
"name": "Get Session",
"type": "n8n-nodes-base.redis",
"position": [
464,
384
],
"parameters": {
"key": "=session:{{ $('Get Final URL').first().json.sessionId }}",
"options": {},
"operation": "get"
},
"credentials": {
"redis": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "4ccd466e-32eb-4465-83f1-433b5664198d",
"name": "Merge Session Data",
"type": "n8n-nodes-base.code",
"position": [
688,
384
],
"parameters": {
"jsCode": "// Get data from Merge After Concat (via Skip Concat or Concatenate path)\nconst mergeData = $('Merge After Concat').first().json;\nconst redisResult = $input.first().json;\n\n// Redis returns data in propertyName field\nconst redisValue = redisResult.propertyName || redisResult;\nconst session = typeof redisValue === 'string' ? JSON.parse(redisValue) : redisValue;\n\nconst s3Url = `https://your-s3-endpoint.com/shorts/videos/${session.sessionId}.mp4`;\n\n// Get video URL from merge data (passed through Skip Concat or Concat path)\nlet videoUrl = mergeData.videoUrl;\n\n// Fallback: try to get from rawResponse\nif (!videoUrl && mergeData.rawResponse) {\n const raw = mergeData.rawResponse;\n videoUrl = raw.data?.response?.originUrls?.[0] || raw.data?.response?.resultUrls?.[0];\n}\n\n// Fallback 2: try Get Final URL directly\nif (!videoUrl) {\n try {\n const finalUrlData = $('Get Final URL').first().json;\n videoUrl = finalUrlData.videoUrl;\n if (!videoUrl && finalUrlData.rawResponse) {\n videoUrl = finalUrlData.rawResponse.data?.response?.originUrls?.[0] || finalUrlData.rawResponse.data?.response?.resultUrls?.[0];\n }\n } catch (e) {\n // Get Final URL not accessible\n }\n}\n\n// Store video URL and raw response for publishing\nreturn {\n json: {\n ...session,\n videoUrl: videoUrl,\n rawResponse: mergeData.rawResponse,\n s3Url: s3Url,\n status: 'video_ready',\n updatedAt: new Date().toISOString()\n }\n};"
},
"typeVersion": 2
},
{
"id": "e2c2c634-d4ad-4be6-84cd-be68f136237c",
"name": "Update Session",
"type": "n8n-nodes-base.redis",
"position": [
1360,
384
],
"parameters": {
"key": "=session:{{ $json.sessionId }}",
"ttl": 86400,
"value": "={{ JSON.stringify($json) }}",
"expire": true,
"operation": "set"
},
"credentials": {
"redis": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "2d0606a9-2ab0-4ffd-a32f-89dca688dce6",
"name": "Download for Telegram",
"type": "n8n-nodes-base.s3",
"position": [
1584,
384
],
"parameters": {
"fileKey": "=videos/{{ $('Create Metadata').first().json.sessionId }}.mp4",
"bucketName": "shorts"
},
"credentials": {
"s3": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "bba58015-be7e-4a45-9749-b9a52e864e20",
"name": "Is Veo Model?",
"type": "n8n-nodes-base.if",
"position": [
1808,
384
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $('Create Metadata').first().json.selectedModel?.startsWith('veo') }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "d7161b85-5598-4711-b0c1-efecfb6a1bff",
"name": "Send Video Preview (Veo)",
"type": "n8n-nodes-base.telegram",
"position": [
2032,
288
],
"parameters": {
"chatId": "={{ $('Create Metadata').first().json.chatId }}",
"operation": "sendVideo",
"binaryData": true,
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "YouTube",
"additionalFields": {
"callback_data": "=publish:{{ $('Create Metadata').first().json.sessionId }}"
}
},
{
"text": "TikTok",
"additionalFields": {
"callback_data": "=tiktok:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "Instagram",
"additionalFields": {
"callback_data": "=instagram:{{ $('Create Metadata').first().json.sessionId }}"
}
},
{
"text": "All Platforms",
"additionalFields": {
"callback_data": "=publishall:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "Extend Video (+8s)",
"additionalFields": {
"callback_data": "=extend:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "Cancel",
"additionalFields": {
"callback_data": "=cancel:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
}
]
},
"additionalFields": {
"caption": "=**Video Ready!**\n\n**Title:** {{ $('Create Metadata').first().json.youtubeMetadata.title }}\n",
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "a64aabf2-f9b9-472b-a7ed-af09abff099f",
"name": "Send Video Preview (Other)",
"type": "n8n-nodes-base.telegram",
"position": [
2032,
480
],
"parameters": {
"chatId": "={{ $('Create Metadata').first().json.chatId }}",
"operation": "sendVideo",
"binaryData": true,
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "YouTube",
"additionalFields": {
"callback_data": "=publish:{{ $('Create Metadata').first().json.sessionId }}"
}
},
{
"text": "TikTok",
"additionalFields": {
"callback_data": "=tiktok:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "Instagram",
"additionalFields": {
"callback_data": "=instagram:{{ $('Create Metadata').first().json.sessionId }}"
}
},
{
"text": "All Platforms",
"additionalFields": {
"callback_data": "=publishall:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "Cancel",
"additionalFields": {
"callback_data": "=cancel:{{ $('Create Metadata').first().json.sessionId }}"
}
}
]
}
}
]
},
"additionalFields": {
"caption": "=**Video Ready!**\n\n**Title:** {{ $('Create Metadata').first().json.youtubeMetadata.title }}\n",
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "75afd09e-e746-449d-9c05-80f4f354bb11",
"name": "Can Retry?",
"type": "n8n-nodes-base.if",
"position": [
-1120,
720
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.attempt < 15 }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "fa1860dd-48a5-4174-b33e-eadf07e6ee23",
"name": "Retry Poll",
"type": "n8n-nodes-base.httpRequest",
"position": [
-880,
640
],
"parameters": {
"url": "https://your-n8n-instance.com/webhook/video-poll",
"method": "POST",
"options": {},
"jsonBody": "={{ JSON.stringify({\n sessionId: $json.sessionId,\n taskId: $json.taskId,\n chatId: $json.chatId,\n messageId: $json.messageId,\n selectedModel: $json.selectedModel,\n modelType: $json.modelType,\n statusEndpoint: $json.statusEndpoint,\n attempt: $json.attempt + 1\n}) }}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "0fa23fe4-5fe5-4c82-9e5d-06e9650225bc",
"name": "Send Timeout",
"type": "n8n-nodes-base.telegram",
"position": [
-880,
800
],
"parameters": {
"text": "=**Video Generation Timeout**\n\nThe video is taking longer than expected ({{ $json.attempt }} attempts).\n\nPlease try again later or send a new idea.\n\n_Task ID: {{ $json.taskId }}_",
"chatId": "={{ $json.chatId }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "6379dbc9-ddcc-4a67-aba4-d4b5c5c1faf0",
"name": "Upload a file",
"type": "n8n-nodes-base.s3",
"position": [
-432,
384
],
"parameters": {
"fileName": "=videos/{{ $('Get Final URL').first().json.sessionId }}.mp4",
"operation": "upload",
"bucketName": "shorts",
"additionalFields": {}
},
"credentials": {
"s3": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "3cdb8933-6193-469c-bd59-ddd6fbcc1fb1",
"name": "Create Metadata",
"type": "n8n-nodes-base.code",
"position": [
912,
384
],
"parameters": {
"jsCode": "const session = $input.first().json;\n\nconst metadata = `Video Metadata\n==============\nSession ID: ${session.sessionId}\nGenerated: ${session.createdAt || 'N/A'}\nCompleted: ${new Date().toISOString()}\n\nOriginal Input\n--------------\nText: ${session.originalInput?.text || 'N/A'}\nPhoto: ${session.originalInput?.photoUrl ? 'Yes' : 'No'}\n\nVideo Generation\n----------------\nModel: ${session.selectedModel || 'veo3'}\nModel Name: ${session.modelName || 'Veo 3.1'}\nTask ID: ${session.taskId || 'N/A'}\nTemplate: ${session.template || 'general'}\nBalance at Generation: ${session.balanceAtGeneration || 'N/A'} credits\n\nYouTube Metadata\n----------------\nTitle: ${session.youtubeMetadata?.title || 'N/A'}\nDescription: ${session.youtubeMetadata?.description || 'N/A'}\nTags: ${session.youtubeMetadata?.tags?.join(', ') || 'N/A'}\n\nGenerated Prompt\n----------------\n${session.generatedPrompt || 'N/A'}\n\nURLs\n----\nS3: ${session.s3Url || 'N/A'}\nKIE: ${session.videoUrl || 'N/A'}`;\n\n// Convert text to binary for S3 upload\nconst binaryData = Buffer.from(metadata, 'utf-8');\n\nreturn {\n json: {\n ...session,\n metadataKey: `videos/${session.sessionId}_metadata.txt`\n },\n binary: {\n metadata: {\n data: binaryData.toString('base64'),\n mimeType: 'text/plain',\n fileName: `${session.sessionId}_metadata.txt`\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "676e3f5f-2994-49b7-a19b-1065cf1623f4",
"name": "Upload Metadata",
"type": "n8n-nodes-base.s3",
"position": [
1136,
384
],
"parameters": {
"fileName": "={{ $json.metadataKey }}",
"operation": "upload",
"bucketName": "shorts",
"additionalFields": {},
"binaryPropertyName": "metadata"
},
"credentials": {
"s3": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "6253a26f-4c47-4452-ade7-691dca7d2b9f",
"name": "Is Extend?",
"type": "n8n-nodes-base.if",
"position": [
-208,
384
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $('Get Final URL').first().json.isExtend }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "9f7d4cf8-9b9e-400a-82d3-3c00bda97742",
"name": "Skip Concat",
"type": "n8n-nodes-base.code",
"position": [
16,
480
],
"parameters": {
"jsCode": "// Pass through for non-extend videos\nconst inputData = $('Get Final URL').first().json;\nreturn {\n json: {\n sessionId: inputData.sessionId,\n isExtend: false,\n videoUrl: inputData.videoUrl,\n rawResponse: inputData.rawResponse\n }\n};"
},
"typeVersion": 2
},
{
"id": "021a9e58-04b5-47d9-b4aa-d6d3e402df02",
"name": "Merge After Concat",
"type": "n8n-nodes-base.merge",
"position": [
240,
384
],
"parameters": {},
"typeVersion": 2
},
{
"id": "3f7921d2-1352-4bd4-a8b1-8740d39f6b21",
"name": "Send Merge Options",
"type": "n8n-nodes-base.telegram",
"position": [
16,
288
],
"parameters": {
"text": "=**Extended Video Ready!** \ud83c\udfac\n\nYour video has been extended by ~8 seconds.\n\n**Choose how to merge:**",
"chatId": "={{ $('Parse Input').first().json.chatId }}",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "\ud83d\udd04 Auto Merge (Transloadit)",
"additionalFields": {
"callback_data": "=am:{{ $('Get Final URL').first().json.sessionId }}"
}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "\ud83d\udd17 Get Video Links (Manual)",
"additionalFields": {
"callback_data": "=mm:{{ $('Get Final URL').first().json.sessionId }}"
}
}
]
}
}
]
},
"additionalFields": {
"parse_mode": "Markdown",
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "1ea2783d-6705-40e7-897d-1135e709e438",
"connections": {
"Can Retry?": {
"main": [
[
{
"node": "Retry Poll",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Timeout",
"type": "main",
"index": 0
}
]
]
},
"Completed?": {
"main": [
[
{
"node": "Get 1080p Video",
"type": "main",
"index": 0
}
],
[
{
"node": "Can Retry?",
"type": "main",
"index": 0
}
]
]
},
"Is Extend?": {
"main": [
[
{
"node": "Send Merge Options",
"type": "main",
"index": 0
}
],
[
{
"node": "Skip Concat",
"type": "main",
"index": 0
}
]
]
},
"Respond OK": {
"main": [
[
{
"node": "Wait 1 Minute",
"type": "main",
"index": 0
}
]
]
},
"Get Session": {
"main": [
[
{
"node": "Merge Session Data",
"type": "main",
"index": 0
}
]
]
},
"Parse Input": {
"main": [
[
{
"node": "Respond OK",
"type": "main",
"index": 0
}
]
]
},
"Skip Concat": {
"main": [
[
{
"node": "Merge After Concat",
"type": "main",
"index": 1
}
]
]
},
"Parse Status": {
"main": [
[
{
"node": "Completed?",
"type": "main",
"index": 0
}
]
]
},
"Poll Trigger": {
"main": [
[
{
"node": "Parse Input",
"type": "main",
"index": 0
}
]
]
},
"Get Final URL": {
"main": [
[
{
"node": "Download Video",
"type": "main",
"index": 0
}
]
]
},
"Is Veo Model?": {
"main": [
[
{
"node": "Send Video Preview (Veo)",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Video Preview (Other)",
"type": "main",
"index": 0
}
]
]
},
"Upload a file": {
"main": [
[
{
"node": "Is Extend?",
"type": "main",
"index": 0
}
]
]
},
"Wait 1 Minute": {
"main": [
[
{
"node": "Check KIE Status",
"type": "main",
"index": 0
}
]
]
},
"Download Video": {
"main": [
[
{
"node": "Upload a file",
"type": "main",
"index": 0
}
]
]
},
"Update Session": {
"main": [
[
{
"node": "Download for Telegram",
"type": "main",
"index": 0
}
]
]
},
"Create Metadata": {
"main": [
[
{
"node": "Upload Metadata",
"type": "main",
"index": 0
}
]
]
},
"Get 1080p Video": {
"main": [
[
{
"node": "Get Final URL",
"type": "main",
"index": 0
}
]
]
},
"Upload Metadata": {
"main": [
[
{
"node": "Update Session",
"type": "main",
"index": 0
}
]
]
},
"Check KIE Status": {
"main": [
[
{
"node": "Parse Status",
"type": "main",
"index": 0
}
]
]
},
"Merge After Concat": {
"main": [
[
{
"node": "Get Session",
"type": "main",
"index": 0
}
]
]
},
"Merge Session Data": {
"main": [
[
{
"node": "Create Metadata",
"type": "main",
"index": 0
}
]
]
},
"Send Merge Options": {
"main": [
[
{
"node": "Merge After Concat",
"type": "main",
"index": 0
}
]
]
},
"Download for Telegram": {
"main": [
[
{
"node": "Is Veo Model?",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
httpHeaderAuthrediss3telegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
[](https://www.linkedin.com/in/mosaab-yassir-lafrimi/)[](https://t.me/joevenner)
Source: https://n8n.io/workflows/12684/ — 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.
Telegram Wait. Uses stickyNote, httpRequest, redis, noOp. Event-driven trigger; 36 nodes.
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
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.
This workflow is an AI-assisted clean plate and object removal pipeline built for modern VFX production environments. It transforms a single plate image and removal brief into multiple high-quality cl
Splitout. Uses stickyNote, respondToWebhook, httpRequest, splitInBatches. Webhook trigger; 29 nodes.