{
  "id": "EB7D5DQptLGKDK6k",
  "name": "Real-Time Uptime Alerts to Jira with Smart Slack On-Call Routing",
  "tags": [],
  "nodes": [
    {
      "id": "1b1c8bc3-c0ad-4112-9e4c-8fa1d7a7514f",
      "name": "Receive Uptime Alert",
      "type": "n8n-nodes-base.webhook",
      "position": [
        576,
        720
      ],
      "parameters": {
        "path": "7347e828-de5e-4368-9222-d53d9815789b",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "924594ee-fcb0-42ba-8113-418935b4ce39",
      "name": "Filter for Critical Status",
      "type": "n8n-nodes-base.if",
      "position": [
        784,
        720
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6af7299d-4509-4dd6-b34e-caac621ba719",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.status }}",
              "rightValue": "=down"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ff37c0a2-3cc3-4514-9572-abe46fa6acd1",
      "name": "Create New Jira Incident",
      "type": "n8n-nodes-base.jira",
      "position": [
        1072,
        704
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10000",
          "cachedResultName": "n8n sample project"
        },
        "summary": "={{ $json.body.serviceName }} {{ $json.body.timestamp }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10003",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "description": "=Service name :  {{ $json.body.serviceName }}\nstatus : {{ $json.body.status }}\ntime stamp : {{ $json.body.timestamp }}\ncustomer impact : {{ $json.body.customerImpact }}\nservice owner : {{ $json.body.serviceName }}\ndowntime duration : {{ $json.body.downtimeDuration }}\nerror code: {{ $json.body.errorCode }}\npriority : {{$json.body.priority }}\n"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "40afe805-f9ea-48f1-abe6-a7aca33ba35f",
      "name": "Get On-Call Channel Members",
      "type": "n8n-nodes-base.slack",
      "position": [
        1328,
        688
      ],
      "parameters": {
        "resource": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "operation": "member"
      },
      "typeVersion": 2.3
    },
    {
      "id": "46c30b16-3c56-4831-b55f-61ede1a4574e",
      "name": "Split/Process Each Member",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1520,
        704
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "92d91b30-466d-4cef-8094-a5e5b72faa1c",
      "name": "Check Slack User Presence",
      "type": "n8n-nodes-base.slack",
      "position": [
        1760,
        704
      ],
      "parameters": {
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.member }}"
        },
        "resource": "user",
        "operation": "getPresence"
      },
      "typeVersion": 2.3
    },
    {
      "id": "d30ac6d3-233d-4d26-b89f-5f4eb1ba8f91",
      "name": "Collect & Set Final Data",
      "type": "n8n-nodes-base.set",
      "position": [
        2000,
        704
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4c0eb9e9-c1c4-43e9-936e-e8d1336e346e",
              "name": "presence",
              "type": "string",
              "value": "={{ $json.presence }}"
            },
            {
              "id": "9ea973a2-fb23-42a3-895e-582281ad2ae4",
              "name": "member id",
              "type": "string",
              "value": "={{ $('Split/Process Each Member').item.json.member }}"
            },
            {
              "id": "76298576-27b3-4a2b-a6fc-a260f46cfb21",
              "name": "service name",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.serviceName }}"
            },
            {
              "id": "db52e6ca-d380-4497-ace6-ee32547a73b6",
              "name": "status",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.status }}"
            },
            {
              "id": "b4f16d01-d76a-4167-b670-aead1866a198",
              "name": "time stamp",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.timestamp }}"
            },
            {
              "id": "42824bf6-ca13-43fa-82bf-2a1099028dd5",
              "name": "customer impact",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.customerImpact }}"
            },
            {
              "id": "27dafc94-0372-4401-82c6-7c9f2582bfd7",
              "name": "last notified",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.lastNotified }}"
            },
            {
              "id": "55dd4347-574d-407c-9866-b6e23ef62fbf",
              "name": "downtime duration",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.downtimeDuration }}"
            },
            {
              "id": "78bbc0c1-7196-49ec-b058-ce64b1922919",
              "name": "error code",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.errorCode }}"
            },
            {
              "id": "1f9d6f1d-0584-4560-bd84-0d50009bb2a9",
              "name": "priority",
              "type": "string",
              "value": "={{ $('Filter for Critical Status').item.json.body.priority }}"
            },
            {
              "id": "027b146f-393a-4408-af1b-62563bbd2fce",
              "name": "jira ticket",
              "type": "string",
              "value": "={{ $('Create New Jira Incident').item.json.key }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "86f6e01f-fed3-4628-88d2-bc942ab008a9",
      "name": "Notify Selected User",
      "type": "n8n-nodes-base.slack",
      "position": [
        1920,
        272
      ],
      "parameters": {
        "text": "=:warning: *Service Alert - {{ $json[\"service name\"] }} is {{ $json.status }}!*\n\n*Status:* {{ $json.status }}\n*Downtime Duration:* {{ $json[\"downtime duration\"] }}\n*Customer Impact:* {{ $json[\"customer impact\"] }}\n*Error Code:* {{ $json[\"error code\"] }}\n*Jira Ticket:* {{ $json[\"jira ticket\"] }}\n*Last Notified:* {{ $json[\"last notified\"] }}\n*Priority:* {{ $json.priority }}\n\nPlease investigate immediately. \n",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json[\"member id\"] }}"
        },
        "select": "user",
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "654ccbc6-335d-4380-b365-cbb22da35c86",
      "name": "Select Active On-Call User",
      "type": "n8n-nodes-base.code",
      "position": [
        1728,
        272
      ],
      "parameters": {
        "jsCode": "// items = array of users with presence and member id + additional data\nconst users = items.map(item => item.json);\n\n// Filter active users\nconst activeUsers = users.filter(u => u.presence === 'active');\n\nlet selectedUser;\n\n// Case 1 & 2: If any active user exists\nif (activeUsers.length > 0) {\n  // Pick random active user\n  const randomIndex = Math.floor(Math.random() * activeUsers.length);\n  selectedUser = activeUsers[randomIndex];\n} else {\n  // Case 3: No active users, pick first user as fallback\n  selectedUser = users[0];\n}\n\n// Return all details for selected user\nreturn [{ json: selectedUser }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "32ec235e-bdc6-4fa7-a1ef-af39bb012563",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        528,
        496
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 400,
        "content": "###  Start Alert & Check Status\nThe workflow is triggered by an external webhook alert containing incident details. It immediately filters the incoming payload based on the alert's status (e.g., 'down') to ensure only critical, actionable events proceed to the next stage."
      },
      "typeVersion": 1
    },
    {
      "id": "52a2a324-a6be-4d04-9910-34b7ce07d0b1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        496
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 400,
        "content": "### Create Ticket in Jira\nUpon validation, a detailed Jira incident is instantly created. It uses dynamic data from the alert, including service name, downtime duration, and error code, to ensure all necessary context is logged in a new ticket for tracking."
      },
      "typeVersion": 1
    },
    {
      "id": "c71adc98-0dda-4c72-bc20-ffa13229146c",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        496
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 400,
        "content": "### Find Available Team Member\nThe workflow fetches all member IDs from the designated on-call Slack channel. It then loops through each individual member ID to check their current Slack presence status (active or away), preparing a filtered list for routing."
      },
      "typeVersion": 1
    },
    {
      "id": "d001bdb7-b00e-4453-8a30-6632d6dce3b6",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1632,
        128
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 320,
        "content": "### Send Alert to User\nAll incident data and user statuses are combined for processing. A JavaScript code node implements the rotation logic to select a single active user. Finally, a direct Slack message is sent to that chosen on-call team member for immediate action."
      },
      "typeVersion": 1
    },
    {
      "id": "4a68b834-c4ef-4e30-833e-25576266ef33",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 448,
        "height": 608,
        "content": "## How it Work\nThis workflow starts when your uptime monitoring tool sends a webhook alert to n8n. The alert payload is checked to ensure the service status is down. Only critical outages pass through to the next stage. Once the alert is validated, a Jira Task is automatically created using all the incident details such as service name, downtime duration, error code, customer impact, and timestamp.\n\nAfter creating the Jira incident, the workflow retrieves all member IDs from your designated Slack on-call rotation channel. Each member\u2019s Slack presence is checked individually. The workflow then applies smart selection logic: if multiple users are active, it randomly picks one; if only one is active, that user is selected; and if no one is active, it falls back to the first member.\n\n## Setup Steps\n1.Import the workflow JSON into n8n.\n2.Configure your Webhook, Slack, and Jira credentials.\n3.Update the IF node to match your desired critical status (already set to \"down\").\n4.Set your Jira project and issue type.\n5.Select your Slack on-call channel.\n6.Activate the workflow and send a test alert using Postman or your monitoring tool."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6674b6f5-7199-4b81-9e6e-1b751762a748",
  "connections": {
    "Receive Uptime Alert": {
      "main": [
        [
          {
            "node": "Filter for Critical Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Collect & Set Final Data": {
      "main": [
        [
          {
            "node": "Split/Process Each Member",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create New Jira Incident": {
      "main": [
        [
          {
            "node": "Get On-Call Channel Members",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Slack User Presence": {
      "main": [
        [
          {
            "node": "Collect & Set Final Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split/Process Each Member": {
      "main": [
        [
          {
            "node": "Select Active On-Call User",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check Slack User Presence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter for Critical Status": {
      "main": [
        [
          {
            "node": "Create New Jira Incident",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Active On-Call User": {
      "main": [
        [
          {
            "node": "Notify Selected User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get On-Call Channel Members": {
      "main": [
        [
          {
            "node": "Split/Process Each Member",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}