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 Bridge",
  "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 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": "데이터 변환 노트",
      "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 운영 노트",
      "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": "로깅 관리 노트",
      "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": "🗺️ 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 이슈 생성",
      "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 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": "로깅 오류 노트",
      "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": "🎣 Linear 이슈 업데이트됨 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 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": "스티키 노트",
      "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
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 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에서 보기

이 워크플로우 공유

카테고리

카테고리: 34