{
  "id": "TckxPn8Et62aAgUP",
  "name": "Sync Fizzy Cards into Basecamp Todos",
  "tags": [
    {
      "id": "nY4Y2BAklcA0nSbM",
      "name": "Fizzy",
      "createdAt": "2026-02-13T14:28:15.351Z",
      "updatedAt": "2026-02-13T14:28:15.351Z"
    }
  ],
  "nodes": [
    {
      "id": "95404f80-67d4-4cfd-b47c-049375fa16c2",
      "name": "Set Basecamp account ID",
      "type": "n8n-nodes-base.code",
      "position": [
        64,
        912
      ],
      "parameters": {
        "jsCode": "// Configuration - Set your Basecamp Account ID here\nconst BASECAMP_ACCOUNT_ID = \"<Put your account ID Here>\";\n\n// Pass through webhook data and add account ID\nconst webhookData = $input.first().json;\n\nreturn {\n  ...webhookData,\n  basecampAccountId: BASECAMP_ACCOUNT_ID\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "a005d45d-2c21-4d83-9c3e-fb6ec2e8058a",
      "name": "Find todo and prepare update",
      "type": "n8n-nodes-base.code",
      "position": [
        2848,
        896
      ],
      "parameters": {
        "jsCode": "// Get the original route data from Route by Action1 node\nconst routeData = $('Check if New Card').first().json;\n\n// Extract values from route data\nconst fizzyCardId = routeData.fizzyCardId;\nconst fizzyAction = routeData.fizzyAction;\nconst assigneeIds = routeData.assigneeIds;\nconst projectId = routeData.projectId;\nconst cardTitle = routeData.cardTitle;\nconst cardDescription = routeData.cardDescription;\n\n// Get all todos from merged results\nconst allTodos = $input.all().map(item => item.json);\n\nconsole.log(`Searching for Fizzy ID: ${fizzyCardId} among ${allTodos.length} todos`);\n\n// Find the matching todo by Fizzy ID in the description\nconst fizzyIdPattern = new RegExp(`Fizzy ID:\\\\s*${fizzyCardId}`, 'i');\nconst matchedTodo = allTodos.find(todo => {\n  if (!todo.description) return false;\n  const matches = fizzyIdPattern.test(todo.description);\n  if (matches) {\n    console.log(`Found matching todo: ${todo.id} - ${todo.title}`);\n  }\n  return matches;\n});\n\nif (!matchedTodo) {\n  const availableTodos = allTodos.map(t => `ID: ${t.id}, Title: ${t.title}, Description: ${t.description?.substring(0, 100) || 'N/A'}`).join('\\n');\n  throw new Error(`No todo found with Fizzy ID: \"${fizzyCardId}\".\\n\\nSearched ${allTodos.length} todos.\\n\\nAvailable todos:\\n${availableTodos}`);\n}\n\nconsole.log(`Successfully matched todo ${matchedTodo.id} for Fizzy card ${fizzyCardId}`);\n\n// Prepare the output based on action type\nlet output = {\n  todoId: matchedTodo.id,\n  projectId: projectId,\n  fizzyAction: fizzyAction,\n  currentAssignees: matchedTodo.assignees || [],\n  assigneeIds: assigneeIds,\n  cardTitle: cardTitle,\n  cardDescription: cardDescription,\n  fizzyCardId: fizzyCardId,\n  currentStatus: matchedTodo.status,\n  currentCompleted: matchedTodo.completed\n};\n\n// For status changes, determine the new status\nif (fizzyAction === 'card_closed') {\n  output.shouldComplete = true;\n  output.shouldReopen = false;\n} else if (fizzyAction === 'card_reopened') {\n  output.shouldComplete = false;\n  output.shouldReopen = true;\n} else if (fizzyAction === 'card_postponed' || fizzyAction === 'card_auto_postponed' || fizzyAction === 'card_sent_back_to_triage') {\n  // Basecamp doesn't have a \"postponed\" status, so we'll uncomplete it\n  output.shouldComplete = false;\n  output.shouldReopen = true;\n}\n\nreturn output;"
      },
      "typeVersion": 2
    },
    {
      "id": "8598d428-8223-49b6-95bd-4fbc93fe92ef",
      "name": "Receive Fizzy webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -160,
        912
      ],
      "parameters": {
        "path": "fizzyxbasecamp",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "f4fdb48e-3aff-4ac6-bdfb-0396d47ffeaf",
      "name": "Fetch Basecamp projects",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        288,
        816
      ],
      "parameters": {
        "url": "=https://3.basecampapi.com/{{ $('Set Basecamp account ID').first().json.basecampAccountId }}/projects.json",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "basecamp4OAuth2Api"
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "6df604c8-d556-48ac-9f1a-1f8d2166c399",
      "name": "Fetch Basecamp people",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        288,
        1008
      ],
      "parameters": {
        "url": "=https://3.basecampapi.com/{{ $('Set Basecamp account ID').first().json.basecampAccountId }}/people.json",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "basecamp4OAuth2Api"
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "d7a1fe7e-8937-411b-9cbf-b55cf4aa1b93",
      "name": "Combine projects and people",
      "type": "n8n-nodes-base.merge",
      "position": [
        512,
        912
      ],
      "parameters": {},
      "typeVersion": 3
    },
    {
      "id": "eedefdae-d447-4f4f-b0e9-4dd6889e704d",
      "name": "Match project and get todoset",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        912
      ],
      "parameters": {
        "jsCode": "// Get the Fizzy board name from webhook node\nconst webhookData = $('Receive Fizzy webhook').first().json;\nconst fizzyBoardName = webhookData.body.board.name;\nconst fizzyAction = webhookData.body.action;\n\n// Get all Basecamp projects\nconst basecampProjects = $('Fetch Basecamp projects').all();\n\n// Get all Basecamp people\nconst basecampPeople = $('Fetch Basecamp people').all();\n\n// Find matching project (case-insensitive)\nconst matchedProject = basecampProjects.find(item => \n  item.json.name.toLowerCase() === fizzyBoardName.toLowerCase()\n);\n\nif (!matchedProject) {\n  throw new Error(`No Basecamp project found matching Fizzy board: \"${fizzyBoardName}\"`);\n}\n\n// Extract project ID\nconst projectId = matchedProject.json.id;\n\n// Find the \"To-dos\" todoset in the dock\nconst todoset = matchedProject.json.dock.find(item => \n  item.name === 'todoset'\n);\n\nif (!todoset) {\n  throw new Error(`No todoset found in project: \"${matchedProject.json.name}\"`);\n}\n\nconst todosetId = todoset.id;\n\n// Return the IDs to pass to next node\nreturn {\n  projectId: projectId,\n  todosetId: todosetId,\n  boardName: fizzyBoardName,\n  fizzyAction: fizzyAction,\n  webhookData: webhookData,\n  basecampPeople: basecampPeople.map(p => p.json)\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "7f931279-850c-4168-a9fa-ef9594c9f376",
      "name": "Fetch project todolists",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1088,
        912
      ],
      "parameters": {
        "url": "=https://3.basecampapi.com/{{ $('Set Basecamp account ID').first().json.basecampAccountId }}/buckets/{{$json.projectId}}/todosets/{{$json.todosetId}}/todolists.json",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "basecamp4OAuth2Api"
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "7c0a17ba-5b36-4c8d-897a-1050d0a22fd6",
      "name": "Match todolist and assignees",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        912
      ],
      "parameters": {
        "jsCode": "// Get webhook data from previous node\nconst previousNodeData = $('Match project and get todoset').first().json;\nconst webhookData = previousNodeData.webhookData;\nconst basecampPeople = previousNodeData.basecampPeople;\nconst fizzyAction = previousNodeData.fizzyAction;\n\n// Get the first tag from Fizzy card\nconst fizzyTags = webhookData.body.eventable.tags;\n\n// Default to \"Fizzy Todo\" if no tags present\nconst firstTag = (fizzyTags && fizzyTags.length > 0) ? fizzyTags[0] : \"Fizzy Todo\";\n\n// Get all todolists from current input\nconst todolists = $input.all();\n\n// Find matching todolist (case-insensitive)\nconst matchedTodolist = todolists.find(item => {\n  const todolistTitle = item.json.title.toLowerCase();\n  const tagToMatch = firstTag.toLowerCase();\n  return todolistTitle === tagToMatch;\n});\n\n// Get projectId from previous node\nconst projectId = previousNodeData.projectId;\n\n// Match assignees by email\nconst fizzyAssignees = webhookData.body.eventable.assignees || [];\nconst assigneeIds = [];\n\nfor (const fizzyAssignee of fizzyAssignees) {\n  const fizzyEmail = fizzyAssignee.email_address.toLowerCase();\n  \n  const matchedPerson = basecampPeople.find(person => \n    person.email_address.toLowerCase() === fizzyEmail\n  );\n  \n  if (matchedPerson) {\n    assigneeIds.push(matchedPerson.id);\n  }\n}\n\n// Get the Fizzy card ID for mapping\nconst fizzyCardId = webhookData.body.eventable.id;\nconst fizzyCardTitle = webhookData.body.eventable.title;\n\n// Base data object\nconst baseData = {\n  projectId: projectId,\n  cardTitle: fizzyCardTitle,\n  cardDescription: webhookData.body.eventable.description || '',\n  assigneeIds: assigneeIds,\n  fizzyAction: fizzyAction,\n  fizzyCardId: fizzyCardId,\n  todosetId: previousNodeData.todosetId,\n  basecampAccountId: $('Set Basecamp account ID').first().json.basecampAccountId,\n  firstTag: firstTag,\n  isDefaultList: (fizzyTags && fizzyTags.length > 0) ? false : true\n};\n\n// If todolist found, add todolistId and route normally\nif (matchedTodolist) {\n  return {\n    ...baseData,\n    todolistId: matchedTodolist.json.id,\n    todolistFound: true\n  };\n} else {\n  // If no todolist found, flag for creation\n  return {\n    ...baseData,\n    todolistFound: false,\n    newTodolistName: firstTag\n  };\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "c19a89c1-da76-4676-be36-327e80b5c639",
      "name": "Fetch active todos",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2576,
        1184
      ],
      "parameters": {
        "url": "=https://3.basecampapi.com/{{ $json.basecampAccountId }}/buckets/{{ $json.projectId }}/todolists/{{ $json.todolistId }}/todos.json",
        "options": {
          "pagination": {
            "pagination": {
              "nextURL": "={{ $response.headers['link']?.match(/<([^>]+)>;\\s*rel=\"next\"/)?.[1] }}",
              "paginationMode": "responseContainsNextURL",
              "completeExpression": "={{ !$response.headers['link'] || !$response.headers['link'].includes('rel=\"next\"') }}",
              "paginationCompleteWhen": "other"
            }
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "basecamp4OAuth2Api"
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "5196689a-ec15-4e80-8299-4a02a9dd832b",
      "name": "Fetch completed todos",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2576,
        1328
      ],
      "parameters": {
        "url": "=https://3.basecampapi.com/{{ $json.basecampAccountId }}/buckets/{{ $json.projectId }}/todolists/{{ $json.todolistId }}/todos.json?completed=true",
        "options": {
          "pagination": {
            "pagination": {
              "nextURL": "={{ $response.headers['link']?.match(/<([^>]+)>;\\s*rel=\"next\"/)?.[1] }}",
              "paginationMode": "responseContainsNextURL",
              "completeExpression": "={{ !$response.headers['link'] || !$response.headers['link'].includes('rel=\"next\"') }}",
              "paginationCompleteWhen": "other"
            }
          }
        },
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {}
          ]
        },
        "nodeCredentialType": "basecamp4OAuth2Api"
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "43594424-0b87-4df3-83e2-d93556158ccd",
      "name": "Combine all todos",
      "type": "n8n-nodes-base.merge",
      "position": [
        2848,
        1248
      ],
      "parameters": {},
      "typeVersion": 3
    },
    {
      "id": "2c3c4aff-dff1-4e21-a665-21c4dcaa511e",
      "name": "Create new todolist",
      "type": "n8n-nodes-basecamp.basecamp4",
      "position": [
        1472,
        1168
      ],
      "parameters": {
        "name": "={{$json.newTodolistName}}",
        "bucketId": "={{$json.projectId}}",
        "resource": "todolist",
        "operation": "createTodolist",
        "todosetId": "={{$json.todosetId}}",
        "description": "=Auto-created from Fizzy",
        "requestOptions": {}
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "25a7038f-8230-4490-92b7-0b4715e349ed",
      "name": "Check if todolist exists",
      "type": "n8n-nodes-base.if",
      "position": [
        1472,
        912
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "todolist_exists",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.todolistFound }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "795ff0a3-df67-4715-955a-6bbaf542b89d",
      "name": "Add new todolist ID",
      "type": "n8n-nodes-base.code",
      "position": [
        1680,
        1168
      ],
      "parameters": {
        "jsCode": "// Get the created todolist data\nconst createdTodolist = $input.first().json;\n\n// Get the original data from Match Todolist & Assignees node\nconst originalData = $('Match todolist and assignees').first().json;\n\n// Merge the new todolist ID with the original data\nreturn {\n  ...originalData,\n  todolistId: createdTodolist.id,\n  todolistFound: true\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "8a8b7b46-1dc6-4890-8d19-ac2148038970",
      "name": "Create new todo",
      "type": "n8n-nodes-basecamp.basecamp4",
      "position": [
        2112,
        896
      ],
      "parameters": {
        "notify": true,
        "content": "={{$json.cardTitle}}",
        "bucketId": "={{$json.projectId}}",
        "resource": "todo",
        "operation": "createTodo",
        "todolistId": "={{$json.todolistId}}",
        "assigneeIds": "={{$json.assigneeIds}}",
        "description": "=Fizzy ID: {{$json.fizzyCardId}} - Please Don't Delete!\n\n{{$json.cardDescription}}",
        "requestOptions": {}
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0507e272-9632-4894-9c84-bc658b16f016",
      "name": "Check if assignment change",
      "type": "n8n-nodes-base.if",
      "position": [
        3264,
        896
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "is_assign",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_assigned"
            },
            {
              "id": "a3e33eb6-a171-4648-863c-8c0c1f05098a",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_unassigned"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "3c2632f9-66a0-4faf-8ecf-3d3116cf375e",
      "name": "Update todo assignees",
      "type": "n8n-nodes-basecamp.basecamp4",
      "position": [
        3488,
        800
      ],
      "parameters": {
        "todoId": "={{$json.todoId}}",
        "content": "={{$json.cardTitle}}",
        "bucketId": "={{$json.projectId}}",
        "resource": "todo",
        "operation": "updateTodo",
        "todoFields": {
          "notify": {
            "notify": true
          },
          "assigneeIds": {
            "assigneeIds": "={{$json.assigneeIds}}"
          },
          "description": {
            "description": "=Fizzy ID: {{$json.fizzyCardId}} - Please Don't Delete!\n\n{{$json.cardDescription}}"
          }
        },
        "requestOptions": {}
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c8806e91-b8cc-4c56-8a55-e02a468451f0",
      "name": "Check if card closed",
      "type": "n8n-nodes-base.if",
      "position": [
        3488,
        992
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is_closed",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_closed"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "69001a54-92c8-40ae-966b-7d4e8e8d69ec",
      "name": "Mark todo as complete",
      "type": "n8n-nodes-basecamp.basecamp4",
      "position": [
        3712,
        896
      ],
      "parameters": {
        "todoId": "={{$json.todoId}}",
        "bucketId": "={{$json.projectId}}",
        "resource": "todo",
        "operation": "completeTodo",
        "requestOptions": {}
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "20166541-01ea-4862-9816-7707b89ce8e5",
      "name": "Mark todo as incomplete",
      "type": "n8n-nodes-basecamp.basecamp4",
      "position": [
        3936,
        1088
      ],
      "parameters": {
        "todoId": "={{$json.todoId}}",
        "bucketId": "={{$json.projectId}}",
        "resource": "todo",
        "operation": "uncompleteTodo",
        "requestOptions": {}
      },
      "credentials": {
        "basecamp4OAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5c87b77a-1c95-4af3-9286-1adc4cfb7816",
      "name": "Check if card reopened",
      "type": "n8n-nodes-base.if",
      "position": [
        3712,
        1088
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "is_reopen",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_reopened"
            },
            {
              "id": "8a109a14-f93a-4815-a804-ed0c5cdb235b",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_postponed"
            },
            {
              "id": "00f74454-0323-4c43-9ae3-f6fcf4bf2ab2",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_auto_postponed"
            },
            {
              "id": "cc752d9a-97bb-4e00-820e-e3934484e133",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_sent_back_to_triage"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "1b6b8631-160d-40e1-8d41-f4f623cbf688",
      "name": "Setup instructions",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        -80
      ],
      "parameters": {
        "width": 880,
        "height": 624,
        "content": "## Setup steps\n\n**1. Install Basecamp community node**\nInstall from: https://www.npmjs.com/package/n8n-nodes-basecamp\n\n**2. Configure Basecamp credentials**\nCreate integration: https://launchpad.37signals.com/integrations\nAdd credentials in n8n with your Client ID and Client Secret\n\n**3. Set your account ID**\nUpdate the \"Set Basecamp account ID\" node with your Account ID\n\n**4. Prepare your Basecamp project**\n- Create project matching your Fizzy board name exactly\n- Enable Todos tool in project settings\n\n**5. Configure Fizzy webhook**\n\n- Each board needs its own webhook:\n- Click globe icon in Fizzy board\n- Paste webhook URL from \"Receive Fizzy webhook\" node\n- Enable all events\n\n## How it works\n\nThis workflow syncs Fizzy cards to Basecamp todos in real-time. When cards are created, assigned, or closed in Fizzy, the corresponding todos update automatically in Basecamp. Card tags determine the todolist, and assignees sync by email match."
      },
      "typeVersion": 1
    },
    {
      "id": "8cfb232e-0c3e-4434-a7d6-1325fcf3bc9b",
      "name": "Initial setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -224,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 624,
        "content": "Receives webhook from Fizzy and fetches Basecamp data"
      },
      "typeVersion": 1
    },
    {
      "id": "43c90a16-2901-4f80-9fcf-8d58b9f22aa1",
      "name": "Project matching",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 1072,
        "height": 800,
        "content": "Matches Fizzy Data to Basecamp Data (Projects, Todoset, Todolist)"
      },
      "typeVersion": 1
    },
    {
      "id": "17f46172-7d8a-4025-bec1-c8a1ae2f86d8",
      "name": "Create path",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2016,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 800,
        "content": "Creates new todo when fizzy card status is equal to published (New)"
      },
      "typeVersion": 1
    },
    {
      "id": "150593f5-f87e-4b15-8ba1-50edc2990fd2",
      "name": "Update path",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2480,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 960,
        "content": "Updates existing todo when card changes"
      },
      "typeVersion": 1
    },
    {
      "id": "a8b2a1c5-1e62-45a5-84bf-887365f3dff7",
      "name": "Status changes",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3168,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 992,
        "height": 816,
        "content": "Handles assignment updates and completion status"
      },
      "typeVersion": 1
    },
    {
      "id": "b98f4005-336a-4e44-be28-840e6952ccf0",
      "name": "Check if New Card",
      "type": "n8n-nodes-base.if",
      "position": [
        2128,
        1168
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "action_create",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.fizzyAction }}",
              "rightValue": "card_published"
            }
          ]
        }
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "1dc5ca67-d4d3-46c9-a197-f620d70ce5a7",
  "connections": {
    "Check if New Card": {
      "main": [
        [
          {
            "node": "Create new todo",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch active todos",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch completed todos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine all todos": {
      "main": [
        [
          {
            "node": "Find todo and prepare update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch active todos": {
      "main": [
        [
          {
            "node": "Combine all todos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add new todolist ID": {
      "main": [
        [
          {
            "node": "Check if New Card",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create new todolist": {
      "main": [
        [
          {
            "node": "Add new todolist ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if card closed": {
      "main": [
        [
          {
            "node": "Mark todo as complete",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check if card reopened",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Basecamp people": {
      "main": [
        [
          {
            "node": "Combine projects and people",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Fetch completed todos": {
      "main": [
        [
          {
            "node": "Combine all todos",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Receive Fizzy webhook": {
      "main": [
        [
          {
            "node": "Set Basecamp account ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if card reopened": {
      "main": [
        [
          {
            "node": "Mark todo as incomplete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Basecamp projects": {
      "main": [
        [
          {
            "node": "Combine projects and people",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch project todolists": {
      "main": [
        [
          {
            "node": "Match todolist and assignees",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Basecamp account ID": {
      "main": [
        [
          {
            "node": "Fetch Basecamp projects",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Basecamp people",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if todolist exists": {
      "main": [
        [
          {
            "node": "Check if New Card",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create new todolist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if assignment change": {
      "main": [
        [
          {
            "node": "Update todo assignees",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check if card closed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine projects and people": {
      "main": [
        [
          {
            "node": "Match project and get todoset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find todo and prepare update": {
      "main": [
        [
          {
            "node": "Check if assignment change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match todolist and assignees": {
      "main": [
        [
          {
            "node": "Check if todolist exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match project and get todoset": {
      "main": [
        [
          {
            "node": "Fetch project todolists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}