{
  "id": "tE3hI4nSlA4ceibM",
  "name": "Employee Directory Sync \u2013 Microsoft Teams & Coda",
  "tags": [],
  "nodes": [
    {
      "id": "31a3c9f2-4b53-4972-b36e-a50ea2e040da",
      "name": "Daily Employee Sync",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        512
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 24
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "b6eeee08-5e33-4dda-80d7-c0452c1296c5",
      "name": "Fetch HR Employees",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        160,
        528
      ],
      "parameters": {
        "url": "https://api.your-hr-system.com/employees",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "bbdbc85c-c287-4284-bf51-4981cb32f256",
      "name": "Check API Response",
      "type": "n8n-nodes-base.if",
      "position": [
        480,
        448
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.statusCode || 200 }}",
              "value2": 200,
              "operation": "equal"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d85ed4ec-03dc-4e03-908d-5e8df5dd8a1b",
      "name": "Teams Alert - API Failure",
      "type": "n8n-nodes-base.microsoftTeams",
      "position": [
        1264,
        400
      ],
      "parameters": {
        "chatId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "message": "<b>Employee sync failed</b><br/>Unable to fetch employee list from HR system.",
        "options": {},
        "resource": "chatMessage",
        "contentType": "html"
      },
      "typeVersion": 2
    },
    {
      "id": "828d24e3-1f79-4dc7-9788-1636f1498eab",
      "name": "Expand Employee List",
      "type": "n8n-nodes-base.code",
      "position": [
        496,
        608
      ],
      "parameters": {
        "jsCode": "// Split HR API array into one item per employee\nconst employees = items[0].json.body?.employees || [];\nreturn employees.map(e => ({ json: e }));"
      },
      "typeVersion": 2
    },
    {
      "id": "c3845b58-3954-4bb8-8793-935239a9c5bf",
      "name": "Split Employees",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        688,
        576
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "1133e025-855e-4eb4-a690-cc9c69be4464",
      "name": "Map Employee Fields",
      "type": "n8n-nodes-base.code",
      "position": [
        864,
        560
      ],
      "parameters": {
        "jsCode": "// Map fields and add helper flags\nconst emp = items[0].json;\nreturn [\n  {\n    json: {\n      employeeId: emp.id || emp.employeeId,\n      name: `${emp.firstName} ${emp.lastName}`.trim(),\n      email: emp.email,\n      department: emp.department || 'Unknown',\n      status: emp.status || 'inactive',\n      active: (emp.status || '').toLowerCase() === 'active',\n      slackHandle: emp.slackHandle || '',\n      teamsMessage: '',\n      slackMessage: ''\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "b33c61b5-8e19-4b53-ac6d-25118ad46b11",
      "name": "Is Active Employee?",
      "type": "n8n-nodes-base.if",
      "position": [
        1040,
        560
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.active }}",
              "operation": "isTrue"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "eca6ebcb-12de-4796-b30a-6333f5dcdaab",
      "name": "Prepare Coda Row",
      "type": "n8n-nodes-base.set",
      "position": [
        1264,
        560
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "0bdb7a7e-3656-4be3-90ed-e516da3f83c1",
      "name": "Create/Update Employee in Coda",
      "type": "n8n-nodes-base.coda",
      "position": [
        1472,
        560
      ],
      "parameters": {
        "docId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_CODA_DOC_ID"
        },
        "options": {},
        "tableId": {
          "__rl": true,
          "mode": "name",
          "value": "Employees"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7cc835df-542e-4175-a50e-97bd9c78cdda",
      "name": "Set Teams Message (Active)",
      "type": "n8n-nodes-base.set",
      "position": [
        1696,
        560
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "f66ea9fc-408d-44e6-ac21-c1ef450cfc80",
      "name": "Teams Notify - Employee Synced",
      "type": "n8n-nodes-base.microsoftTeams",
      "position": [
        1904,
        560
      ],
      "parameters": {
        "chatId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "message": "={{ $json.teamsMessage }}",
        "options": {},
        "resource": "chatMessage",
        "contentType": "html"
      },
      "typeVersion": 2
    },
    {
      "id": "003318b7-158f-4701-bfbf-edddf63c7a1d",
      "name": "Slack Notify - New Employee",
      "type": "n8n-nodes-base.slack",
      "position": [
        2096,
        560
      ],
      "parameters": {
        "operation": "postMessage"
      },
      "typeVersion": 2.1
    },
    {
      "id": "0d2dbdcd-fe88-420e-90ae-53e9e279a510",
      "name": "Set Teams Message (Inactive)",
      "type": "n8n-nodes-base.set",
      "position": [
        1264,
        752
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "ed7575e1-ab55-49ed-b42b-8539ccc1ff5b",
      "name": "Teams Notify - Employee Inactive",
      "type": "n8n-nodes-base.microsoftTeams",
      "position": [
        1472,
        752
      ],
      "parameters": {
        "chatId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "message": "={{ $json.teamsMessage }}",
        "options": {},
        "resource": "chatMessage",
        "contentType": "html"
      },
      "typeVersion": 2
    },
    {
      "id": "1ff67d58-5022-439b-917f-2cb28cf84beb",
      "name": "Employee Directory Sync \u2013 Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        160
      ],
      "parameters": {
        "width": 550,
        "height": 674,
        "content": "## How it works\nThis workflow runs automatically every 24 hours to synchronize employee information between your HR system and your internal directory in Coda. First, it pulls the complete employee list from the HR API and verifies a successful response. Each employee record is processed one-by-one: fields are mapped, active employees are saved to Coda, and notifications are sent to both Microsoft Teams and Slack. If the HR API call fails, a Teams alert is dispatched immediately so the HR or IT team can investigate.\n\n## Setup steps\n1. Add your HR API base URL and credentials to the HTTP Request node.\n2. Create a Coda doc and table named \u201cEmployees\u201d (or update the table name in the Coda node).\n3. Supply your Coda API credential and doc ID in the Coda node parameters.\n4. Connect a Microsoft Teams OAuth credential and fill in Team & Channel IDs in all Teams nodes.\n5. (Optional) Connect a Slack credential and adjust the channel name if desired.\n6. Review field mappings in the \u201cMap Employee Fields\u201d and \u201cPrepare Coda Row\u201d nodes to match your schema.\n7. Activate the workflow and perform a manual run for validation."
      },
      "typeVersion": 1
    },
    {
      "id": "42c3e44d-7f92-454d-9ad8-7960db594d13",
      "name": "Section \u2013 Retrieval",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 450,
        "height": 590,
        "content": "## Data Retrieval & Validation\nThis section contains the trigger, data-fetch, and validation logic. The *Daily Employee Sync* schedule node fires every 24 hours (adjustable). It immediately calls the HR system\u2019s REST API via the *Fetch HR Employees* HTTP Request node, expecting a structured JSON payload. The subsequent *Check API Response* IF node safeguards the rest of the workflow by confirming that the HTTP status code is 200. If the call fails, an instant Microsoft Teams alert is generated so stakeholders can resolve the issue quickly. By isolating retrieval and validation here, downstream nodes only receive reliable data, reducing unnecessary error handling in later stages."
      },
      "typeVersion": 1
    },
    {
      "id": "db883c40-abef-45cb-b3a2-9af92f398318",
      "name": "Section \u2013 Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 802,
        "height": 590,
        "content": "## Employee Processing\nAfter the raw list arrives, *Expand Employee List* converts it into one-item-per-employee format. The *Split Employees* node ensures batched processing to respect rate limits on both Coda and notification services. The *Map Employee Fields* code node normalizes data so it can be consumed consistently\u2014adding derived fields like the `active` boolean. The *Is Active Employee?* IF node then routes records: active staff proceed to storage and announcements, while inactive individuals merely trigger status notifications. This modular design keeps the processing logic clean, making it easy to add further enrichment steps (e.g., role mapping, manager look-ups) without altering other workflow parts."
      },
      "typeVersion": 1
    },
    {
      "id": "60c9e818-6e51-46f2-a17a-ed730a234cca",
      "name": "Section \u2013 Storage & Notify",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1168,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 1074,
        "height": 702,
        "content": "## Storage & Notifications\nActive employee records flow into *Prepare Coda Row*, translating mapped fields into Coda-ready key/value pairs. The *Create/Update Employee in Coda* node writes each employee into the \u201cEmployees\u201d table, keeping your directory up to date. Success triggers a Teams message (and an optional Slack post) summarizing the action for transparency. Inactive records produce a distinct Teams notification so HR can archive or reactivate as needed. Centralizing storage and messaging here aids maintainability; if your organization adopts additional channels (e.g., email or database storage), you can append nodes inside this gray block without touching upstream logic."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a369e0c8-6f51-4085-93fa-ae58a20b5bf1",
  "connections": {
    "Split Employees": {
      "main": [
        [
          {
            "node": "Map Employee Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Coda Row": {
      "main": [
        [
          {
            "node": "Create/Update Employee in Coda",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check API Response": {
      "main": [
        [
          {
            "node": "Expand Employee List",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Teams Alert - API Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch HR Employees": {
      "main": [
        [
          {
            "node": "Check API Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Employee Sync": {
      "main": [
        [
          {
            "node": "Fetch HR Employees",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Active Employee?": {
      "main": [
        [
          {
            "node": "Prepare Coda Row",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Teams Message (Inactive)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Employee Fields": {
      "main": [
        [
          {
            "node": "Is Active Employee?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Expand Employee List": {
      "main": [
        [
          {
            "node": "Split Employees",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Teams Message (Active)": {
      "main": [
        [
          {
            "node": "Teams Notify - Employee Synced",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Teams Message (Inactive)": {
      "main": [
        [
          {
            "node": "Teams Notify - Employee Inactive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create/Update Employee in Coda": {
      "main": [
        [
          {
            "node": "Set Teams Message (Active)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Teams Notify - Employee Synced": {
      "main": [
        [
          {
            "node": "Slack Notify - New Employee",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}