{
  "name": "Freshdesk-YOUR_OPENAI_KEY_HERE 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": "## \ud83c\udfa3 Webhook Triggers & Data Entry\n\n*Entry points that initiate the synchronization workflow:*\n\n\u2022 **New Ticket Webhook** - Captures newly created Freshdesk tickets via POST endpoint\n\u2022 **Update Ticket Webhook** - Handles modifications to existing Freshdesk tickets\n\n*These webhooks serve as the primary triggers that start the Freshdesk-YOUR_OPENAI_KEY_HERE-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": "## \ud83d\udcc4 Data Transformation & Field Mapping\n\n*Critical Data Processing (Field Mapping):\n\u2022 Freshdesk \u2192 Linear \u2014 Converts ticket data into Linear-ready format, including priority (Low/Medium/High/Urgent \u2194 4/3/2/1) and status (Open/Pending/Resolved/Closed \u2194 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": "## \ud83c\udfaf API Operations & External Integration\n\n*Direct communication with external platforms:*\n\n\u2022 **Create Linear Issue** - Makes GraphQL mutation calls to Linear API for issue creation\n\u2022 **Check Linear Creation Success** - Validates successful API response before proceeding\n\u2022 **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": "## \ud83d\udcca Logging & Operation Management\n\n*Comprehensive monitoring and audit trail system:*\n\n\u2022 **Log Linear Creation Success** - Records successful operations with timestamps and IDs\n\u2022 **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": "\ud83d\uddfa\ufe0f Map Freshdesk Fields to 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": "\ud83c\udfaf Create 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": "\u2705 Check Linear Creation Success",
      "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": "\ud83d\udd17 Link Freshdesk with Linear ID",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1440,
        2080
      ],
      "parameters": {
        "url": "=https://{{ $vars.FRESHDESK_DOMAIN }}.freshdesk.com/api/v2/tickets/{{ $('\ud83d\uddfa\ufe0f 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": "\u274c Log Linear Creation Error",
      "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": "\ud83c\udf89 Log Linear Creation Success",
      "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": "\ud83c\udd95 New 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": "\ud83d\udcc4 Update 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": "## \ud83c\udfa3 Webhook Trigger & Data Entry\n\n*Entry point for Linear-to-Freshdesk synchronization:*\n\n\u2022 **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": "## \ud83d\udcca Logging & Error Management\n\n*Comprehensive monitoring for reverse sync operations:*\n\n\u2022 **Log Freshdesk Update Success** - Records successful ticket updates with timestamps and IDs\n\u2022 **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": "\ud83c\udfa3 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": "\ud83d\udcc4 Map Linear to Freshdesk Fields",
      "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": "\ud83d\udd0d Check if Freshdesk Ticket ID Exists",
      "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": "\ud83c\udfab Update Freshdesk Ticket",
      "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": "\u26a0\ufe0f Log Missing Ticket ID Error",
      "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": "\u2705 Log Freshdesk Update Success",
      "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": "## \ud83c\udfaf API Operations & Validation\n\n*External communication and data integrity checks:*\n\n\u2022 **Check if Freshdesk Ticket ID Exists** - Validates that Linear issue contains valid Freshdesk ticket reference\n\u2022 **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": "## \ud83d\udcc4 Data Transformation & Field Mapping\n\n*Critical data processing back to Freshdesk:\n\u2022 Map Linear \u2192 Freshdesk Fields \u2014 Converts Linear issue data into Freshdesk format, handling state mapping (todo/backlog\u2192Open, in_progress\u2192Pending, done\u2192Resolved, canceled\u2192Closed), priority conversion (1\u20144 \u2194 4\u20141), and restoring the original Freshdesk ticket ID from the description.*"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "\ud83c\udd95 New Ticket Webhook": {
      "main": [
        [
          {
            "node": "\ud83d\uddfa\ufe0f Map Freshdesk Fields to Linear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udfaf Create Linear Issue": {
      "main": [
        [
          {
            "node": "\u2705 Check Linear Creation Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcc4 Update Ticket Webhook": {
      "main": [
        [
          {
            "node": "\ud83d\uddfa\ufe0f Map Freshdesk Fields to Linear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udfab Update Freshdesk Ticket": {
      "main": [
        [
          {
            "node": "\u2705 Log Freshdesk Update Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2705 Check Linear Creation Success": {
      "main": [
        [
          {
            "node": "\ud83d\udd17 Link Freshdesk with Linear ID",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\u274c Log Linear Creation Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udfa3 Linear Issue Updated Webhook": {
      "main": [
        [
          {
            "node": "\ud83d\udcc4 Map Linear to Freshdesk Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd17 Link Freshdesk with Linear ID": {
      "main": [
        [
          {
            "node": "\ud83c\udf89 Log Linear Creation Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcc4 Map Linear to Freshdesk Fields": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d Check if Freshdesk Ticket ID Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\uddfa\ufe0f Map Freshdesk Fields to Linear": {
      "main": [
        [
          {
            "node": "\ud83c\udfaf Create Linear Issue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0d Check if Freshdesk Ticket ID Exists": {
      "main": [
        [
          {
            "node": "\ud83c\udfab Update Freshdesk Ticket",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\u26a0\ufe0f Log Missing Ticket ID Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}