{
  "name": "Izini events to Microsoft Teams",
  "nodes": [
    {
      "id": "5c759974-df9a-43a9-8110-b002a8918389",
      "name": "Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -60,
        -60
      ],
      "parameters": {
        "color": 4,
        "width": 760,
        "height": 300,
        "content": "## Izini events to Microsoft Teams\n1. Paste your webhook secret (Izini: Developers > Webhooks) into **Sign with your webhook secret**.\n2. Connect Microsoft Teams (a work or school account) and pick the team and channel in **Post to Teams**.\n3. Activate the workflow, copy the production URL of **Izini webhook**, and add it in Izini as a webhook with the events you want.\n\nRequests not signed by Izini, or older than 5 minutes, get 401. A retried delivery is handled once. Guide: https://app.izini.ng/developers/guides/events-to-your-tools"
      }
    },
    {
      "id": "63535e32-d3c3-482d-84c4-1111def7420f",
      "name": "Izini webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "izini-events",
        "responseMode": "responseNode",
        "options": {
          "rawBody": true
        }
      }
    },
    {
      "id": "acef6763-0c51-4b18-88b7-c4d9871f947b",
      "name": "Read raw body",
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        220,
        300
      ],
      "parameters": {
        "operation": "text",
        "destinationKey": "rawBody"
      }
    },
    {
      "id": "21f62c85-f542-4603-8e18-1334cbd5ed64",
      "name": "Sign with your webhook secret",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 1,
      "position": [
        440,
        300
      ],
      "parameters": {
        "action": "hmac",
        "type": "SHA256",
        "value": "={{ $('Izini webhook').item.json.headers['x-izini-timestamp'] }}.{{ $json.rawBody }}",
        "dataPropertyName": "expectedSignature",
        "secret": "PASTE_YOUR_IZINI_WEBHOOK_SECRET",
        "encoding": "hex"
      }
    },
    {
      "id": "88461d2f-7b51-46b7-89c3-58b52c8c46f3",
      "name": "Signed by Izini, sent in the last 5 minutes?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        660,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "leftValue": "={{ $json.expectedSignature }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "rightValue": "={{ $('Izini webhook').item.json.headers['x-izini-signature-v2'] }}"
            },
            {
              "leftValue": "={{ Math.abs($now.toSeconds() - Number($('Izini webhook').item.json.headers['x-izini-timestamp'])) }}",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "rightValue": 300
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "fe7ce71e-5ff7-4909-87b8-fee1eba347b0",
      "name": "Answer 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        880,
        200
      ],
      "parameters": {
        "respondWith": "noData",
        "options": {
          "responseCode": 200
        }
      }
    },
    {
      "id": "ef3b9d44-f285-4d6c-8fa7-035cf217699e",
      "name": "Answer 401",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        880,
        420
      ],
      "parameters": {
        "respondWith": "noData",
        "options": {
          "responseCode": 401
        }
      }
    },
    {
      "id": "0ad89082-7e55-44f2-880a-389c26e37e5a",
      "name": "Parse event",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1100,
        200
      ],
      "parameters": {
        "mode": "raw",
        "jsonOutput": "={{ $('Read raw body').item.json.rawBody }}",
        "includeOtherFields": false
      }
    },
    {
      "id": "b771dbaf-a6ad-4b03-8d22-0f9ea5a16ede",
      "name": "Skip repeats",
      "type": "n8n-nodes-base.removeDuplicates",
      "typeVersion": 2,
      "position": [
        1320,
        200
      ],
      "parameters": {
        "operation": "removeItemsSeenInPreviousExecutions",
        "logic": "removeItemsWithAlreadySeenKeyValues",
        "dedupeValue": "={{ $json.id }}"
      }
    },
    {
      "id": "a36a72b3-1343-4141-8f08-71774a36aea6",
      "name": "Describe event",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1540,
        200
      ],
      "parameters": {
        "mode": "manual",
        "includeOtherFields": true,
        "assignments": {
          "assignments": [
            {
              "id": "headline",
              "name": "headline",
              "type": "string",
              "value": "={{ ({\"consent.updated\":\"Consent recorded\",\"dsar.received\":\"New data subject request\",\"dsar.due_soon\":\"Data subject request due within 7 days\",\"dsar.overdue\":\"Data subject request past its target\",\"dsar.closed\":\"Data subject request closed\",\"incident.created\":\"Incident logged\",\"incident.breach_clock\":\"72-hour NDPC clock\",\"incident.ndpc_notified\":\"Breach reported to the NDPC\",\"dpia.completed\":\"DPIA completed\",\"policy.published\":\"Privacy policy published\",\"vendor.dpa_review_due\":\"Vendor DPA due for review\",\"training.overdue\":\"Staff training overdue\",\"car.due\":\"Annual audit return due 31 March\"})[$json.event] ?? $json.event }}{{ $json.event === 'incident.breach_clock' ? ': ' + (({\"started\":\"clock started\",\"48h\":\"48 hours left\",\"24h\":\"24 hours left\",\"6h\":\"6 hours left\",\"overdue\":\"deadline passed\"})[$json.payload.milestone] ?? $json.payload.milestone) : '' }}"
            },
            {
              "id": "reference",
              "name": "reference",
              "type": "string",
              "value": "={{ $json.payload.reference ?? $json.payload.agreement_name ?? \"\" }}"
            },
            {
              "id": "when",
              "name": "when",
              "type": "string",
              "value": "={{ $json.payload.due_at ?? $json.payload.notification_deadline ?? $json.payload.review_due_date ?? $json.payload.due_date ?? $json.timestamp }}"
            },
            {
              "id": "link",
              "name": "link",
              "type": "string",
              "value": "={{ $json.payload.dashboard_url ?? \"https://app.izini.ng/dashboard\" }}"
            }
          ]
        }
      }
    },
    {
      "id": "28567fc7-e733-4814-8bae-6182a8c62196",
      "name": "Post to Teams",
      "type": "n8n-nodes-base.microsoftTeams",
      "typeVersion": 1.1,
      "position": [
        1760,
        200
      ],
      "parameters": {
        "resource": "channelMessage",
        "operation": "create",
        "teamId": "",
        "channelId": "",
        "messageType": "html",
        "message": "=<b>{{ $json.headline }}</b>{{ $json.reference ? \" · \" + $json.reference : \"\" }}<br>Date: {{ $json.when }}<br><a href=\"{{ $json.link }}\">Open in Izini</a>",
        "options": {
          "includeLinkToWorkflow": false
        }
      }
    }
  ],
  "connections": {
    "Izini webhook": {
      "main": [
        [
          {
            "node": "Read raw body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read raw body": {
      "main": [
        [
          {
            "node": "Sign with your webhook secret",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sign with your webhook secret": {
      "main": [
        [
          {
            "node": "Signed by Izini, sent in the last 5 minutes?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Signed by Izini, sent in the last 5 minutes?": {
      "main": [
        [
          {
            "node": "Answer 200",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Answer 401",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Answer 200": {
      "main": [
        [
          {
            "node": "Parse event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse event": {
      "main": [
        [
          {
            "node": "Skip repeats",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip repeats": {
      "main": [
        [
          {
            "node": "Describe event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Describe event": {
      "main": [
        [
          {
            "node": "Post to Teams",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false,
    "source": "https://app.izini.ng/developers/guides/events-to-your-tools"
  }
}
