Freshdesk-Linear Bridge

Avancé

Ceci est unContent Creation, Multimodal AIworkflow d'automatisation du domainecontenant 22 nœuds.Utilise principalement des nœuds comme If, Webhook, Function, HttpRequest. Synchronisation bidirectionnelle des tickets entre Freshdesk et Linear avec journalisation des erreurs

Prérequis
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)
  • Peut nécessiter les informations d'identification d'authentification de l'API cible
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "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": "🗺️ Mapper les champs Freshdesk vers 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": "🎯 Créer un ticket 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": "✅ Vérifier la création 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": "🔗 Lier Freshdesk avec l'ID 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": "❌ Journaliser l'erreur de création 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": "🎉 Journaliser la création Linear réussie",
      "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": "🆕 Nouveau 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": "📄 Mettre à jour le 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": "🎣 Ticket Linear mis à jour Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        560,
        2912
      ],
      "parameters": {
        "path": "linear-issue-updated",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "8fc267ea-44fd-43e3-84e1-26a104e7d36e",
      "name": "📄 Mapper Linear vers les champs 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": "🔍 Vérifier si l'ID ticket Freshdesk existe",
      "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": "🎫 Mettre à jour le ticket 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": "⚠️ Journaliser l'erreur d'ID manquant",
      "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": "✅ Journaliser la mise à jour Freshdesk réussie",
      "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
          }
        ]
      ]
    }
  }
}
Foire aux questions

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.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds22
Catégorie2
Types de nœuds5
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Auteur
Avkash Kakdiya

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.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34