Puente Freshdesk-Linear
Este es unContent Creation, Multimodal AIflujo de automatización del dominio deautomatización que contiene 22 nodos.Utiliza principalmente nodos como If, Webhook, Function, HttpRequest. Sincronización bidireccional de tickets entre Freshdesk y Linear, con registro de errores
- •Punto final de HTTP Webhook (n8n generará automáticamente)
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (22)
Categoría
{
"name": "Freshdesk-Linear Bridge",
"tags": [],
"nodes": [
{
"id": "dee7aabb-d434-45f3-8a13-9f4f75c96895",
"name": "Webhook Triggers Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
1712
],
"parameters": {
"width": 322,
"height": 736,
"content": "## 🎣 Webhook Triggers & Data Entry\n\n*Entry points that initiate the synchronization workflow:*\n\n• **New Ticket Webhook** - Captures newly created Freshdesk tickets via POST endpoint\n• **Update Ticket Webhook** - Handles modifications to existing Freshdesk tickets\n\n*These webhooks serve as the primary triggers that start the Freshdesk-to-Linear synchronization process, automatically routing incoming ticket data to the field mapping stage.*"
},
"typeVersion": 1
},
{
"id": "3a2f18c2-4c61-440e-85ca-4957bd9d10ba",
"name": "Data Transformation Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
720,
1712
],
"parameters": {
"color": 2,
"width": 210,
"height": 736,
"content": "## 📄 Data Transformation & Field Mapping\n\n*Critical Data Processing (Field Mapping):\n• Freshdesk → Linear — Converts ticket data into Linear-ready format, including priority (Low/Medium/High/Urgent ↔ 4/3/2/1) and status (Open/Pending/Resolved/Closed ↔ todo/in_progress/done/canceled), with proper title/description formatting.*"
},
"typeVersion": 1
},
{
"id": "6f04cd1c-77e6-4e4b-89c3-a671be46f916",
"name": "API Operations Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
944,
1712
],
"parameters": {
"color": 3,
"width": 434,
"height": 734,
"content": "## 🎯 API Operations & External Integration\n\n*Direct communication with external platforms:*\n\n• **Create Linear Issue** - Makes GraphQL mutation calls to Linear API for issue creation\n• **Check Linear Creation Success** - Validates successful API response before proceeding\n• **Link Freshdesk with Linear ID** - Updates Freshdesk ticket with Linear issue reference for bidirectional linking\n\n*These nodes handle the core integration logic, ensuring reliable data exchange between platforms with proper authentication and error validation.*"
},
"typeVersion": 1
},
{
"id": "0daec925-562a-43d9-92d6-5501f3567460",
"name": "Logging Management Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
1712
],
"parameters": {
"color": 5,
"width": 450,
"height": 736,
"content": "## 📊 Logging & Operation Management\n\n*Comprehensive monitoring and audit trail system:*\n\n• **Log Linear Creation Success** - Records successful operations with timestamps and IDs\n• **Log Linear Creation Error** - Captures detailed failure information for debugging\n\n*This logging system provides complete visibility into sync operations, enabling easy troubleshooting and maintaining audit trails for all ticket-to-issue creation processes.*"
},
"typeVersion": 1
},
{
"id": "90550747-96c5-4c2f-9db1-6f9b69e357ba",
"name": "🗺️ Mapear Campos de Freshdesk a Linear",
"type": "n8n-nodes-base.function",
"position": [
768,
2176
],
"parameters": {
"functionCode": "// Map Freshdesk priority to Linear priority\nconst freshdeskPriority = items[0].json.priority;\nlet linearPriority = 0;\n\nswitch(freshdeskPriority) {\n case 1: // Low\n linearPriority = 4;\n break;\n case 2: // Medium\n linearPriority = 3;\n break;\n case 3: // High\n linearPriority = 2;\n break;\n case 4: // Urgent\n linearPriority = 1;\n break;\n default:\n linearPriority = 3;\n}\n\n// Map Freshdesk status to Linear state\nconst freshdeskStatus = items[0].json.status;\nlet linearStateId = 'todo'; // Default to todo state\n\nswitch(freshdeskStatus) {\n case 2: // Open\n linearStateId = 'todo';\n break;\n case 3: // Pending\n linearStateId = 'in_progress';\n break;\n case 4: // Resolved\n linearStateId = 'done';\n break;\n case 5: // Closed\n linearStateId = 'canceled';\n break;\n}\n\nreturn [{\n json: {\n ...items[0].json,\n linearPriority: linearPriority,\n linearStateId: linearStateId,\n linearTitle: items[0].json.subject || 'Freshdesk Ticket #' + items[0].json.id,\n linearDescription: items[0].json.description_text || items[0].json.description || 'No description provided'\n }\n}];"
},
"typeVersion": 1
},
{
"id": "3b240bad-52b3-4d2f-87de-62ed8594ce53",
"name": "🎯 Crear Issue en Linear",
"type": "n8n-nodes-base.httpRequest",
"position": [
992,
2176
],
"parameters": {
"url": "https://api.linear.app/graphql",
"options": {},
"sendBody": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{}
]
},
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "={{ $vars.LINEAR_API_KEY }}"
}
]
}
},
"typeVersion": 4
},
{
"id": "b1beacfa-51d9-45e1-8e30-14c63cd6d4a2",
"name": "✅ Verificar Éxito de Creación en Linear",
"type": "n8n-nodes-base.if",
"position": [
1216,
2176
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "success_condition",
"operator": {
"type": "boolean",
"operation": "equal"
},
"leftValue": "={{ $json.data.issueCreate.success }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "ee9c5ce0-8ed7-4042-8920-f2b1eeee78c3",
"name": "🔗 Vincular Freshdesk con ID de Linear",
"type": "n8n-nodes-base.httpRequest",
"position": [
1440,
2080
],
"parameters": {
"url": "=https://{{ $vars.FRESHDESK_DOMAIN }}.freshdesk.com/api/v2/tickets/{{ $('🗺️ Map Freshdesk Fields to Linear').item.json.id }}",
"options": {},
"sendBody": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{}
]
},
"genericAuthType": "httpBasicAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4
},
{
"id": "58b14ee7-9633-41c9-abf4-b1019a026681",
"name": "❌ Registrar Error de Creación en Linear",
"type": "n8n-nodes-base.function",
"position": [
1440,
2272
],
"parameters": {
"functionCode": "// Log error details\nconst errorData = {\n timestamp: new Date().toISOString(),\n workflow: 'Sync Freshdesk and Linear tickets',\n error: 'Failed to create Linear issue',\n freshdeskTicketId: items[0].json.id,\n freshdeskTicketSubject: items[0].json.subject,\n linearResponse: items[0].json\n};\n\nconsole.error('Linear Issue Creation Failed:', JSON.stringify(errorData, null, 2));\n\nreturn [{\n json: {\n error: true,\n message: 'Failed to create Linear issue',\n details: errorData\n }\n}];"
},
"typeVersion": 1
},
{
"id": "70b0dac2-16bb-4a06-8d6a-d70ad95d7ced",
"name": "🎉 Registrar Éxito de Creación en Linear",
"type": "n8n-nodes-base.function",
"position": [
1664,
2080
],
"parameters": {
"functionCode": "// Log successful creation\nconst successData = {\n timestamp: new Date().toISOString(),\n workflow: 'Sync Freshdesk and Linear tickets',\n message: 'Successfully created Linear issue and linked to Freshdesk ticket',\n freshdeskTicketId: items[0].json.id,\n linearIssueId: items[0].json.data?.issueCreate?.issue?.id,\n linearIssueKey: items[0].json.data?.issueCreate?.issue?.identifier,\n action: 'create_linear_from_freshdesk'\n};\n\nconsole.log('Creation Success:', JSON.stringify(successData, null, 2));\n\nreturn [{\n json: {\n success: true,\n message: 'Successfully created Linear issue from Freshdesk ticket',\n details: successData\n }\n}];"
},
"typeVersion": 1
},
{
"id": "48c2ca3f-857d-4e4a-9e02-ff3c3741dcfa",
"name": "🆕 Nuevo Ticket Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
544,
2080
],
"parameters": {
"path": "create-ticket",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "f1a4c78a-9a5d-40cd-bb99-136b1b776b54",
"name": "📄 Actualizar Ticket Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
544,
2272
],
"parameters": {
"path": "update-ticket",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "6a1887df-1e4c-4eed-8349-d0671501e1e1",
"name": "Webhook Trigger Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
2480
],
"parameters": {
"width": 324,
"height": 760,
"content": "## 🎣 Webhook Trigger & Data Entry\n\n*Entry point for Linear-to-Freshdesk synchronization:*\n\n• **Linear Webhook - Issue Updated** - Receives webhook notifications when Linear issues are modified\n\n*This webhook serves as the reverse sync trigger, capturing Linear issue updates and initiating the process to sync changes back to corresponding Freshdesk tickets.*"
},
"typeVersion": 1
},
{
"id": "e7943820-74be-4bf5-b823-5b87829444fb",
"name": "Logging Error Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
2480
],
"parameters": {
"color": 5,
"width": 452,
"height": 768,
"content": "## 📊 Logging & Error Management\n\n*Comprehensive monitoring for reverse sync operations:*\n\n• **Log Freshdesk Update Success** - Records successful ticket updates with timestamps and IDs\n• **Log Missing Ticket ID Error** - Captures cases where Linear issues lack Freshdesk ticket references\n\n*This logging system provides visibility into reverse sync operations, enabling troubleshooting of failed updates and maintaining audit trails for Linear-to-Freshdesk synchronization.*"
},
"typeVersion": 1
},
{
"id": "848d05ae-fb8a-473f-be86-4b4c922ba031",
"name": "🎣 Issue de Linear Actualizado Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
560,
2912
],
"parameters": {
"path": "linear-issue-updated",
"options": {}
},
"typeVersion": 1
},
{
"id": "8fc267ea-44fd-43e3-84e1-26a104e7d36e",
"name": "📄 Mapear Campos de Linear a Freshdesk",
"type": "n8n-nodes-base.function",
"position": [
784,
2912
],
"parameters": {
"functionCode": "// Map Linear state to Freshdesk status\nconst linearState = items[0].json.data.state.name.toLowerCase();\nlet freshdeskStatus = 2; // Default to Open\n\nswitch(linearState) {\n case 'todo':\n case 'backlog':\n freshdeskStatus = 2; // Open\n break;\n case 'in progress':\n case 'in_progress':\n freshdeskStatus = 3; // Pending\n break;\n case 'done':\n case 'completed':\n freshdeskStatus = 4; // Resolved\n break;\n case 'canceled':\n case 'cancelled':\n freshdeskStatus = 5; // Closed\n break;\n}\n\n// Map Linear priority to Freshdesk priority\nconst linearPriority = items[0].json.data.priority || 3;\nlet freshdeskPriority = 2; // Default to Medium\n\nswitch(linearPriority) {\n case 1: // Urgent\n freshdeskPriority = 4;\n break;\n case 2: // High\n freshdeskPriority = 3;\n break;\n case 3: // Medium\n freshdeskPriority = 2;\n break;\n case 4: // Low\n freshdeskPriority = 1;\n break;\n}\n\n// Extract Freshdesk ticket ID from Linear issue description\nconst description = items[0].json.data.description || '';\nconst ticketIdMatch = description.match(/Freshdesk Ticket ID: (\\d+)/);\nconst freshdeskTicketId = ticketIdMatch ? ticketIdMatch[1] : null;\n\nreturn [{\n json: {\n ...items[0].json,\n freshdeskStatus: freshdeskStatus,\n freshdeskPriority: freshdeskPriority,\n freshdeskTicketId: freshdeskTicketId,\n linearTitle: items[0].json.data.title,\n linearDescription: items[0].json.data.description\n }\n}];"
},
"typeVersion": 1
},
{
"id": "ba73505f-c43e-4cf1-919a-53d71226fa4c",
"name": "🔍 Verificar si Existe ID de Ticket en Freshdesk",
"type": "n8n-nodes-base.if",
"position": [
1008,
2912
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ticket_id_exists",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.freshdeskTicketId }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "2461420b-58df-4266-8ba6-143842afc09c",
"name": "🎫 Actualizar Ticket en Freshdesk",
"type": "n8n-nodes-base.httpRequest",
"position": [
1232,
2816
],
"parameters": {
"url": "=https://{{ $vars.FRESHDESK_DOMAIN }}.freshdesk.com/api/v2/tickets/{{ $json.freshdeskTicketId }}",
"options": {},
"sendBody": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{}
]
},
"genericAuthType": "httpBasicAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4
},
{
"id": "7b907b6a-1968-4d4e-9eb2-d2458179c95e",
"name": "⚠️ Registrar Error de ID de Ticket Faltante",
"type": "n8n-nodes-base.function",
"position": [
1456,
3088
],
"parameters": {
"functionCode": "// Log error details\nconst errorData = {\n timestamp: new Date().toISOString(),\n workflow: 'Sync Freshdesk and Linear tickets',\n error: 'No Freshdesk Ticket ID found in Linear issue',\n linearIssueId: items[0].json.data.id,\n linearIssueTitle: items[0].json.data.title,\n linearDescription: items[0].json.data.description\n};\n\nconsole.error('Missing Freshdesk Ticket ID:', JSON.stringify(errorData, null, 2));\n\nreturn [{\n json: {\n error: true,\n message: 'No Freshdesk Ticket ID found in Linear issue description',\n details: errorData\n }\n}];"
},
"typeVersion": 1
},
{
"id": "e8bc7b41-59b5-4e5e-945a-33d5f13880dc",
"name": "✅ Registrar Éxito de Actualización en Freshdesk",
"type": "n8n-nodes-base.function",
"position": [
1456,
2816
],
"parameters": {
"functionCode": "// Log successful sync\nconst successData = {\n timestamp: new Date().toISOString(),\n workflow: 'Sync Freshdesk and Linear tickets',\n message: 'Successfully synced Linear issue to Freshdesk ticket',\n freshdeskTicketId: items[0].json.freshdeskTicketId,\n linearIssueId: items[0].json.data?.id,\n action: 'update_freshdesk_from_linear'\n};\n\nconsole.log('Sync Success:', JSON.stringify(successData, null, 2));\n\nreturn [{\n json: {\n success: true,\n message: 'Successfully updated Freshdesk ticket from Linear issue',\n details: successData\n }\n}];"
},
"typeVersion": 1
},
{
"id": "bdbfdef4-f069-452e-ab92-649ce6763a27",
"name": "API Operations Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
960,
2480
],
"parameters": {
"color": 3,
"width": 420,
"height": 768,
"content": "## 🎯 API Operations & Validation\n\n*External communication and data integrity checks:*\n\n• **Check if Freshdesk Ticket ID Exists** - Validates that Linear issue contains valid Freshdesk ticket reference\n• **Update Freshdesk Ticket** - Makes REST API calls to Freshdesk to update ticket with synced data\n\n*These nodes ensure reliable reverse sync by validating ticket linkage before attempting updates and handling the actual API communication with Freshdesk.*"
},
"typeVersion": 1
},
{
"id": "46662f60-8cda-4f1a-ab36-b30b0d2caa44",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
720,
2480
],
"parameters": {
"color": 3,
"width": 224,
"height": 768,
"content": "## 📄 Data Transformation & Field Mapping\n\n*Critical data processing back to Freshdesk:\n• Map Linear → Freshdesk Fields — Converts Linear issue data into Freshdesk format, handling state mapping (todo/backlog→Open, in_progress→Pending, done→Resolved, canceled→Closed), priority conversion (1—4 ↔ 4—1), and restoring the original Freshdesk ticket ID from the description.*"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"connections": {
"48c2ca3f-857d-4e4a-9e02-ff3c3741dcfa": {
"main": [
[
{
"node": "90550747-96c5-4c2f-9db1-6f9b69e357ba",
"type": "main",
"index": 0
}
]
]
},
"3b240bad-52b3-4d2f-87de-62ed8594ce53": {
"main": [
[
{
"node": "b1beacfa-51d9-45e1-8e30-14c63cd6d4a2",
"type": "main",
"index": 0
}
]
]
},
"f1a4c78a-9a5d-40cd-bb99-136b1b776b54": {
"main": [
[
{
"node": "90550747-96c5-4c2f-9db1-6f9b69e357ba",
"type": "main",
"index": 0
}
]
]
},
"2461420b-58df-4266-8ba6-143842afc09c": {
"main": [
[
{
"node": "e8bc7b41-59b5-4e5e-945a-33d5f13880dc",
"type": "main",
"index": 0
}
]
]
},
"b1beacfa-51d9-45e1-8e30-14c63cd6d4a2": {
"main": [
[
{
"node": "ee9c5ce0-8ed7-4042-8920-f2b1eeee78c3",
"type": "main",
"index": 0
}
],
[
{
"node": "58b14ee7-9633-41c9-abf4-b1019a026681",
"type": "main",
"index": 0
}
]
]
},
"848d05ae-fb8a-473f-be86-4b4c922ba031": {
"main": [
[
{
"node": "8fc267ea-44fd-43e3-84e1-26a104e7d36e",
"type": "main",
"index": 0
}
]
]
},
"ee9c5ce0-8ed7-4042-8920-f2b1eeee78c3": {
"main": [
[
{
"node": "70b0dac2-16bb-4a06-8d6a-d70ad95d7ced",
"type": "main",
"index": 0
}
]
]
},
"8fc267ea-44fd-43e3-84e1-26a104e7d36e": {
"main": [
[
{
"node": "ba73505f-c43e-4cf1-919a-53d71226fa4c",
"type": "main",
"index": 0
}
]
]
},
"90550747-96c5-4c2f-9db1-6f9b69e357ba": {
"main": [
[
{
"node": "3b240bad-52b3-4d2f-87de-62ed8594ce53",
"type": "main",
"index": 0
}
]
]
},
"ba73505f-c43e-4cf1-919a-53d71226fa4c": {
"main": [
[
{
"node": "2461420b-58df-4266-8ba6-143842afc09c",
"type": "main",
"index": 0
}
],
[
{
"node": "7b907b6a-1968-4d4e-9eb2-d2458179c95e",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Avanzado - Creación de contenido, IA Multimodal
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Avkash Kakdiya
@itechnotion🚀 Founder of iTechNotion — we build custom AI-powered automation workflows for startups, agencies, and founders. 💡 Specializing in agentic AI systems, content automation, sales funnels, and digital workers. 🔧 14+ years in tech | Building scalable no-code/low-code solutions using n8n, OpenAI, and other API-first tools. 📬 Let’s automate what slows you down.
Compartir este flujo de trabajo