Création automatisée de tickets Slack vers Jira avec pièces jointes
Ceci est unContent Creation, Multimodal AIworkflow d'automatisation du domainecontenant 19 nœuds.Utilise principalement des nœuds comme If, Code, Jira, Slack, HttpRequest. 带附件deautomatisationSlackàJira问题création
- •Token Bot Slack ou URL Webhook
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
Nœuds utilisés (19)
Catégorie
{
"id": "UWaBGGumTuGmryJq",
"meta": {
"instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177",
"templateCredsSetupCompleted": true
},
"name": "Automated Slack-to-Jira Issue Creation with Attachments",
"tags": [
{
"id": "SHQpff6D2VUAhiBO",
"name": "slack-integration",
"createdAt": "2025-09-03T10:01:17.871Z",
"updatedAt": "2025-09-03T10:01:17.871Z"
},
{
"id": "us8CC0JZKBaYTMbE",
"name": "automation",
"createdAt": "2025-09-03T10:01:17.853Z",
"updatedAt": "2025-09-03T10:01:17.853Z"
}
],
"nodes": [
{
"id": "9a2f9325-f367-4178-b57f-da06ce268aa3",
"name": "Note adhésive 7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1472,
2544
],
"parameters": {
"color": 5,
"height": 320,
"content": "Purpose: Attaches downloaded files to created Jira issue\n\nFunction: Uploads binary file data to \nspecific Jira ticket\n\nUse Case: Preserves screenshots/documentation from Slack in Jira\n\nInput: Jira issue key + file binary data\nResult: File becomes viewable in Jira issue"
},
"typeVersion": 1
},
{
"id": "45ca44bb-fcf5-4892-8915-b5b561d489ee",
"name": "Note adhésive 8",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
2240
],
"parameters": {
"color": 3,
"height": 320,
"content": "Purpose: Downloads files from Slack using private URLs\n\nFunction: Fetches attachment data with Slack bot token authentication\n\nUse Case: Retrieves screenshots/files to attach to Jira issue\nAuthentication: Bearer token in header\n\nResponse: File data in binary format"
},
"typeVersion": 1
},
{
"id": "a9b50384-69f7-4325-b209-9b8b0980d4fd",
"name": "Note adhésive 9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
3088
],
"parameters": {
"color": 6,
"height": 272,
"content": "Purpose: Creates new Jira issue with parsed data\n\nFunction: Submits ticket to specified Jira project.\n\nUse Case: Automatically creates trackable issues from Slack reports\n\nOutput: Jira issue details including unique issue key"
},
"typeVersion": 1
},
{
"id": "89199791-4879-47be-8d99-f6b5be1eb3e2",
"name": "Note adhésive 10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-336,
2480
],
"parameters": {
"color": 2,
"height": 384,
"content": "Purpose: Extracts structured issue details from Slack message text\n\nFunction: Uses regex to parse Title, Description, Priority from message\n\nUse Case: Converts \"Title: X Description: Y Priority: Z\" format to structured data\nKey Features:\n\nExtracts title, description, priority using regex patterns\nMaps Slack priorities (high/medium/low) to Jira format"
},
"typeVersion": 1
},
{
"id": "618371b4-bf61-4a9e-b76a-8081716eef8c",
"name": "Note adhésive 11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-896,
2544
],
"parameters": {
"height": 352,
"content": "Purpose: Monitors specific Slack channel for new messages\n\nFunction: Automatically triggers workflow when message posted\n\nUse Case: Captures issue reports from channel.\n\nConfiguration: Listens for message events only\n\nOutput: Raw Slack message data with text, user, files, timestamps"
},
"typeVersion": 1
},
{
"id": "bcabc988-0058-4e65-8e1e-cf7d32dacfec",
"name": "Note adhésive 12",
"type": "n8n-nodes-base.stickyNote",
"position": [
848,
2976
],
"parameters": {
"color": 4,
"height": 224,
"content": "Purpose: Sends confirmation message back to Slack\n\nFunction: Posts success notification in tickets channel\n\nUse Case: Confirms issue creation and provides Jira tracking info"
},
"typeVersion": 1
},
{
"id": "31b4df31-3567-40b3-b44d-06a2f9e5abcd",
"name": "Note adhésive 13",
"type": "n8n-nodes-base.stickyNote",
"position": [
96,
2592
],
"parameters": {
"color": 3,
"height": 288,
"content": "Purpose: Splits multiple attachments into individual items for processing\n\nFunction: Loops through each attachment one by one\n\nUse Case: Handles multiple file uploads from Slack message\n\nOutput: Individual attachment items that can be processed sequentially"
},
"typeVersion": 1
},
{
"id": "9c766474-c73f-4579-a938-e7a02e7e88e2",
"name": "Note adhésive - Split Files",
"type": "n8n-nodes-base.stickyNote",
"position": [
512,
2512
],
"parameters": {
"color": 5,
"height": 240,
"content": "NEW: Splits all files into individual batches\n\nPurpose: Processes each attachment separately\n\nFunction: Takes files array and creates one execution per file\n\nBenefit: Enables uploading multiple attachments to Jira"
},
"typeVersion": 1
},
{
"id": "df70376c-d7cd-48ae-a90d-f9ae05647257",
"name": "Déclencheur Slack",
"type": "n8n-nodes-base.slackTrigger",
"position": [
-720,
2912
],
"webhookId": "7cadf9c3-f927-4738-aa85-11fb035ffcf5",
"parameters": {
"options": {},
"trigger": [
"message"
],
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09CVLMSF3R",
"cachedResultName": "issue-smarteremr"
}
},
"credentials": {
"slackApi": {
"id": "rNqvWj9TfChPVRYY",
"name": "Slack account"
}
},
"typeVersion": 1
},
{
"id": "65a9703b-d356-442c-99a5-8d2351843374",
"name": "Prepare Files for Processing",
"type": "n8n-nodes-base.code",
"position": [
400,
2784
],
"parameters": {
"jsCode": "// Extract files from Parse Message and prepare them for batch processing\nconst parseMessageData = $('Parse Message into Jira Format').first().json;\nconst jiraIssueData = $('Create Jira Issue').first().json;\n\nconsole.log('Parse Message Data:', JSON.stringify(parseMessageData, null, 2));\nconsole.log('Jira Issue Data:', JSON.stringify(jiraIssueData, null, 2));\n\n// Extract files from the attachments array (not files array)\nconst files = parseMessageData.attachments || [];\nconst jiraIssueKey = jiraIssueData.key;\n\nconsole.log(`Found ${files.length} files to process`);\nconsole.log('Jira Issue Key:', jiraIssueKey);\n\n// Return each file as a separate item with the Jira issue key\nconst items = files.map((file, index) => {\n return {\n fileId: file.id,\n fileName: file.name || file.title || `file_${index}`,\n fileUrl: file.url, // Use the url property from your attachments\n jiraIssueKey: jiraIssueKey,\n fileIndex: index,\n totalFiles: files.length,\n originalFile: file\n };\n});\n\nconsole.log('Prepared items for batch processing:', JSON.stringify(items, null, 2));\n\nreturn items;"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "3b52b68f-beb7-4f72-a1db-439761d9235a",
"name": "Split Files into Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
624,
2784
],
"parameters": {
"options": {
"reset": false
}
},
"typeVersion": 3
},
{
"id": "23c27f8e-283e-4247-9103-1cf5b8052801",
"name": "Upload Attachment to Jira",
"type": "n8n-nodes-base.jira",
"position": [
1296,
2736
],
"parameters": {
"issueKey": "={{ $('Split Files into Batches').item.json.jiraIssueKey }}",
"resource": "issueAttachment"
},
"credentials": {
"jiraSoftwareCloudApi": {
"id": "Q6d7sLBVOfGWmaLw",
"name": "Jira SW Cloud account 3"
}
},
"typeVersion": 1
},
{
"id": "749ae50d-dec2-4245-a560-24b689250fdc",
"name": "checking message",
"type": "n8n-nodes-base.if",
"position": [
-496,
2912
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0eb704ae-11e8-4588-a0fb-02b1f7c1cde7",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $json.text }}",
"rightValue": "title"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e74b893a-4c33-4de3-bc1e-d82f2f792e7a",
"name": "Reply to Channel On Slack",
"type": "n8n-nodes-base.slack",
"position": [
848,
2784
],
"webhookId": "326747fc-4f09-4a30-9836-ead0ec1316c1",
"parameters": {
"text": "=✅ Jira Issue Created Successfully!\n\n🎫 Issue Key: https://herevivekpatidar.atlassian.net/browse/{{ $('Create Jira Issue').item.json.key }}\n\n📝 Title: {{ $('Parse Message into Jira Format').item.json.summary }} \n\n📝 Description:{{ $('Parse Message into Jira Format').item.json.extractedData.descriptionMatch }}\n\n📋 issueType: {{ $('Parse Message into Jira Format').item.json.issueTypeName }}\n\n⚡Priority: {{ $('Parse Message into Jira Format').item.json.priority }}\n\n📎 Attachments: {{ $('Parse Message into Jira Format').item.json.files.length }} file(s) uploaded\n\nThank you for reporting this issue!",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09D7N4MXFF",
"cachedResultName": "tickets"
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"id": "DCKcEblxPx2EbUUX",
"name": "Slack account 3"
}
},
"typeVersion": 2.1
},
{
"id": "68fa2a54-85a5-42cb-99c1-3a6c398a7226",
"name": "Parse Message into Jira Format",
"type": "n8n-nodes-base.code",
"position": [
-272,
2912
],
"parameters": {
"jsCode": "// Enhanced Parse Slack message - handles both plain text and rich text blocks\nconst message = $input.first().json;\nlet text = message.text || '';\nconst user = message.user || '';\nconst channel = message.channel || '';\nconst files = message.files || [];\nconst timestamp = message.ts || '';\nconst blocks = message.blocks || [];\n\nconsole.log('Original text length:', text.length);\nconsole.log('Blocks found:', blocks.length);\nconsole.log('Files found:', files.length);\n\n// Extract text from rich text blocks if available (this gives us complete text)\nif (blocks && blocks.length > 0) {\n let richText = '';\n \n blocks.forEach(block => {\n if (block.type === 'rich_text' && block.elements) {\n block.elements.forEach(element => {\n if (element.type === 'rich_text_section' && element.elements) {\n element.elements.forEach(textElement => {\n if (textElement.type === 'text') {\n richText += textElement.text || '';\n }\n });\n } else if (element.type === 'rich_text_list' && element.elements) {\n // Handle bullet points and lists\n element.elements.forEach(listItem => {\n if (listItem.elements) {\n richText += '\\n• ';\n listItem.elements.forEach(listTextElement => {\n if (listTextElement.type === 'text') {\n richText += listTextElement.text || '';\n }\n });\n }\n });\n }\n });\n }\n });\n \n // Use rich text if it's longer and contains more content\n if (richText.length > text.length) {\n console.log('Using rich text content (length:', richText.length, ')');\n text = richText;\n }\n}\n\nconsole.log('Final text length:', text.length);\nconsole.log('Text preview:', text.substring(0, 200) + '...');\n\n// Log file details for debugging\nfiles.forEach((file, index) => {\n console.log(`File ${index}:`, {\n id: file.id,\n name: file.name,\n mimetype: file.mimetype,\n size: file.size,\n filetype: file.filetype\n });\n});\n\n// Robust regex patterns for title*:* format with flexible spacing\nconst titleMatch = text.match(/title\\s*\\*?\\s*:\\s*\\*?\\s*([^\\n]*?)(?=\\s*(?:\\n|$))/i);\n\n// For description, capture everything after description*:* until we hit priority: or type:\nconst descriptionMatch = text.match(/description\\s*\\*?\\s*:\\s*\\*?\\s*([\\s\\S]*?)(?=\\s*priority\\s*\\*?\\s*:\\s*\\*?|$)/i);\n\n// Priority - capture just the value after priority:\nconst priorityMatch = text.match(/priority\\s*\\*?\\s*:\\s*\\*?\\s*([^\\n]*?)(?=\\s*(?:\\n|$))/i);\n\n// Type - capture just the value after type:\nconst typeMatch = text.match(/type\\s*\\*?\\s*:\\s*\\*?\\s*([^\\n]*?)(?=\\s*(?:\\n|$))/i);\n\n// Enhanced text cleaning function\nconst cleanText = (str) => {\n if (!str) return null;\n \n return str\n .replace(/^\\s*[\\*_\\-\\+=]*\\s*/, '') // Remove leading special characters\n .replace(/\\s*[\\*_\\-\\+=]*\\s*$/, '') // Remove trailing special characters\n .replace(/\\*+/g, '') // Remove asterisks\n .replace(/_{2,}/g, '') // Remove multiple underscores\n .replace(/^\\s+/gm, '') // Remove leading whitespace from lines\n .replace(/\\s+$/gm, '') // Remove trailing whitespace from lines\n .replace(/\\n\\s*\\n+/g, '\\n\\n') // Normalize multiple newlines\n .trim();\n};\n\n// Clean and extract values\nconst extractedTitle = titleMatch ? cleanText(titleMatch[1]) : null;\nconst extractedDescription = descriptionMatch ? cleanText(descriptionMatch[1]) : null;\nconst extractedPriority = priorityMatch ? cleanText(priorityMatch[1]) : null;\nconst extractedType = typeMatch ? cleanText(typeMatch[1]) : null;\n\n// Enhanced logging\nconsole.log('=== EXTRACTION RESULTS ===');\nconsole.log('Title match:', !!titleMatch, '- Value:', extractedTitle);\nconsole.log('Description match:', !!descriptionMatch, '- Length:', extractedDescription ? extractedDescription.length : 0);\nconsole.log('Priority match:', !!priorityMatch, '- Value:', extractedPriority);\nconsole.log('Type match:', !!typeMatch, '- Value:', extractedType);\n\n// Smart fallback logic\nconst summary = (extractedTitle && extractedTitle.length > 3) ? \n extractedTitle : 'Issue reported from Slack';\n\nconst description = (extractedDescription && extractedDescription.length > 5) ? \n extractedDescription : 'No description provided';\n\n// Enhanced priority parsing\nconst determinePriority = (priorityText) => {\n if (!priorityText) return 'medium';\n \n const lowerPriority = priorityText.toLowerCase().trim();\n const cleanPriority = lowerPriority.replace(/[^\\w\\s]/g, '').trim();\n \n if (['critical', 'urgent', 'highest', 'blocker'].includes(cleanPriority)) return 'critical';\n if (['high'].includes(cleanPriority)) return 'high';\n if (['medium', 'med', 'normal', 'moderate'].includes(cleanPriority)) return 'medium';\n if (['low', 'lowest', 'minor'].includes(cleanPriority)) return 'low';\n \n if (cleanPriority.includes('critical') || cleanPriority.includes('urgent')) return 'critical';\n if (cleanPriority.includes('high')) return 'high';\n if (cleanPriority.includes('low')) return 'low';\n \n return 'medium';\n};\n\n// Enhanced issue type parsing\nconst determineIssueType = (typeText) => {\n if (!typeText) return 'enhancement';\n \n const lowerType = typeText.toLowerCase().trim();\n const cleanType = lowerType.replace(/[^\\w\\s]/g, '').trim();\n \n const typeMapping = {\n 'bug': 'bug', 'issue': 'bug', 'defect': 'bug', 'error': 'bug', 'problem': 'bug',\n 'feature': 'feature', 'story': 'feature', 'request': 'feature', 'new': 'feature',\n 'enhancement': 'enhancement', 'improvement': 'enhancement', 'modify': 'enhancement', \n 'change': 'enhancement', 'update': 'enhancement', 'enhance': 'enhancement',\n 'task': 'task', 'todo': 'task', 'work': 'task', 'chore': 'task',\n 'epic': 'epic'\n };\n \n if (typeMapping[cleanType]) return typeMapping[cleanType];\n \n for (const [key, value] of Object.entries(typeMapping)) {\n if (cleanType.includes(key)) return value;\n }\n \n return 'enhancement';\n};\n\nconst priority = determinePriority(extractedPriority);\nconst issueType = determineIssueType(extractedType);\n\n// Map to Jira values with IDs\nconst priorityMapping = {\n 'critical': { name: 'Highest', id: '1' },\n 'high': { name: 'High', id: '2' },\n 'medium': { name: 'Medium', id: '3' },\n 'low': { name: 'Low', id: '4' }\n};\nconst jiraPriorityObj = priorityMapping[priority] || priorityMapping['medium'];\nconst jiraPriority = jiraPriorityObj.name;\nconst jiraPriorityId = jiraPriorityObj.id;\n\nconst issueTypeMapping = {\n 'bug': '10041',\n 'feature': '10004',\n 'enhancement': '10008',\n 'task': '10008',\n 'epic': '10000'\n};\nconst jiraIssueType = issueTypeMapping[issueType] || '10008';\n\n// Enhanced file processing\nconst attachments = files.map(file => {\n let downloadUrl = null;\n \n if (file.url_private_download && file.url_private_download.startsWith('https://')) {\n downloadUrl = file.url_private_download;\n } else if (file.url_private && file.url_private.startsWith('https://')) {\n downloadUrl = file.url_private;\n } else if (file.permalink && file.permalink.startsWith('https://')) {\n downloadUrl = file.permalink;\n } else if (file.url_download && file.url_download.startsWith('https://')) {\n downloadUrl = file.url_download;\n }\n \n const isVideo = file.mimetype && file.mimetype.startsWith('video/') || \n ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv'].includes(file.filetype?.toLowerCase());\n const isLargeFile = file.size && file.size > 10485760;\n \n return {\n id: file.id || 'unknown',\n name: file.name || file.title || 'unnamed_file',\n url: downloadUrl,\n size: file.size || 0,\n mimetype: file.mimetype || 'application/octet-stream',\n filetype: file.filetype || 'unknown',\n isVideo: isVideo,\n isLargeFile: isLargeFile,\n sizeFormatted: file.size ? `${(file.size / 1024 / 1024).toFixed(2)} MB` : 'Unknown size'\n };\n}).filter(att => att.url);\n\n// Create clean Jira description\nlet jiraDescription = '';\n\nif (extractedDescription) {\n jiraDescription = extractedDescription + '\\n\\n';\n}\n\n// Add metadata\njiraDescription += `**Reported by:** <@${user}>\\n`;\njiraDescription += `**Channel:** <#${channel}>\\n`;\njiraDescription += `**Timestamp:** ${new Date(parseFloat(timestamp) * 1000).toISOString()}`;\n\n// Add attachments info if present\nif (attachments.length > 0) {\n jiraDescription += '\\n\\n**Attachments:**\\n';\n attachments.forEach((att, index) => {\n jiraDescription += `${index + 1}. ${att.name} (${att.sizeFormatted})`;\n if (att.isVideo) jiraDescription += ' [VIDEO]';\n if (att.isLargeFile) jiraDescription += ' [LARGE FILE]';\n jiraDescription += '\\n';\n });\n}\n\nreturn {\n summary,\n description: jiraDescription,\n priority: jiraPriority,\n priorityId: jiraPriorityId,\n issueType: jiraIssueType,\n issueTypeName: issueType,\n reporter: user,\n attachments,\n originalText: text,\n \n // Clear extraction results\n extractedData: {\n titleMatch: extractedTitle,\n descriptionMatch: extractedDescription,\n priorityMatch: extractedPriority,\n typeMatch: extractedType,\n \n // Debugging info\n parsing: {\n titleFound: !!titleMatch,\n descriptionFound: !!descriptionMatch,\n priorityFound: !!priorityMatch,\n typeFound: !!typeMatch,\n titleLength: extractedTitle ? extractedTitle.length : 0,\n descriptionLength: extractedDescription ? extractedDescription.length : 0,\n usedRichText: blocks.length > 0\n }\n },\n \n files: {\n totalFiles: files.length,\n validAttachments: attachments.length,\n videoFiles: attachments.filter(att => att.isVideo).length,\n largeFiles: attachments.filter(att => att.isLargeFile).length,\n attachmentDetails: attachments.map(att => ({\n name: att.name,\n size: att.sizeFormatted,\n type: att.filetype,\n isVideo: att.isVideo,\n isLarge: att.isLargeFile\n }))\n }\n};"
},
"typeVersion": 2
},
{
"id": "a16fadd8-597b-4791-9737-14a22a578d55",
"name": "Create Jira Issue",
"type": "n8n-nodes-base.jira",
"position": [
-48,
2912
],
"parameters": {
"project": {
"__rl": true,
"mode": "list",
"value": "10001",
"cachedResultName": "Kanban"
},
"summary": "={{ $('Parse Message into Jira Format').item.json.summary }}",
"issueType": {
"__rl": true,
"mode": "list",
"value": "10006",
"cachedResultName": "Task"
},
"additionalFields": {
"assignee": {
"__rl": true,
"mode": "list",
"value": "712020:d36fa274-fdb6-45c4-a2c5-8c53a89342d4",
"cachedResultName": "Vivek Patidar"
},
"reporter": {
"__rl": true,
"mode": "list",
"value": "712020:d36fa274-fdb6-45c4-a2c5-8c53a89342d4",
"cachedResultName": "Vivek Patidar"
},
"description": "={{ $('Parse Message into Jira Format').item.json.extractedData.descriptionMatch }}"
}
},
"credentials": {
"jiraSoftwareCloudApi": {
"id": "Q6d7sLBVOfGWmaLw",
"name": "Jira SW Cloud account 3"
}
},
"typeVersion": 1
},
{
"id": "a543ed0b-81a9-4391-a239-82d6d5b06cc1",
"name": "Check Attachments",
"type": "n8n-nodes-base.if",
"position": [
176,
2912
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition1",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $('Parse Message into Jira Format').item.json.files.totalFiles }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2
},
{
"id": "cbe776cf-6812-43d0-a9d3-034688b23f98",
"name": "Get File Info",
"type": "n8n-nodes-base.httpRequest",
"position": [
848,
2592
],
"parameters": {
"url": "=https://slack.com/api/files.info?file={{ $json.fileId }}",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{$credentials.slackApi.accessToken}}"
}
]
}
},
"typeVersion": 4.1
},
{
"id": "29408946-d34e-46d6-90fc-50e8477e8f2f",
"name": "Download Attachment",
"type": "n8n-nodes-base.httpRequest",
"position": [
1072,
2592
],
"parameters": {
"url": "={{ $json.file.url_private_download }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{$credentials.slackApi.accessToken}}"
}
]
}
},
"typeVersion": 4.1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "9d97b85d-0648-470a-8c5a-ed257f4ac92d",
"connections": {
"cbe776cf-6812-43d0-a9d3-034688b23f98": {
"main": [
[
{
"node": "29408946-d34e-46d6-90fc-50e8477e8f2f",
"type": "main",
"index": 0
}
]
]
},
"Slack Trigger": {
"main": [
[
{
"node": "749ae50d-dec2-4245-a560-24b689250fdc",
"type": "main",
"index": 0
}
]
]
},
"749ae50d-dec2-4245-a560-24b689250fdc": {
"main": [
[
{
"node": "68fa2a54-85a5-42cb-99c1-3a6c398a7226",
"type": "main",
"index": 0
}
]
]
},
"a543ed0b-81a9-4391-a239-82d6d5b06cc1": {
"main": [
[
{
"node": "65a9703b-d356-442c-99a5-8d2351843374",
"type": "main",
"index": 0
}
],
[
{
"node": "e74b893a-4c33-4de3-bc1e-d82f2f792e7a",
"type": "main",
"index": 0
}
]
]
},
"a16fadd8-597b-4791-9737-14a22a578d55": {
"main": [
[
{
"node": "a543ed0b-81a9-4391-a239-82d6d5b06cc1",
"type": "main",
"index": 0
}
]
]
},
"29408946-d34e-46d6-90fc-50e8477e8f2f": {
"main": [
[
{
"node": "23c27f8e-283e-4247-9103-1cf5b8052801",
"type": "main",
"index": 0
}
]
]
},
"3b52b68f-beb7-4f72-a1db-439761d9235a": {
"main": [
[
{
"node": "e74b893a-4c33-4de3-bc1e-d82f2f792e7a",
"type": "main",
"index": 0
}
],
[
{
"node": "cbe776cf-6812-43d0-a9d3-034688b23f98",
"type": "main",
"index": 0
}
]
]
},
"23c27f8e-283e-4247-9103-1cf5b8052801": {
"main": [
[
{
"node": "3b52b68f-beb7-4f72-a1db-439761d9235a",
"type": "main",
"index": 0
}
]
]
},
"65a9703b-d356-442c-99a5-8d2351843374": {
"main": [
[
{
"node": "3b52b68f-beb7-4f72-a1db-439761d9235a",
"type": "main",
"index": 0
}
]
]
},
"68fa2a54-85a5-42cb-99c1-3a6c398a7226": {
"main": [
[
{
"node": "a16fadd8-597b-4791-9737-14a22a578d55",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Création de contenu, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Rahul Joshi
@rahul08Rahul Joshi is a seasoned technology leader specializing in the n8n automation tool and AI-driven workflow automation. With deep expertise in building open-source workflow automation and self-hosted automation platforms, he helps organizations eliminate manual processes through intelligent n8n ai agent automation solutions.
Partager ce workflow