8
n8n 中文网amn8n.com

Freshdesk-Linear 桥接

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 22 个节点。主要使用 If, Webhook, Function, HttpRequest 等节点。 Freshdesk 与 Linear 之间的双向工单同步,包含错误日志记录

前置要求
  • HTTP Webhook 端点(n8n 会自动生成)
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "name": "Freshdesk-Linear 桥接",
  "tags": [],
  "nodes": [
    {
      "id": "dee7aabb-d434-45f3-8a13-9f4f75c96895",
      "name": "Webhook 触发器说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        1712
      ],
      "parameters": {
        "width": 322,
        "height": 736,
        "content": "## 🎣 Webhook 触发器与数据录入"
      },
      "typeVersion": 1
    },
    {
      "id": "3a2f18c2-4c61-440e-85ca-4957bd9d10ba",
      "name": "数据转换说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        1712
      ],
      "parameters": {
        "color": 2,
        "width": 210,
        "height": 736,
        "content": "## 📄 数据转换与字段映射"
      },
      "typeVersion": 1
    },
    {
      "id": "6f04cd1c-77e6-4e4b-89c3-a671be46f916",
      "name": "API 操作说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        1712
      ],
      "parameters": {
        "color": 3,
        "width": 434,
        "height": 734,
        "content": "## 🎯 API 操作与外部集成"
      },
      "typeVersion": 1
    },
    {
      "id": "0daec925-562a-43d9-92d6-5501f3567460",
      "name": "日志管理说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        1712
      ],
      "parameters": {
        "color": 5,
        "width": 450,
        "height": 736,
        "content": "## 📊 日志记录与操作管理"
      },
      "typeVersion": 1
    },
    {
      "id": "90550747-96c5-4c2f-9db1-6f9b69e357ba",
      "name": "🗺️ 将 Freshdesk 字段映射到 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": "🎯 创建 Linear Issue",
      "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": "✅ 检查 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": "🔗 将 Freshdesk 与 Linear ID 链接",
      "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": "❌ 记录 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": "🎉 记录 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": "🆕 新工单 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": "📄 更新工单 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 触发器说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        2480
      ],
      "parameters": {
        "width": 324,
        "height": 760,
        "content": "## 🎣 Webhook 触发器与数据录入"
      },
      "typeVersion": 1
    },
    {
      "id": "e7943820-74be-4bf5-b823-5b87829444fb",
      "name": "日志错误说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        2480
      ],
      "parameters": {
        "color": 5,
        "width": 452,
        "height": 768,
        "content": "## 📊 日志记录与错误管理"
      },
      "typeVersion": 1
    },
    {
      "id": "848d05ae-fb8a-473f-be86-4b4c922ba031",
      "name": "🎣 Linear Issue Updated Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        560,
        2912
      ],
      "parameters": {
        "path": "linear-issue-updated",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "8fc267ea-44fd-43e3-84e1-26a104e7d36e",
      "name": "📄 将 Linear 映射到 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": "🔍 检查 Freshdesk 工单 ID 是否存在",
      "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": "🎫 更新 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": "⚠️ 记录缺失工单 ID 错误",
      "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": "✅ 记录 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 操作说明1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        2480
      ],
      "parameters": {
        "color": 3,
        "width": 420,
        "height": 768,
        "content": "## 🎯 API 操作与验证"
      },
      "typeVersion": 1
    },
    {
      "id": "46662f60-8cda-4f1a-ab36-b30b0d2caa44",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        2480
      ],
      "parameters": {
        "color": 3,
        "width": 224,
        "height": 768,
        "content": "## 📄 数据转换与字段映射"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "🆕 New Ticket Webhook": {
      "main": [
        [
          {
            "node": "🗺️ Map Freshdesk Fields to Linear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎯 Create Linear Issue": {
      "main": [
        [
          {
            "node": "✅ Check Linear Creation Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "📄 Update Ticket Webhook": {
      "main": [
        [
          {
            "node": "🗺️ Map Freshdesk Fields to Linear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎫 Update Freshdesk Ticket": {
      "main": [
        [
          {
            "node": "✅ Log Freshdesk Update Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "✅ Check Linear Creation Success": {
      "main": [
        [
          {
            "node": "🔗 Link Freshdesk with Linear ID",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "❌ Log Linear Creation Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎣 Linear Issue Updated Webhook": {
      "main": [
        [
          {
            "node": "📄 Map Linear to Freshdesk Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🔗 Link Freshdesk with Linear ID": {
      "main": [
        [
          {
            "node": "🎉 Log Linear Creation Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "📄 Map Linear to Freshdesk Fields": {
      "main": [
        [
          {
            "node": "🔍 Check if Freshdesk Ticket ID Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🗺️ Map Freshdesk Fields to Linear": {
      "main": [
        [
          {
            "node": "🎯 Create Linear Issue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🔍 Check if Freshdesk Ticket ID Exists": {
      "main": [
        [
          {
            "node": "🎫 Update Freshdesk Ticket",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "⚠️ Log Missing Ticket ID Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 内容创作, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量22
分类2
节点类型5
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
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.

外部链接
在 n8n.io 查看

分享此工作流