N
n8n Store
Workflow Market
Linear to Todoist sync

Linear to Todoist sync

by leo-mathurin0 views

Description

Categories

⚙️ Automation

Nodes Used

n8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.noOpn8n-nodes-base.noOp
PriceFree
Views0
Last Updated11/28/2025
workflow.json
{
  "id": "aC9sCGsVQNLzG2xx",
  "meta": {
    "instanceId": "6e768e1641d5138eab6003235059436fff37b0dfd201aeb913cfc5c011d5b83c",
    "templateCredsSetupCompleted": true
  },
  "name": "Linear to Todoist sync",
  "tags": [],
  "nodes": [
    {
      "id": "eaefa5e3-2158-4804-b3ff-aad4a8f9dcc6",
      "name": "Update task",
      "type": "n8n-nodes-base.todoist",
      "position": [
        2300,
        120
      ],
      "parameters": {
        "taskId": "={{ $('if task already exists3').item.json.id }}",
        "operation": "update",
        "updateFields": {
          "content": "={{ $json.title }}",
          "description": "={{ $('Switch based on action').item.json.data.url }}\n\n{{ $('Switch based on action').item.json.data.description }}  \n\nID: {{ $('Switch based on action').item.json.data.id }}",
          "dueDateTime": "={{ $('Switch based on action').item.json.data.dueDate }}"
        }
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "41a03ae9-a7a9-4a0d-95f4-2851c7c99dab",
      "name": "New issue or updated issue",
      "type": "n8n-nodes-base.linearTrigger",
      "position": [
        -960,
        -100
      ],
      "webhookId": "154092cf-e62c-46fe-80aa-3bbae1734fdc",
      "parameters": {
        "teamId": "5abb18c7-f59d-4516-a97c-fe390fb8b1f8",
        "resources": [
          "issue"
        ],
        "authentication": "oAuth2"
      },
      "credentials": {
        "linearOAuth2Api": {
          "id": "qZNJgALxIFFGCr3w",
          "name": "Linear account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cda5c4d5-d3a4-4e24-aaad-b6e3a42c1bb1",
      "name": "Check if task already exists1",
      "type": "n8n-nodes-base.todoist",
      "position": [
        60,
        -120
      ],
      "parameters": {
        "filters": {
          "filter": "=rechercher : {{ $json.data.id }}"
        },
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "81272e61-dd97-4042-a7d3-4a9c84369aea",
      "name": "if task already exists1",
      "type": "n8n-nodes-base.if",
      "position": [
        280,
        -120
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1043fd3c-7105-4b90-bd25-74a08f6a8822",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": "[Object: {}]"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "40e5429d-ed52-4834-86a7-7757f4fc673b",
      "name": "Remove task",
      "type": "n8n-nodes-base.todoist",
      "position": [
        780,
        20
      ],
      "parameters": {
        "taskId": "={{ $json.id }}",
        "operation": "delete"
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "4c66f3de-dc6c-4dd4-bbb3-4c48089c397e",
      "name": "Do nothing1",
      "type": "n8n-nodes-base.noOp",
      "position": [
        780,
        220
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "714ed999-ac53-49a7-8039-bb0e30551404",
      "name": "Switch based on action",
      "type": "n8n-nodes-base.switch",
      "position": [
        -440,
        -100
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "remove",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "f0de4434-01fe-4dbf-a2ea-6bf76f720a48",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "remove"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "create",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ff29a584-5920-41af-be60-e13a826b9804",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "create"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "update",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "d11fab7a-6492-4ec9-b330-bbee12275857",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "update"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "d2135dd7-f692-4327-a1bc-678456eb1b8c",
      "name": "If action's due date is not empty and assignee is me",
      "type": "n8n-nodes-base.if",
      "position": [
        780,
        400
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2325a438-715c-4afd-a794-77c16b7403c9",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $('Switch based on action').item.json.data.dueDate }}",
              "rightValue": ""
            },
            {
              "id": "12d5a7cf-f620-4b88-9ef2-1c6c84716817",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Switch based on action').item.json.data.assignee.email }}",
              "rightValue": "[email protected]"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "442647f1-94c0-41b2-8577-dca92294316b",
      "name": "Task finished ?",
      "type": "n8n-nodes-base.switch",
      "position": [
        2020,
        20
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Task finished",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "67d03bb8-96b2-4874-a703-340c502033ee",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Switch based on action').item.json.data.state.name }}",
                    "rightValue": "Done"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Task not finished",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "63637eed-a30c-42f7-8216-1388aaabf886",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ [\"Todo\", \"In Progress\", \"Backlog\", \"In Review\"].includes($('Switch based on action').item.json.data.state.name) }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "a89acbf6-ddcb-4143-95f9-07e3c1101b65",
      "name": "Close task",
      "type": "n8n-nodes-base.todoist",
      "position": [
        2300,
        -80
      ],
      "parameters": {
        "taskId": "={{ $('if task already exists3').item.json.id }}",
        "operation": "close"
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "8582c2e8-85c2-46c1-8b86-c989f1646851",
      "name": "If it's a sub-issue",
      "type": "n8n-nodes-base.if",
      "position": [
        1240,
        280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "35cb96a8-7847-436d-b3f5-8b90330d7e7a",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $('Switch based on action').item.json.data.parentId }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9cbe3218-9a39-4f1f-8f4a-d3135c69c1b4",
      "name": "Get parent issue",
      "type": "n8n-nodes-base.linear",
      "position": [
        1460,
        20
      ],
      "parameters": {
        "issueId": "={{ $('Switch based on action').item.json.data.parentId }}",
        "operation": "get",
        "authentication": "oAuth2"
      },
      "credentials": {
        "linearOAuth2Api": {
          "id": "qZNJgALxIFFGCr3w",
          "name": "Linear account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "54d7de2b-e8fb-42cc-b345-f15e4a18aa42",
      "name": "Set title with parent and sub-issue",
      "type": "n8n-nodes-base.set",
      "position": [
        1680,
        20
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "356f6023-2cb1-4974-a7d0-6480a61e6f3c",
              "name": "=title",
              "type": "string",
              "value": "={{ '[' + $json.title + ']' + ' -> ' + $('Switch based on action').item.json.data.title }}"
            },
            {
              "id": "683e47e6-7e08-42e8-a461-0f837ef86c41",
              "name": "",
              "type": "string",
              "value": ""
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "de878754-5b40-409a-a776-b9f4848693b7",
      "name": "Update task1",
      "type": "n8n-nodes-base.todoist",
      "position": [
        2300,
        600
      ],
      "parameters": {
        "taskId": "={{ $json.id }}",
        "operation": "update",
        "updateFields": {
          "content": "={{ $('New issue or updated issue').item.json.data.title }}",
          "description": "={{ $('New issue or updated issue').item.json.data.url }}\n\n{{ $('New issue or updated issue').item.json.data.description }}  \n\nID: {{ $('New issue or updated issue').item.json.data.id }}",
          "dueDateTime": "={{ $('New issue or updated issue').item.json.data.dueDate }}"
        }
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "53686909-20d4-449c-81c6-363b6a42cc28",
      "name": "Task finished ?1",
      "type": "n8n-nodes-base.switch",
      "position": [
        2020,
        300
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Task finished",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "67d03bb8-96b2-4874-a703-340c502033ee",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('New issue or updated issue').item.json.data.state.name }}",
                    "rightValue": "Done"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Task not finished",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "63637eed-a30c-42f7-8216-1388aaabf886",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ [\"Todo\", \"In Progress\", \"Backlog\", \"In Review\"].includes($('New issue or updated issue').item.json.data.state.name) }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "f30f4fa7-06c0-43d2-9e15-b19acc0cdee0",
      "name": "Close task1",
      "type": "n8n-nodes-base.todoist",
      "position": [
        2300,
        300
      ],
      "parameters": {
        "taskId": "={{ $json.id }}",
        "operation": "close"
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "aaa5377c-cfe7-43ab-8331-b8b4e7de4798",
      "name": "Check if task already exists3",
      "type": "n8n-nodes-base.todoist",
      "position": [
        60,
        420
      ],
      "parameters": {
        "filters": {
          "filter": "=rechercher : {{ $json.data.id }}"
        },
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "2d167171-2980-4494-96ee-595891a1bef3",
      "name": "if task already exists3",
      "type": "n8n-nodes-base.if",
      "position": [
        280,
        420
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1043fd3c-7105-4b90-bd25-74a08f6a8822",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": "[Object: {}]"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "d5f9f91b-3374-4937-9c78-a31e82b9cf7d",
      "name": "Do nothing2",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1240,
        900
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "8421b381-0fb8-44a7-91e4-1d421eb841b1",
      "name": "If action's due date is not empty and assignee is me1",
      "type": "n8n-nodes-base.if",
      "position": [
        780,
        800
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2325a438-715c-4afd-a794-77c16b7403c9",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $('Switch based on action').item.json.data.dueDate }}",
              "rightValue": ""
            },
            {
              "id": "12d5a7cf-f620-4b88-9ef2-1c6c84716817",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Switch based on action').item.json.data.assignee.email }}",
              "rightValue": "[email protected]"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8f07bede-8ae7-430b-b7e2-4a7f97e75ecd",
      "name": "If it's a sub-issue1",
      "type": "n8n-nodes-base.if",
      "position": [
        1240,
        700
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "35cb96a8-7847-436d-b3f5-8b90330d7e7a",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $('Switch based on action').item.json.data.parentId }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "155f6e76-9f3f-48d0-b523-7379f0356ed0",
      "name": "Remove task1",
      "type": "n8n-nodes-base.todoist",
      "position": [
        1240,
        500
      ],
      "parameters": {
        "taskId": "={{ $json.id }}",
        "operation": "delete"
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "64308a06-b0d2-4e69-bf96-fda3ace090ae",
      "name": "Get parent issue1",
      "type": "n8n-nodes-base.linear",
      "position": [
        1460,
        600
      ],
      "parameters": {
        "issueId": "={{ $('Switch based on action').item.json.data.parentId }}",
        "operation": "get",
        "authentication": "oAuth2"
      },
      "credentials": {
        "linearOAuth2Api": {
          "id": "qZNJgALxIFFGCr3w",
          "name": "Linear account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b7375565-e771-4997-86ff-d8dd50ccdcd7",
      "name": "Set title with parent and sub-issue1",
      "type": "n8n-nodes-base.set",
      "position": [
        1680,
        600
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "356f6023-2cb1-4974-a7d0-6480a61e6f3c",
              "name": "=title",
              "type": "string",
              "value": "={{ '[' + $json.title + ']' + ' -> ' + $('Switch based on action').item.json.data.title }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "cbe53d00-6983-4eb2-83d5-c316ee42b0d0",
      "name": "Create task2",
      "type": "n8n-nodes-base.todoist",
      "position": [
        1460,
        800
      ],
      "parameters": {
        "labels": [
          "linear"
        ],
        "content": "={{ $('Switch based on action').item.json.data.title }}",
        "options": {
          "description": "={{ $('Switch based on action').item.json.data.url }}\n\n{{ $('Switch based on action').item.json.data.description }}\n\nID:\n{{ $('Switch based on action').item.json.data.id }}",
          "dueDateTime": "={{ $('Switch based on action').item.json.data.dueDate }}"
        },
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "2353872970",
          "cachedResultName": "Inbox"
        }
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "54799714-af97-4c7f-bc7e-68cc17234779",
      "name": "Create task3",
      "type": "n8n-nodes-base.todoist",
      "position": [
        2020,
        600
      ],
      "parameters": {
        "labels": [
          "linear"
        ],
        "content": "={{ $json.title }}",
        "options": {
          "description": "={{ $('Switch based on action').item.json.data.url }}\n\n{{ $('Switch based on action').item.json.data.description }}\n\nID:\n{{ $('Switch based on action').item.json.data.id }}",
          "dueDateTime": "={{ $('Switch based on action').item.json.data.dueDate }}"
        },
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "2353872970",
          "cachedResultName": "Inbox"
        }
      },
      "credentials": {
        "todoistApi": {
          "id": "gnCECSozD5wQfRiI",
          "name": "Todoist account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c2bd8e00-4d06-4800-aa02-bbad49183b8d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1600,
        -280
      ],
      "parameters": {
        "width": 440,
        "height": 1520,
        "content": "## ✨ Try It Out!\nSync your **Linear issues to Todoist** automatically with this n8n workflow. When an issue is created, updated, or completed in Linear, a corresponding task is created, updated, or closed in Todoist.\n\n---\n\n## ⚙️ How It Works\n\n- Triggered by issue changes via `linearTrigger`\n- Routes based on action (`create`, `update`, `remove`)\n- Checks if a matching Todoist task already exists (via issue ID)\n- If the issue has:\n  - A **due date**\n  - And is assigned to **you** (`[email protected]`)  \n  ➤ Then it creates or updates the task accordingly\n- If the issue is marked **Done**, the Todoist task is closed\n- If it's deleted in Linear, the Todoist task is also removed\n- Sub-issues get enriched with their parent title for clarity\n\n---\n\n## 🛠️ Customization\n\n- Replace `[email protected]` with your **Linear email** in the `IF` nodes\n- Adjust which states are synced (e.g. “In Progress”, “Todo”...)\n- Customize the Todoist project, labels, or title formatting\n\n---\n\n## ⚠️ Bi-directional Sync?\n\nThis workflow is **one-way** (Linear ➜ Todoist).  \nBi-directional syncing *might* be possible but isn’t handled here—it would be a cool upgrade!\n\n---\n\n## ✅ Requirements\n\n- n8n with OAuth2 access to **Linear** and **Todoist**\n- Your **Linear email** set in the workflow for filtering\n- A target Todoist project (default: *Inbox*)\n\n---\n\n## 💬 Need Help?\n\nAsk in the [n8n Forum](https://community.n8n.io/) or join the [Discord](https://discord.com/invite/XPKeKXeB7d).\n\nHappy Automating! 🚀\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9b496a22-c2d2-4fff-964d-6c86c022fd11",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1120,
        -280
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 400,
        "content": "## 1. Listen for Linear Issue Events\n[Learn more about the Linear Trigger node](https://docs.n8n.io/integrations/linear/)\n\nThis node captures events from Linear like issue creation, update, or removal—it's the starting point of our workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "e1b9cd74-bd3a-4024-886e-914fb3c6cf62",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -660,
        -280
      ],
      "parameters": {
        "color": 7,
        "width": 540,
        "height": 400,
        "content": "## 2. Route by Action: Create, Update or Remove\n[See how Switch nodes work](https://docs.n8n.io/nodes/n8n-nodes-base.switch/)\n\nBased on the type of action (`create`, `update`, or `remove`), we branch into different flows. Each one handles the task accordingly in Todoist."
      },
      "typeVersion": 1
    },
    {
      "id": "b98a335c-4d60-4464-8d94-0b832801878b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -280
      ],
      "parameters": {
        "color": 7,
        "width": 600,
        "height": 900,
        "content": "## 3. Check for Existing Task in Todoist\n[Explore Todoist Node Docs](https://docs.n8n.io/integrations/todoist/)\n\nBefore creating or updating anything, we check if a task for the Linear issue already exists in Todoist—using a custom search on the issue ID. This helps avoid duplicates."
      },
      "typeVersion": 1
    },
    {
      "id": "a6aa24be-dadb-46b0-b75f-03b1f13b1390",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1160,
        -280
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 1340,
        "content": "## 5. Handle Sub-Issues with Context\n[Example: Fetching Parent Data](https://docs.n8n.io/nodes/n8n-nodes-base.linear/)\n\nIf the Linear issue is a sub-task, we fetch the parent issue's title and combine both to generate a meaningful task name in Todoist like:  \n`[Parent] → Sub-Issue`."
      },
      "typeVersion": 1
    },
    {
      "id": "8c91d12a-2fd8-44b3-aa49-76eca5327ef4",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        -280
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 1340,
        "content": "## 4. Conditional Logic for Updates or Completion\n[Learn about IF & Switch nodes](https://docs.n8n.io/workflows/expressions/conditions/)\n\nWe make sure the issue:\n- Has a due date\n- Is assigned to *you*\n- Is not already completed (or should be marked done in Todoist if the issue is finished)\n\nThis logic helps filter out irrelevant or already-completed issues. You can customize this to your needs."
      },
      "typeVersion": 1
    },
    {
      "id": "65157739-1dbb-4828-b4f6-48ea21a675bc",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1920,
        -280
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 1080,
        "content": "## 6. Create, Update or Close Todoist Tasks\n[Todoist Integration Guide](https://docs.n8n.io/integrations/todoist/)\n\nFinally, based on the logic above, we either:\n- Create a new task in your Todoist project\n- Update an existing task with new title, description, or due date\n- Close the task if the Linear issue is marked as \"Done\""
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "ad8ea79a-1b64-47b0-84c0-46f5c322eb9c",
  "connections": {
    "Task finished ?": {
      "main": [
        [
          {
            "node": "Close task",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get parent issue": {
      "main": [
        [
          {
            "node": "Set title with parent and sub-issue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Task finished ?1": {
      "main": [
        [
          {
            "node": "Close task1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update task1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get parent issue1": {
      "main": [
        [
          {
            "node": "Set title with parent and sub-issue1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If it's a sub-issue": {
      "main": [
        [
          {
            "node": "Get parent issue",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Task finished ?1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If it's a sub-issue1": {
      "main": [
        [
          {
            "node": "Get parent issue1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create task2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch based on action": {
      "main": [
        [
          {
            "node": "Check if task already exists1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check if task already exists3",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check if task already exists3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "if task already exists1": {
      "main": [
        [
          {
            "node": "Remove task",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Do nothing1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "if task already exists3": {
      "main": [
        [
          {
            "node": "If action's due date is not empty and assignee is me",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If action's due date is not empty and assignee is me1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New issue or updated issue": {
      "main": [
        [
          {
            "node": "Switch based on action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if task already exists1": {
      "main": [
        [
          {
            "node": "if task already exists1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if task already exists3": {
      "main": [
        [
          {
            "node": "if task already exists3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set title with parent and sub-issue": {
      "main": [
        [
          {
            "node": "Task finished ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set title with parent and sub-issue1": {
      "main": [
        [
          {
            "node": "Create task3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If action's due date is not empty and assignee is me": {
      "main": [
        [
          {
            "node": "If it's a sub-issue",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Remove task1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If action's due date is not empty and assignee is me1": {
      "main": [
        [
          {
            "node": "If it's a sub-issue1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Do nothing2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

相关工作流