This workflow corresponds to n8n.io template #14006 — we link there as the canonical source.
This workflow follows the Google Sheets → HTTP Request 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": "bxMDNbmaW6ygo8Rb",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Virtual Apparel Try-On Telegram Bot",
"tags": [],
"nodes": [
{
"id": "0ede88b5-b324-40f3-b0f2-3d38d02f14d9",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-416,
2128
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "967cc6cb-ce35-4b6e-9da1-ce97bd9a7c87",
"name": "Extract Message Info",
"type": "n8n-nodes-base.set",
"position": [
-192,
2128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e1",
"name": "chatId",
"type": "string",
"value": "={{ $json.message.chat.id }}"
},
{
"id": "e2",
"name": "caption",
"type": "string",
"value": "={{ ($json.message.caption ?? '').toLowerCase().trim() }}"
},
{
"id": "e3",
"name": "hasPhoto",
"type": "boolean",
"value": "={{ $json.message.photo !== undefined }}"
},
{
"id": "e4",
"name": "fileId",
"type": "string",
"value": "={{ $json.message.photo ? $json.message.photo[$json.message.photo.length - 1].file_id : '' }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "ef066042-e44f-4d8b-aab8-813cef499e5c",
"name": "\u2699\ufe0f Config",
"type": "n8n-nodes-base.set",
"position": [
32,
2128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c1",
"name": "botToken",
"type": "string",
"value": "{TELEGRAM_BOT_TOKEN}"
},
{
"id": "c2",
"name": "tryonApiKey",
"type": "string",
"value": "{TRYON_API_KEY}"
},
{
"id": "c3",
"name": "tryonApiBase",
"type": "string",
"value": "https://tryon-api.com"
},
{
"id": "c4",
"name": "sheetId",
"type": "string",
"value": "{GOOGLE_SHEET_ID}"
},
{
"id": "c5",
"name": "chatId",
"type": "string",
"value": "={{ $('Extract Message Info').item.json.chatId }}"
},
{
"id": "c6",
"name": "fileId",
"type": "string",
"value": "={{ $('Extract Message Info').item.json.fileId }}"
},
{
"id": "c7",
"name": "caption",
"type": "string",
"value": "={{ $('Extract Message Info').item.json.caption }}"
},
{
"id": "c8",
"name": "hasPhoto",
"type": "boolean",
"value": "={{ $('Extract Message Info').item.json.hasPhoto }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "ca083aaa-154d-484f-a721-1094765a7178",
"name": "Has Photo?",
"type": "n8n-nodes-base.if",
"position": [
256,
2128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "hp1",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.hasPhoto }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "81f8f152-96ab-4d51-a1e3-e5660753d1c6",
"name": "Send Welcome Message",
"type": "n8n-nodes-base.telegram",
"position": [
480,
2224
],
"parameters": {
"text": "\ud83d\udc4b Welcome to Virtual Try-On Bot!\n\n1\ufe0f\u20e3 Send a *person photo* \u2014 full body, no caption\n2\ufe0f\u20e3 Then send the *garment photo* with caption `garment`\n\nI'll generate the try-on result! \ud83d\udc57\u2728",
"chatId": "={{ $('\u2699\ufe0f Config').item.json.chatId }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "2024a886-5e99-4c3e-b09e-2a7b61047388",
"name": "Is Garment Photo?",
"type": "n8n-nodes-base.if",
"position": [
480,
2032
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ig1",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.caption }}",
"rightValue": "garment"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "1f2bcd45-87fc-46fb-9466-4f6c2f002dd8",
"name": "Save Person to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
704,
1936
],
"parameters": {
"columns": {
"value": {
"chat_id": "={{ $('\u2699\ufe0f Config').item.json.chatId }}",
"person_file_id": "={{ $('\u2699\ufe0f Config').item.json.fileId }}"
},
"schema": [
{
"id": "chat_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "chat_id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "person_file_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "person_file_id",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"chat_id"
]
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "tryon-state"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('\u2699\ufe0f Config').item.json.sheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "5eac99d6-4dcb-4351-8ad3-6cf8e9eaa099",
"name": "Ask for Garment Photo",
"type": "n8n-nodes-base.telegram",
"position": [
928,
1936
],
"parameters": {
"text": "\u2705 Person photo saved!\n\nNow send your *garment photo* with caption `garment` \ud83d\udc55",
"chatId": "={{ $('\u2699\ufe0f Config').item.json.chatId }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "6c3211b9-78d2-4f98-8026-0e6c18e06fc5",
"name": "Lookup Person from Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
704,
2128
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json.chatId }}",
"lookupColumn": "chat_id"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1wsCSDxhnTnIcyDxAYd16haxLHfRaZnB2ZXIPTGEesZs/edit#gid=0",
"cachedResultName": "tryon-state"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('\u2699\ufe0f Config').item.json.sheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "b0a6bad7-019c-4ab2-933f-17a9b74c5f86",
"name": "Has Person Saved?",
"type": "n8n-nodes-base.if",
"position": [
928,
2128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "hp2",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.person_file_id }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "66b0aa3c-269d-4fad-a698-15e02080430e",
"name": "Ask for Person First",
"type": "n8n-nodes-base.telegram",
"position": [
1152,
2224
],
"parameters": {
"text": "\u26a0\ufe0f Please send your *person photo* first (full body, no caption needed), then send the garment photo with caption `garment`.",
"chatId": "={{ $('\u2699\ufe0f Config').item.json.chatId }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "fba2ab05-ea3e-45b1-aa94-f721bbc7315f",
"name": "Collect IDs",
"type": "n8n-nodes-base.set",
"position": [
1152,
2032
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ci1",
"name": "chatId",
"type": "string",
"value": "={{ $('\u2699\ufe0f Config').item.json.chatId }}"
},
{
"id": "ci2",
"name": "personFileId",
"type": "string",
"value": "={{ $json.person_file_id }}"
},
{
"id": "ci3",
"name": "garmentFileId",
"type": "string",
"value": "={{ $('\u2699\ufe0f Config').item.json.fileId }}"
},
{
"id": "ci4",
"name": "rowNumber",
"type": "number",
"value": "={{ $json.row_number }}"
},
{
"id": "ci5",
"name": "botToken",
"type": "string",
"value": "={{ $('\u2699\ufe0f Config').item.json.botToken }}"
},
{
"id": "ci6",
"name": "tryonApiKey",
"type": "string",
"value": "={{ $('\u2699\ufe0f Config').item.json.tryonApiKey }}"
},
{
"id": "ci7",
"name": "tryonApiBase",
"type": "string",
"value": "={{ $('\u2699\ufe0f Config').item.json.tryonApiBase }}"
},
{
"id": "ci8",
"name": "sheetId",
"type": "string",
"value": "={{ $('\u2699\ufe0f Config').item.json.sheetId }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c0fff2e6-7cd1-4d00-8b35-3eb1d5a434ae",
"name": "Send Processing Message",
"type": "n8n-nodes-base.telegram",
"position": [
1376,
2032
],
"parameters": {
"text": "\ud83d\udd04 Processing your virtual try-on...\n\nThis usually takes 15\u201360 seconds. Please wait! \u23f3",
"chatId": "={{ $json.chatId }}",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "3041396b-99d2-4999-a979-a6aceb3990cf",
"name": "Get Person File Path",
"type": "n8n-nodes-base.httpRequest",
"position": [
1600,
2032
],
"parameters": {
"url": "=https://api.telegram.org/bot{{ $('Collect IDs').item.json.botToken }}/getFile",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "file_id",
"value": "={{ $('Collect IDs').item.json.personFileId }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "5f51611e-5e17-46b2-b64b-5f3808f22e47",
"name": "Set Person Download URL",
"type": "n8n-nodes-base.set",
"position": [
1824,
2032
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "pu1",
"name": "personDownloadUrl",
"type": "string",
"value": "=https://api.telegram.org/file/bot{{ $('Collect IDs').item.json.botToken }}/{{ $json.result.file_path }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "cfb00dcf-fd84-4448-89ff-219339443e46",
"name": "Get Garment File Path",
"type": "n8n-nodes-base.httpRequest",
"position": [
2048,
2032
],
"parameters": {
"url": "=https://api.telegram.org/bot{{ $('Collect IDs').item.json.botToken }}/getFile",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "file_id",
"value": "={{ $('Collect IDs').item.json.garmentFileId }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "f4096aba-fb45-47f4-b02b-c1a0ba2d5620",
"name": "Set Garment Download URL",
"type": "n8n-nodes-base.set",
"position": [
2272,
2032
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "gu1",
"name": "garmentDownloadUrl",
"type": "string",
"value": "=https://api.telegram.org/file/bot{{ $('Collect IDs').item.json.botToken }}/{{ $json.result.file_path }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f8cd2136-e962-4408-84ee-b5b701c4410d",
"name": "Download Person Image",
"type": "n8n-nodes-base.httpRequest",
"position": [
2496,
2032
],
"parameters": {
"url": "={{ $('Set Person Download URL').item.json.personDownloadUrl }}",
"options": {
"response": {
"response": {
"responseFormat": "file",
"outputPropertyName": "person_image"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "354a10f6-9cdd-453e-ab96-e63b0d2ef7c8",
"name": "Download Garment Image",
"type": "n8n-nodes-base.httpRequest",
"position": [
2720,
2032
],
"parameters": {
"url": "={{ $('Set Garment Download URL').item.json.garmentDownloadUrl }}",
"options": {
"response": {
"response": {
"responseFormat": "file",
"outputPropertyName": "garment_image"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "eb8542fb-91a8-462c-b191-c2e01fa905e7",
"name": "Submit Try-On Job",
"type": "n8n-nodes-base.httpRequest",
"position": [
2944,
2032
],
"parameters": {
"url": "={{ $('Collect IDs').item.json.tryonApiBase }}/api/v1/tryon",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "multipart-form-data",
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "person_images",
"parameterType": "formBinaryData",
"inputDataFieldName": "person_image"
},
{
"name": "garment_images",
"parameterType": "formBinaryData",
"inputDataFieldName": "garment_image"
},
{
"name": "fast_mode",
"value": "false"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('Collect IDs').item.json.tryonApiKey }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "0d24662f-aa0c-46f6-b3b3-35bc774f7811",
"name": "Extract Job ID",
"type": "n8n-nodes-base.set",
"position": [
3168,
2032
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ji1",
"name": "jobId",
"type": "string",
"value": "={{ $json.jobId }}"
},
{
"id": "ji2",
"name": "statusUrl",
"type": "string",
"value": "={{ $json.statusUrl }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b3afa4b4-4b7d-4df8-8af3-92a973cbc1f8",
"name": "Wait 15 Seconds",
"type": "n8n-nodes-base.wait",
"position": [
3392,
2032
],
"parameters": {
"amount": 15
},
"typeVersion": 1.1
},
{
"id": "f90cce7f-857e-4260-ae86-81efd01f9d7e",
"name": "Check Job Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
3616,
1904
],
"parameters": {
"url": "={{ $('Collect IDs').item.json.tryonApiBase }}/api/v1/tryon/status/{{ $('Submit Try-On Job').item.json.jobId }}",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('Collect IDs').item.json.tryonApiKey }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "1b0f1b09-a081-424a-98a3-d689cc6fd71a",
"name": "Merge State",
"type": "n8n-nodes-base.set",
"position": [
3840,
1904
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ms1",
"name": "status",
"type": "string",
"value": "={{ $json.status }}"
},
{
"id": "ms2",
"name": "imageUrl",
"type": "string",
"value": "={{ $json.imageUrl }}"
},
{
"id": "ms3",
"name": "jobId",
"type": "string",
"value": "={{ $json.jobId }}"
},
{
"id": "ms4",
"name": "errorMessage",
"type": "string",
"value": "={{ $json.error ?? '' }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6a7c9814-d81a-4106-b75b-8b56f4415409",
"name": "Is Job Complete?",
"type": "n8n-nodes-base.if",
"position": [
4064,
1904
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "jc1",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "completed"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "52b6967f-8093-4a97-b8d3-c801a6146ba9",
"name": "Is Job Failed?",
"type": "n8n-nodes-base.if",
"position": [
4288,
2128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "jf1",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "failed"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "bb7c6f29-0712-4300-ab39-5bb342b52f9f",
"name": "Send Result Photo",
"type": "n8n-nodes-base.telegram",
"position": [
4512,
1840
],
"parameters": {
"chatId": "={{ $('Collect IDs').item.json.chatId }}",
"operation": "sendPhoto",
"binaryData": true,
"additionalFields": {
"caption": "\u2705 Here's your virtual try-on result! \ud83c\udf89\n\nSend a new person photo to try another outfit! \ud83d\udc57"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "2bf9864a-9db8-4f40-8928-6ddb4f395239",
"name": "Delete Row from Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
4752,
1840
],
"parameters": {
"operation": "delete",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "tryon-state"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Collect IDs').item.json.sheetId }}"
},
"startIndex": "={{ $('Collect IDs').item.json.rowNumber }}"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "c6a72a21-b298-4e46-8fdf-ae7a9f36844e",
"name": "Send Error Message",
"type": "n8n-nodes-base.telegram",
"position": [
4512,
2128
],
"parameters": {
"text": "\u274c Sorry, the try-on failed. Please try again with clearer photos!\n\n\u2022 Person photo: full body visible, good lighting\n\u2022 Garment photo: clear view of the item \ud83d\udcf8",
"chatId": "={{ $('Collect IDs').item.json.chatId }}",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "d7b6dbe0-b0ed-45b2-b1df-dea70af43b84",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
4288,
1840
],
"parameters": {
"url": "={{ $json.imageUrl }}",
"options": {}
},
"typeVersion": 4.4
},
{
"id": "10b68de2-086f-44c4-a7ef-8520f54bb553",
"name": "Sticky Note - Config",
"type": "n8n-nodes-base.stickyNote",
"position": [
-64,
1808
],
"parameters": {
"color": 3,
"width": 284,
"height": 482,
"content": "## \u2699\ufe0f Config \u2014 Edit This First\n\nSet these 2 values before activating:\n\n* `botToken` - Your Telegram bot token from @BotFather\n* `sheetId` - ID from your Google Sheets URL\n\nAll other nodes reference values from here \u2014 you only need to change things in one place."
},
"typeVersion": 1
},
{
"id": "bff60fff-9cf5-47be-babe-b7acf67ea595",
"name": "Sticky Note - State Management1",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
1616
],
"parameters": {
"color": 5,
"width": 688,
"height": 292,
"content": "## \ud83d\udccb State Management via Google Sheets\n\n**The problem:** Each Telegram message triggers a separate workflow execution with no shared memory.\n\n**The fix:** Google Sheets acts as a bridge.\n\n- **Save Person to Sheet** \u2192 writes `chat_id` + `person_file_id` when user sends person photo\n- **Lookup Person from Sheet** \u2192 reads that row back when garment photo arrives\n- **Has Person Saved?** \u2192 if no row found, tells user to send person photo first\n\n> The `chat_id` is the unique key \u2014 it never changes for a given user/bot conversation."
},
"typeVersion": 1
},
{
"id": "8bca4062-f765-4e5b-a36f-7c97d97c4e12",
"name": "Sticky Note - Collect IDs1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1152,
1760
],
"parameters": {
"color": 6,
"width": 456,
"height": 230,
"content": "## \ud83d\udcc1 Collect IDs\n\nCarries all required data forward into the rest of the workflow:\n- `chatId` \u2014 who to reply to\n- `personFileId` \u2014 Telegram file ID of person photo\n- `garmentFileId` \u2014 Telegram file ID of garment photo\n- `rowNumber` \u2014 sheet row to delete after job completes\n- `botToken`, `tryonApiKey`, `tryonApiBase`, `sheetId` \u2014 configs\n\n> Needed because after Lookup node, the Config node is no longer in the direct chain."
},
"typeVersion": 1
},
{
"id": "971a0a2c-acef-448f-8ed5-8adbe810f6c8",
"name": "Sticky Note - File URL Resolution1",
"type": "n8n-nodes-base.stickyNote",
"position": [
2048,
1760
],
"parameters": {
"color": 6,
"width": 792,
"height": 226,
"content": "## \ud83d\udd17 Telegram File URL Resolution\n\nTelegram does **not** give you a direct download URL in the message. It only gives a `file_id`.\n\nTo get the actual image you must:\n1. Call `getFile?file_id=...` \u2192 returns a `file_path`\n2. Build download URL: `api.telegram.org/file/bot{TOKEN}/{file_path}`\n\nThis 4-node sequence does this for **both** person and garment images before passing them to the Try-On API."
},
"typeVersion": 1
},
{
"id": "97a0e691-7408-40dd-ad9a-bf058cc45fda",
"name": "Sticky Note - Polling Loop1",
"type": "n8n-nodes-base.stickyNote",
"position": [
3536,
2048
],
"parameters": {
"color": 7,
"width": 668,
"height": 252,
"content": "## \u23f1\ufe0f Polling Loop\n\nThe Try-On API is **asynchronous** \u2014 submitting a job returns a `jobId`, not the result immediately.\n\nThis loop:\n1. Waits 15 seconds\n2. Calls the status endpoint with the `jobId`\n3. Checks if status is `completed` \u2192 send result\n4. Checks if status is `failed` \u2192 send error\n5. Otherwise loops back to Wait\n\n**Typical wait time:** 15\u201360 seconds total"
},
"typeVersion": 1
},
{
"id": "c794ec17-2a15-4624-b401-80edc061c511",
"name": "Sticky Note - Download Result1",
"type": "n8n-nodes-base.stickyNote",
"position": [
4240,
1600
],
"parameters": {
"color": 2,
"width": 436,
"height": 222,
"content": "## \u2b07\ufe0f Download Result Image\n\nThe Try-On API returns an `imageUrl` (a signed URL). Telegram's `sendPhoto` with a URL can fail if the URL expires or requires auth headers.\n\nThis node downloads the image as a binary file first, then **Send Result Photo** sends it as a proper file upload \u2014 more reliable."
},
"typeVersion": 1
},
{
"id": "33934043-0a35-4283-8917-9e8fd4a06a92",
"name": "Sticky Note - Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1536,
1792
],
"parameters": {
"color": 4,
"width": 1068,
"height": 580,
"content": "# \ud83d\udc57 Virtual Try-On Telegram Bot\n\n## What this workflow does\nThis bot lets users virtually try on clothing via Telegram. A user sends a **person photo**, then a **garment photo** (with caption `garment`), and the bot replies with an AI-generated try-on result image.\n\n## How it works\n1. **Message comes in** \u2192 checks if it contains a photo\n2. **Person photo** (no caption) \u2192 saved to Google Sheets as state\n3. **Garment photo** (caption: `garment`) \u2192 looks up saved person photo from Sheets, resolves both Telegram file URLs, downloads both images, submits to Try-On API\n4. **Polling loop** \u2192 checks job status every 15s until `completed` or `failed`\n5. **Result** \u2192 downloads the result image and sends it back to the user in Telegram\n\n## Setup checklist\n- [ ] Set your **Telegram Bot Token** in \u2699\ufe0f Config node\n- [ ] Set your **Google Sheet ID** in \u2699\ufe0f Config node\n- [ ] Confirm Google Sheet has tab named `tryon-state` with headers `chat_id` and `person_file_id`\n- [ ] Assign Telegram credential to all Telegram nodes\n- [ ] Assign Google Sheets credential to all Google Sheets nodes\n- [ ] **Activate** the workflow (Telegram Trigger only works when active)"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "9fede48e-ca46-4fc0-88ce-5af539c8e6d9",
"connections": {
"Has Photo?": {
"main": [
[
{
"node": "Is Garment Photo?",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Welcome Message",
"type": "main",
"index": 0
}
]
]
},
"Collect IDs": {
"main": [
[
{
"node": "Send Processing Message",
"type": "main",
"index": 0
}
]
]
},
"Merge State": {
"main": [
[
{
"node": "Is Job Complete?",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Send Result Photo",
"type": "main",
"index": 0
}
]
]
},
"\u2699\ufe0f Config": {
"main": [
[
{
"node": "Has Photo?",
"type": "main",
"index": 0
}
]
]
},
"Extract Job ID": {
"main": [
[
{
"node": "Wait 15 Seconds",
"type": "main",
"index": 0
}
]
]
},
"Is Job Failed?": {
"main": [
[
{
"node": "Send Error Message",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait 15 Seconds",
"type": "main",
"index": 0
}
]
]
},
"Wait 15 Seconds": {
"main": [
[
{
"node": "Check Job Status",
"type": "main",
"index": 0
}
]
]
},
"Check Job Status": {
"main": [
[
{
"node": "Merge State",
"type": "main",
"index": 0
}
]
]
},
"Is Job Complete?": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
],
[
{
"node": "Is Job Failed?",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "Extract Message Info",
"type": "main",
"index": 0
}
]
]
},
"Has Person Saved?": {
"main": [
[
{
"node": "Collect IDs",
"type": "main",
"index": 0
}
],
[
{
"node": "Ask for Person First",
"type": "main",
"index": 0
}
]
]
},
"Is Garment Photo?": {
"main": [
[
{
"node": "Lookup Person from Sheet",
"type": "main",
"index": 0
}
],
[
{
"node": "Save Person to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Send Result Photo": {
"main": [
[
{
"node": "Delete Row from Sheet",
"type": "main",
"index": 0
}
]
]
},
"Submit Try-On Job": {
"main": [
[
{
"node": "Extract Job ID",
"type": "main",
"index": 0
}
]
]
},
"Extract Message Info": {
"main": [
[
{
"node": "\u2699\ufe0f Config",
"type": "main",
"index": 0
}
]
]
},
"Get Person File Path": {
"main": [
[
{
"node": "Set Person Download URL",
"type": "main",
"index": 0
}
]
]
},
"Save Person to Sheet": {
"main": [
[
{
"node": "Ask for Garment Photo",
"type": "main",
"index": 0
}
]
]
},
"Download Person Image": {
"main": [
[
{
"node": "Download Garment Image",
"type": "main",
"index": 0
}
]
]
},
"Get Garment File Path": {
"main": [
[
{
"node": "Set Garment Download URL",
"type": "main",
"index": 0
}
]
]
},
"Download Garment Image": {
"main": [
[
{
"node": "Submit Try-On Job",
"type": "main",
"index": 0
}
]
]
},
"Send Processing Message": {
"main": [
[
{
"node": "Get Person File Path",
"type": "main",
"index": 0
}
]
]
},
"Set Person Download URL": {
"main": [
[
{
"node": "Get Garment File Path",
"type": "main",
"index": 0
}
]
]
},
"Lookup Person from Sheet": {
"main": [
[
{
"node": "Has Person Saved?",
"type": "main",
"index": 0
}
]
]
},
"Set Garment Download URL": {
"main": [
[
{
"node": "Download Person Image",
"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.
googleSheetsOAuth2ApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Try on any outfit virtually - right inside Telegram. A user sends a person photo, then a garment photo (captioned ), and the bot replies with an AI-generated try-on result image using a dedicated Virtual Try-On API. No app. No frontend. Just a Telegram chat. Fashion e-commerce…
Source: https://n8n.io/workflows/14006/ — 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.
TGBot. Uses telegram, googleSheets, telegramTrigger, httpRequest. Event-driven trigger; 30 nodes.
This n8n workflow enables Telegram users to interact with multiple AI models dynamically using #model_id commands. It also supports a /models command to list all available models. Each user has a dail
Send any URL to your Telegram bot and get an AI summary instantly.
A robust n8n workflow designed to enhance Telegram bot functionality for user management and broadcasting. It facilitates automatic support ticket creation, efficient user data storage in Redis, and a
Transform your digital payment business with a fully-featured Telegram bot that handles everything from product listings to transaction processing. Perfect for entrepreneurs looking to automate their