{
  "name": "HA Interactive Update Manager",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "id": "efc3241f-63d5-4f7f-acae-fdfbfe0014d5",
      "name": "Daily Check Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [5952, 1104]
    },
    {
      "parameters": {
        "url": "http://192.168.0.137:8123/api/states",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJlMjgwMDhkMmEyM2M0ZjU3YTQ4MTVjY2RmNDVkN2QyNSIsImlhdCI6MTc3Mzc4MTc2MiwiZXhwIjoyMDg5MTQxNzYyfQ.YwT6ivwW_4fu9r22Q_bdHEpweBTvPvql-pcsN15w8ic"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "options": {}
      },
      "id": "68e06c8a-b587-4f69-9299-ef4ef0b939f0",
      "name": "Get HA Core Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6192, 1056]
    },
    {
      "parameters": {
        "jsCode": "// Deduplicate: only notify if the set of pending updates has changed\nconst sd = $getWorkflowStaticData('global');\n\nconst updates = $input.all()\n  .map(i => i.json)\n  .filter(s => typeof s.entity_id === 'string' && s.entity_id.startsWith('update.') && s.state === 'on')\n  .map(s => ({\n    entity_id: s.entity_id,\n    name: s.attributes?.friendly_name || s.entity_id,\n    installed_version: s.attributes?.installed_version || s.attributes?.current_version || 'unknown',\n    latest_version: s.attributes?.latest_version || 'unknown'\n  }));\n\nconst currentIds = updates.map(u => u.entity_id).sort().join(',');\nconst alreadyNotified = !!sd.notifiedUpdateIds && sd.notifiedUpdateIds === currentIds;\n\nconst summary = updates.length\n  ? updates.map(u => `- ${u.name}: ${u.installed_version} -> ${u.latest_version}`).join('\\n')\n  : 'No updates available';\n\nreturn [{\n  json: {\n    updates,\n    update_count: updates.length,\n    has_updates: updates.length > 0 && !alreadyNotified,\n    update_summary: summary,\n    current_update_ids: currentIds\n  }\n}];"
      },
      "id": "65ab3a37-4da0-4d5b-bbe6-ba682f0e2a08",
      "name": "Collect Available Updates",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [6352, 1056]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "update-check",
              "leftValue": "={{ $json.has_updates }}",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "rightValue": ""
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "9aaf7413-f38a-4bb7-b503-13dd7afdba0f",
      "name": "Is Update Available?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [6528, 1056]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.telegram.org/bot8708411717:AAHFQr5-TV5NdQ2VwDZQ2HJKnFU3jU8Wb6Y/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: '-1003870868518', text: `Home Assistant Updates Available\\n\\n${$json.update_summary}\\n\\nInstall all available updates now?`, reply_markup: { inline_keyboard: [[{ text: '⬆️ Update Now', callback_data: 'ha_do_update' }, { text: '✖ Dismiss', callback_data: 'ha_ignore' }]] } }) }}",
        "options": {}
      },
      "id": "8e882b8d-edb3-4ce5-a2fd-1b42780dbd46",
      "name": "HTTP: Ask via Telegram",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6928, 1040]
    },
    {
      "parameters": {
        "jsCode": "// Save the current update IDs so we don't re-notify for the same set next run\nconst sd = $getWorkflowStaticData('global');\nconst currentIds = $('Collect Available Updates').first().json.current_update_ids;\nsd.notifiedUpdateIds = currentIds;\nreturn [{ json: { saved: true, notified_ids: currentIds } }];"
      },
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Save Notified IDs",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [7120, 1040]
    },
    {
      "parameters": {
        "updates": [
          "callback_query"
        ],
        "additionalFields": {}
      },
      "id": "9c947828-ad70-4072-937c-f8b1b1c71934",
      "name": "Telegram Button Listener",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [5920, 1328],
      "webhookId": "464f0bc1-e858-4452-a8ee-11a3bcd56836",
      "credentials": {
        "telegramApi": {
          "id": "WXTyetoJLOgPlvCo",
          "name": "Home Assistant Update"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const cq = $json.callback_query || $json.body?.callback_query || $json;\n\nreturn [{\n  json: {\n    ...$json,\n    callback_query: cq,\n    callback_data: cq?.data || $json.data || '',\n    callback_query_id: cq?.id || $json.id || '',\n    message_id: cq?.message?.message_id || '',\n    chat_id: cq?.message?.chat?.id || ''\n  }\n}];"
      },
      "id": "711cf29d-4464-44ef-8e02-ee0f1e02e9f3",
      "name": "Normalize Callback",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [6144, 1328]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "is-update-btn",
              "leftValue": "={{ $json.callback_data }}",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "string.equals"
              },
              "rightValue": "ha_do_update"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2ba5fd44-d72f-4f64-bf1c-2ee78552b160",
      "name": "If Update Clicked",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [6336, 1328]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "is-restart-btn",
              "leftValue": "={{ $json.callback_data }}",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "string.equals"
              },
              "rightValue": "ha_restart"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
      "name": "If Restart Clicked",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [6336, 1600]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot8708411717:AAHFQr5-TV5NdQ2VwDZQ2HJKnFU3jU8Wb6Y/editMessageReplyMarkup",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $json.chat_id }}"
            },
            {
              "name": "message_id",
              "value": "={{ $json.message_id }}"
            },
            {
              "name": "reply_markup",
              "value": "={\"inline_keyboard\":[]}"
            }
          ]
        },
        "options": {}
      },
      "onError": "continueRegularOutput",
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "name": "Remove Telegram Buttons",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6560, 1760]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.telegram.org/bot8708411717:AAHFQr5-TV5NdQ2VwDZQ2HJKnFU3jU8Wb6Y/answerCallbackQuery",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ callback_query_id: $json.callback_query_id }) }}",
        "options": {}
      },
      "onError": "continueRegularOutput",
      "id": "e81b4254-9ab4-4a2c-9601-95cdab4ab94a",
      "name": "Close Loading Spinner",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6560, 1600]
    },
    {
      "parameters": {
        "url": "http://192.168.0.137:8123/api/states",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJlMjgwMDhkMmEyM2M0ZjU3YTQ4MTVjY2RmNDVkN2QyNSIsImlhdCI6MTc3Mzc4MTc2MiwiZXhwIjoyMDg5MTQxNzYyfQ.YwT6ivwW_4fu9r22Q_bdHEpweBTvPvql-pcsN15w8ic"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "options": {}
      },
      "id": "55c1d03b-8724-44f9-bef0-f53cbf5e7f17",
      "name": "Get HA States (On Click)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6544, 1312]
    },
    {
      "parameters": {
        "jsCode": "const states = $input.all()\n  .map(i => i.json)\n  .filter(s => typeof s.entity_id === 'string' && s.entity_id.startsWith('update.') && s.state === 'on');\n\nif (states.length === 0) {\n  throw new Error('No pending update entities are currently ON.');\n}\n\nconst items = states.map(s => ({\n  entity_id: s.entity_id,\n  name: s.attributes?.friendly_name || s.entity_id.replace(/^update\\./, '').replace(/_/g, ' '),\n  from: s.attributes?.installed_version || s.attributes?.current_version || '?',\n  to: s.attributes?.latest_version || '?',\n  needs_restart: !!(s.attributes?.release_notes || '').toLowerCase().includes('restart') ||\n    /home_assistant_core|home_assistant_operating_system|supervisor/i.test(s.entity_id)\n}));\n\nconst needsRestart = items.some(i => i.needs_restart);\n\nreturn [{ json: { entity_id: items.map(i => i.entity_id), items, needs_restart: needsRestart } }];"
      },
      "id": "e6597caa-9279-4a4c-93cd-ea5f8ce8e449",
      "name": "Build Install Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [6768, 1312]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://192.168.0.137:8123/api/services/update/install",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJlMjgwMDhkMmEyM2M0ZjU3YTQ4MTVjY2RmNDVkN2QyNSIsImlhdCI6MTc3Mzc4MTc2MiwiZXhwIjoyMDg5MTQxNzYyfQ.YwT6ivwW_4fu9r22Q_bdHEpweBTvPvql-pcsN15w8ic"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ entity_id: $json.entity_id }) }}",
        "options": {}
      },
      "id": "1313066c-f036-4b25-8053-c0f71fd9b559",
      "name": "POST Update to HA",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6992, 1312]
    },
    {
      "parameters": {
        "jsCode": "const { items = [], entity_id = [], needs_restart = false } = $('Build Install Payload').first().json;\nconst entityIds = Array.isArray(entity_id) ? entity_id : [entity_id];\n\nconst lines = items.length\n  ? items.map(i => `• ${i.name}: ${i.from} → ${i.to}`).join('\\n')\n  : entityIds.map(id => `• ${id.replace(/^update\\./, '').replace(/_/g, ' ')}`).join('\\n');\n\nconst baseText = `✅ Updates Installing\\n\\n${lines}`;\n\nreturn [{ json: { notify_text: baseText, needs_restart } }];"
      },
      "id": "91c4534f-6edd-402c-a83b-862d014c3bac",
      "name": "Build Update Success Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [7184, 1312]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "needs-restart-check",
              "leftValue": "={{ $json.needs_restart }}",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "rightValue": ""
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "name": "If Needs Restart?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [7376, 1312]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.telegram.org/bot8708411717:AAHFQr5-TV5NdQ2VwDZQ2HJKnFU3jU8Wb6Y/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: '-1003870868518', text: $json.notify_text + '\\n\\n⚠️ A restart is required to complete the update.\\nRestart Home Assistant now?', reply_markup: { inline_keyboard: [[{ text: '🔄 Restart Now', callback_data: 'ha_restart' }, { text: '⏭ Later', callback_data: 'ha_ignore' }]] } }) }}",
        "options": {}
      },
      "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
      "name": "Send Restart Prompt",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [7568, 1200]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.telegram.org/bot8708411717:AAHFQr5-TV5NdQ2VwDZQ2HJKnFU3jU8Wb6Y/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: '-1003870868518', text: $json.notify_text + '\\n\\n🔄 Integrations will reload automatically.' }) }}",
        "options": {}
      },
      "id": "9c303515-ae5d-4d3a-9977-f4d095bfab5d",
      "name": "HTTP: Notify Update Success",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [7568, 1440]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://192.168.0.137:8123/api/services/homeassistant/restart",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJlMjgwMDhkMmEyM2M0ZjU3YTQ4MTVjY2RmNDVkN2QyNSIsImlhdCI6MTc3Mzc4MTc2MiwiZXhwIjoyMDg5MTQxNzYyfQ.YwT6ivwW_4fu9r22Q_bdHEpweBTvPvql-pcsN15w8ic"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={}",
        "options": {}
      },
      "id": "f6a7b8c9-d0e1-2345-fabc-456789012345",
      "name": "POST Restart to HA",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6720, 1760]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.telegram.org/bot8708411717:AAHFQr5-TV5NdQ2VwDZQ2HJKnFU3jU8Wb6Y/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: '-1003870868518', text: '🔄 Home Assistant is restarting...\\n\\nThis may take a minute.' }) }}",
        "options": {}
      },
      "id": "a7b8c9d0-e1f2-3456-abcd-567890123456",
      "name": "Notify Restart Sent",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [6960, 1760]
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [5952, 912],
      "id": "36b384b1-53f7-49a9-9037-aa04915bf96d",
      "name": "When clicking 'Execute workflow'"
    }
  ],
  "pinData": {},
  "connections": {
    "Daily Check Trigger": {
      "main": [[{ "node": "Get HA Core Status", "type": "main", "index": 0 }]]
    },
    "Get HA Core Status": {
      "main": [[{ "node": "Collect Available Updates", "type": "main", "index": 0 }]]
    },
    "Collect Available Updates": {
      "main": [[{ "node": "Is Update Available?", "type": "main", "index": 0 }]]
    },
    "Is Update Available?": {
      "main": [[{ "node": "HTTP: Ask via Telegram", "type": "main", "index": 0 }]]
    },
    "HTTP: Ask via Telegram": {
      "main": [[{ "node": "Save Notified IDs", "type": "main", "index": 0 }]]
    },
    "Telegram Button Listener": {
      "main": [[{ "node": "Normalize Callback", "type": "main", "index": 0 }]]
    },
    "Normalize Callback": {
      "main": [[{ "node": "If Update Clicked", "type": "main", "index": 0 }]]
    },
    "If Update Clicked": {
      "main": [
        [
          { "node": "Get HA States (On Click)", "type": "main", "index": 0 },
          { "node": "Close Loading Spinner", "type": "main", "index": 0 },
          { "node": "Remove Telegram Buttons", "type": "main", "index": 0 }
        ],
        [
          { "node": "If Restart Clicked", "type": "main", "index": 0 }
        ]
      ]
    },
    "If Restart Clicked": {
      "main": [
        [
          { "node": "Close Loading Spinner", "type": "main", "index": 0 },
          { "node": "Remove Telegram Buttons", "type": "main", "index": 0 },
          { "node": "POST Restart to HA", "type": "main", "index": 0 }
        ],
        [
          { "node": "Close Loading Spinner", "type": "main", "index": 0 },
          { "node": "Remove Telegram Buttons", "type": "main", "index": 0 }
        ]
      ]
    },
    "Get HA States (On Click)": {
      "main": [[{ "node": "Build Install Payload", "type": "main", "index": 0 }]]
    },
    "Build Install Payload": {
      "main": [[{ "node": "POST Update to HA", "type": "main", "index": 0 }]]
    },
    "POST Update to HA": {
      "main": [[{ "node": "Build Update Success Message", "type": "main", "index": 0 }]]
    },
    "Build Update Success Message": {
      "main": [[{ "node": "If Needs Restart?", "type": "main", "index": 0 }]]
    },
    "If Needs Restart?": {
      "main": [
        [{ "node": "Send Restart Prompt", "type": "main", "index": 0 }],
        [{ "node": "HTTP: Notify Update Success", "type": "main", "index": 0 }]
      ]
    },
    "POST Restart to HA": {
      "main": [[{ "node": "Notify Restart Sent", "type": "main", "index": 0 }]]
    },
    "When clicking 'Execute workflow'": {
      "main": [[{ "node": "Get HA Core Status", "type": "main", "index": 0 }]]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all",
    "saveManualExecutions": true,
    "saveExecutionProgress": true,
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false
  },
  "versionId": "f6ff6ffc-e75c-4e08-9aaa-6b46423d993c",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "e09d1f0f8b9f78e80ac70b6dc8726dd263b0b6ffc4300b0eee3b58f6da316f29"
  },
  "id": "vP0brL1a1ohfHlNj",
  "tags": [
    {
      "updatedAt": "2026-03-17T21:15:17.988Z",
      "createdAt": "2026-03-17T21:15:17.988Z",
      "id": "XlNPbrIR5uhMIKFj",
      "name": "Home Assistent"
    }
  ]
}
