{
  "id": "VFx1qpO7OYLJRTtq",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "SLA Monitoring & Alerting",
  "tags": [],
  "nodes": [
    {
      "id": "5bbf4343-9879-42b5-b16e-c24c6c48d882",
      "name": "Trigger Every Hour",
      "type": "n8n-nodes-base.cron",
      "position": [
        -1904,
        608
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "61005911-1ea7-4e84-afe1-e394909fe306",
      "name": "\u23f0 SLA Monitoring Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2240,
        496
      ],
      "parameters": {
        "width": 280,
        "height": 300,
        "content": "\u23f0 WORKFLOW START\n\nThis workflow monitors Zendesk tickets and ensures SLAs are met by:\n\n\u2022 Running every hour automatically\n\u2022 Fetching all open tickets\n\u2022 Calculating time remaining\n\u2022 Escalating tickets nearing breach\n\u2022 Logging compliance metrics\n\u2022 Alerting team via Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "dbe9f15d-4e00-4018-ac5e-8ee35473c310",
      "name": "Fetch Open Tickets from Zendesk",
      "type": "n8n-nodes-base.zendesk",
      "position": [
        -1680,
        608
      ],
      "parameters": {
        "options": {},
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "zendeskApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c5eb8fbd-4837-437a-ba29-1b7e236d19dd",
      "name": "\ud83d\udce5 Zendesk Fetch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1792,
        272
      ],
      "parameters": {
        "width": 280,
        "height": 300,
        "content": "\ud83d\udce5 ZENDESK DATA RETRIEVAL\n\nFetches all tickets from Zendesk:\n\u2022 Uses Zendesk REST API\n\u2022 Retrieves all records (returnAll: true)\n\u2022 Returns: ticket ID, status, created_at, sla_due, priority\n\nRequired ticket fields:\n\u2713 created_at (ISO timestamp)\n\u2713 sla_due (ISO timestamp)\n\u2713 id (unique identifier)\n\u2713 priority (low/medium/high/urgent)"
      },
      "typeVersion": 1
    },
    {
      "id": "ff9333b9-b761-4ae7-8d1d-af38d44dc30e",
      "name": "Filter: Open Tickets Only",
      "type": "n8n-nodes-base.if",
      "position": [
        -1456,
        608
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "open-filter",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "open"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b5a5e4bc-c62f-4093-bc6f-4ee998868cf8",
      "name": "\ud83d\udd0d Filter Open",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1600,
        784
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "\ud83d\udd0d OPEN TICKET FILTER\n\nFilters results to include only:\n\u2713 Tickets with status = 'open'\n\nRejected:\n\u2717 Closed tickets\n\u2717 On-hold tickets\n\u2717 Pending tickets\n\nOnly open tickets need SLA monitoring"
      },
      "typeVersion": 1
    },
    {
      "id": "988815d0-084f-411a-9fc7-5d3d4510030b",
      "name": "Notify: No Open Tickets",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1232,
        704
      ],
      "parameters": {
        "text": "\u2705 No open tickets at this time",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09GNB90TED",
          "cachedResultName": "general-information"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d97ef397-098e-4310-a6aa-742990d45a54",
      "name": "\u2705 Clear Alert",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1216,
        864
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "\u2705 NO TICKETS ALERT\n\nSent when no open tickets found:\n\u2022 Channel: general-information\n\u2022 Confirms all tickets resolved\n\u2022 Provides status update\n\nHelps team stay informed of workload status"
      },
      "typeVersion": 1
    },
    {
      "id": "6d07f0c0-c2f8-491f-b6b0-677d658ce8b4",
      "name": "Calculate SLA Time Remaining",
      "type": "n8n-nodes-base.function",
      "position": [
        -1232,
        512
      ],
      "parameters": {
        "functionCode": "// Expects each ticket to include: created_at (ISO), sla_due (ISO), id, priority\nconst out = items.map(i => {\n  const t = i.json;\n  const now = new Date();\n  const created = new Date(t.created_at);\n  const due = new Date(t.sla_due);\n  const slaTotal = due - created; // ms\n  const timeRemainingMs = due - now;\n  const elapsed = slaTotal > 0 ? (1 - timeRemainingMs / slaTotal) : 1;\n  const percentElapsed = Math.round(elapsed * 100);\n  t.timeRemainingMinutes = Math.max(0, Math.round(timeRemainingMs / 60000));\n  t.percentElapsed = Math.min(100, Math.max(0, percentElapsed));\n  return { json: t };\n});\nreturn out;"
      },
      "typeVersion": 1
    },
    {
      "id": "c90f88a5-4da2-4ff0-a7a8-e3b06629d817",
      "name": "\u23f1\ufe0f SLA Calculation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        144
      ],
      "parameters": {
        "width": 280,
        "height": 340,
        "content": "\u23f1\ufe0f SLA CALCULATION\n\nFor each ticket, calculates:\n\n1. Total SLA Duration:\n   slaTotal = sla_due - created_at\n\n2. Time Remaining:\n   timeRemainingMs = sla_due - now\n   timeRemainingMinutes = timeRemainingMs / 60000\n\n3. Percentage Elapsed:\n   percentElapsed = (1 - remaining/total) \u00d7 100\n   Range: 0-100%\n\nOutputs added to ticket data:\n\u2713 percentElapsed\n\u2713 timeRemainingMinutes"
      },
      "typeVersion": 1
    },
    {
      "id": "6235fdfa-6f4f-4d05-a81f-3e5fce7b8f41",
      "name": "Prepare Escalation Payload",
      "type": "n8n-nodes-base.set",
      "position": [
        -1008,
        512
      ],
      "parameters": {
        "values": {
          "number": [],
          "string": [
            {
              "name": "priority",
              "value": "High"
            },
            {
              "name": "note",
              "value": "Auto-prioritised due to SLA nearing breach"
            }
          ],
          "boolean": []
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "0103cb4e-c5da-48e8-bd30-6d69b79a9347",
      "name": "\ud83d\udea8 Escalation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1056,
        160
      ],
      "parameters": {
        "width": 280,
        "height": 300,
        "content": "\ud83d\udea8 ESCALATION PAYLOAD\n\nPrepares data for high-urgency tickets:\n\nSets priority to: 'High'\nAdds note: 'Auto-prioritised due to SLA nearing breach'\n\nThis payload is sent to:\n\u2192 Update Zendesk ticket\n\u2192 Triggers automation rules\n\u2192 Notifies support team\n\nUsed for 90%+ elapsed tickets"
      },
      "typeVersion": 1
    },
    {
      "id": "1ecaf93c-d3ac-454d-a39e-9ef12bf4c13c",
      "name": "\ud83d\udd34 90% Threshold",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        -160
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "\ud83d\udd34 CRITICAL THRESHOLD\n\nCondition: percentElapsed \u2265 90%\n\nMeans:\n\u2022 90% of SLA time consumed\n\u2022 Only ~10% time remaining\n\u2022 Ticket at risk of breach\n\u2022 CRITICAL priority\n\nAction: Route to escalation & Zendesk update"
      },
      "typeVersion": 1
    },
    {
      "id": "cc40c04a-de71-41fa-9477-ab36fb883b60",
      "name": "\ud83d\udfe1 75% Threshold",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        592
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "\ud83d\udfe1 WARNING THRESHOLD\n\nCondition: percentElapsed \u2265 75%\n\nMeans:\n\u2022 75% of SLA time consumed\n\u2022 ~25% time remaining\n\u2022 Ticket needs attention\n\u2022 WARNING level\n\nAction: Send warning message to Slack for team awareness"
      },
      "typeVersion": 1
    },
    {
      "id": "f629e9ff-e0e5-4c28-a804-b4ff35b2452f",
      "name": "Update Zendesk: Warning Priority",
      "type": "n8n-nodes-base.zendesk",
      "position": [
        -784,
        512
      ],
      "parameters": {
        "id": "={{ $json.id }}",
        "operation": "update",
        "updateFields": {}
      },
      "credentials": {
        "zendeskApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e0571751-f696-4dce-9334-c496fc8e4ab7",
      "name": "\ud83d\udd04 Zendesk Update",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        720
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "\ud83d\udd04 ZENDESK UPDATE (75%+)\n\nUpdates ticket in Zendesk:\n\u2022 Uses ticket ID for targeting\n\u2022 Sets priority to 'High'\n\u2022 Adds internal note\n\u2022 Triggers Zendesk automations\n\nNext: Routes to both escalation and warning branches"
      },
      "typeVersion": 1
    },
    {
      "id": "ac4530cf-eed4-4577-b32e-83b720039cac",
      "name": "Update Zendesk: Escalate (90%+)",
      "type": "n8n-nodes-base.zendesk",
      "position": [
        -224,
        160
      ],
      "parameters": {
        "id": "={{ $json.id }}",
        "operation": "update",
        "updateFields": {}
      },
      "credentials": {
        "zendeskApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8334235e-e73e-4e1e-a869-05ea55dcd696",
      "name": "\ud83d\udea8 Zendesk Escalate",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -192
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "\ud83d\udea8 ZENDESK UPDATE (90%+)\n\nUpdates ticket in Zendesk:\n\u2022 Uses escalation payload\n\u2022 Sets priority to 'High'\n\u2022 Adds breach warning note\n\u2022 May trigger escalation rules\n\nAction: Notifies support to take immediate action"
      },
      "typeVersion": 1
    },
    {
      "id": "67393b6d-e097-45fc-916b-c4367efdc5db",
      "name": "Alert Slack: SLA Warning",
      "type": "n8n-nodes-base.slack",
      "position": [
        -240,
        384
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09GNB90TED",
          "cachedResultName": "general-information"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.3
    },
    {
      "id": "2ff470b8-7e28-436d-b046-9d5eee814001",
      "name": "\u26a0\ufe0f Slack Alert",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        352
      ],
      "parameters": {
        "width": 280,
        "height": 300,
        "content": "\u26a0\ufe0f SLACK WARNING ALERT\n\nSends to: general-information channel\n\nContains:\n\u2022 Ticket ID\n\u2022 Time remaining\n\u2022 Percentage of SLA elapsed\n\u2022 Priority level\n\u2022 Action required\n\nTriggers for 75%+ elapsed tickets\nKeeps team informed of at-risk tickets"
      },
      "typeVersion": 1
    },
    {
      "id": "98d57cf4-7748-4c6a-a459-ba0c0bf7900f",
      "name": "\ud83d\udcca Compliance Log",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        1056
      ],
      "parameters": {
        "width": 280,
        "height": 300,
        "content": "\ud83d\udcca COMPLIANCE LOGGING\n\nPrepares audit log for each ticket:\n\nData points:\n\u2713 Ticket ID\n\u2713 Percentage elapsed\n\u2713 Time remaining (minutes)\n\u2713 Timestamp (ISO)\n\nPurpose:\n\u2022 Compliance tracking\n\u2022 SLA history\n\u2022 Audit trail\n\u2022 Reporting metrics\n\nStored in Google Sheets for analysis"
      },
      "typeVersion": 1
    },
    {
      "id": "e786ac7c-4d1b-45ce-ab4e-8103364357f3",
      "name": "Log to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -144,
        896
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "ticket_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ticket_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "percent_elapsed",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "percent_elapsed",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time_remaining_minutes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "time_remaining_minutes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GeP8mTYttDTnVqdNrr3omGbGxlV7qu-jihhcVbeKs6Q/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1GeP8mTYttDTnVqdNrr3omGbGxlV7qu-jihhcVbeKs6Q",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GeP8mTYttDTnVqdNrr3omGbGxlV7qu-jihhcVbeKs6Q/edit?usp=drivesdk",
          "cachedResultName": "Stripe Data"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "c4f11e00-5027-4e1f-b544-f9d444fed3fd",
      "name": "\ud83d\udcc8 Sheets Logging",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        1072
      ],
      "parameters": {
        "width": 280,
        "height": 300,
        "content": "\ud83d\udcc8 GOOGLE SHEETS LOGGING\n\nAppends compliance records to:\nSheet: \"Stripe Data\" (Sheet1)\n\nColumns recorded:\n\u2022 ticket_id\n\u2022 percent_elapsed\n\u2022 time_remaining_minutes\n\u2022 timestamp\n\nUsed for:\n\u2713 Historical analysis\n\u2713 Compliance reports\n\u2713 SLA trending\n\u2713 Team metrics"
      },
      "typeVersion": 1
    },
    {
      "id": "6e465ec5-cccd-42a1-8a99-b70a1a9f5737",
      "name": "If \u2265 90% (Escalate)1",
      "type": "n8n-nodes-base.if",
      "position": [
        -560,
        176
      ],
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json[\"percentElapsed\"]}}",
              "value2": 90,
              "operation": "largerEqual"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0ff34295-27aa-4411-8f06-9d1c5c33ec84",
      "name": "If \u2265 75% (Warn)1",
      "type": "n8n-nodes-base.if",
      "position": [
        -560,
        512
      ],
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json[\"percentElapsed\"]}}",
              "value2": 75,
              "operation": "largerEqual"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "670ef417-71e2-4683-b107-c6e14bc7001e",
      "name": "Prepare Compliance Log1",
      "type": "n8n-nodes-base.function",
      "position": [
        -480,
        896
      ],
      "parameters": {
        "functionCode": "// Append a simple compliance log object to output for later storage or aggregation\nreturn items.map(i => ({ json: { id: i.json.id, percentElapsed: i.json.percentElapsed, timeRemainingMinutes: i.json.timeRemainingMinutes, timestamp: new Date().toISOString() } }));"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "1782ce88-b776-4180-a138-a1b6c94aa5b5",
  "connections": {
    "If \u2265 75% (Warn)1": {
      "main": [
        [
          {
            "node": "Alert Slack: SLA Warning",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Every Hour": {
      "main": [
        [
          {
            "node": "Fetch Open Tickets from Zendesk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If \u2265 90% (Escalate)1": {
      "main": [
        [
          {
            "node": "Update Zendesk: Escalate (90%+)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Compliance Log1": {
      "main": [
        [
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: Open Tickets Only": {
      "main": [
        [
          {
            "node": "Calculate SLA Time Remaining",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify: No Open Tickets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Escalation Payload": {
      "main": [
        [
          {
            "node": "Update Zendesk: Warning Priority",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate SLA Time Remaining": {
      "main": [
        [
          {
            "node": "Prepare Escalation Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Open Tickets from Zendesk": {
      "main": [
        [
          {
            "node": "Filter: Open Tickets Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Zendesk: Warning Priority": {
      "main": [
        [
          {
            "node": "If \u2265 90% (Escalate)1",
            "type": "main",
            "index": 0
          },
          {
            "node": "If \u2265 75% (Warn)1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Compliance Log1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}