Mein Arbeitsablauf

Experte

Dies ist ein Content Creation, Multimodal AI-Bereich Automatisierungsworkflow mit 26 Nodes. Hauptsächlich werden If, Code, Switch, Webhook, Postgres und andere Nodes verwendet. Erstellen Sie einen sicheren manuellen Freigabeprozess mit Postgres und Telegram

Voraussetzungen
  • HTTP Webhook-Endpunkt (wird von n8n automatisch generiert)
  • PostgreSQL-Datenbankverbindungsdaten
  • Telegram Bot Token
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
  "meta": {
    "instanceId": "9c8d0d4640139c59e2bc183c0a14df0fbc0573cb91e494f5db8144fe78fe28ca"
  },
  "name": "My workflow",
  "tags": [],
  "nodes": [
    {
      "id": "411a0468-c67b-4762-93e2-1d4e116f1181",
      "name": "01 Webhook Trigger: Genehmigungsentscheidung",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1808,
        400
      ],
      "webhookId": "12e347b0-b52a-4a2e-b096-4c5448f9641f",
      "parameters": {
        "path": "/approval",
        "options": {
          "responseData": "✅ Thanks, your decision was recorded."
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "08db80ea-aad6-45f7-973a-a0fbfa9285e0",
      "name": "02 FN: Signatur + TTL prüfen",
      "type": "n8n-nodes-base.code",
      "position": [
        -1584,
        400
      ],
      "parameters": {
        "language": "python",
        "pythonCode": "import hashlib\nimport hmac\nimport time\nimport os\n\nsecret = os.getenv(\"SECRET_KEY\")\nif not secret:\n    raise ValueError(\"SECRET_KEY environment variable not set\")\nnow = int(time.time())\n\nout = []\n\nfor item in items:\n    q = item[\"json\"].get(\"query\", {})\n    cid = q.get(\"cid\")\n    status = q.get(\"status\")\n    action = q.get(\"action\")\n    exp = int(q.get(\"exp\", \"0\"))\n    sig = q.get(\"sig\")\n\n    payload = f\"{cid}|{status}|{exp}\"\n    check_sig = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()\n\n    # Default result\n    result = {\n        \"correlation_id\": cid,\n        \"new_status\": status,\n        \"reason\": None\n    }\n\n    if sig != check_sig:\n        result[\"action\"] = \"invalid\"\n        result[\"reason\"] = \"Invalid signature\"\n    elif exp < now:\n        result[\"action\"] = \"expired\"\n        result[\"reason\"] = \"Link expired\"\n    elif action == \"approve\":\n        result[\"action\"] = \"approve\"\n        result[\"actor\"] = \"manager\"  # later replace with real manager identity\n    elif action == \"reject\":\n        result[\"action\"] = \"reject\"\n        result[\"actor\"] = \"manager\"\n    else:\n        result[\"action\"] = \"unknown\"\n        result[\"reason\"] = \"Unsupported action\"\n\n    out.append({\"json\": result})\n\nreturn out\n"
      },
      "typeVersion": 2
    },
    {
      "id": "3b7594c2-07c0-4baa-906b-daacff925853",
      "name": "04c DB: Ticketstatus aktualisieren",
      "type": "n8n-nodes-base.postgres",
      "notes": "Updates ticket status by correlation ID. Also inserts audit row and notifies ticket owner. Requires tickets table and audit schema.",
      "position": [
        -896,
        192
      ],
      "parameters": {
        "query": "UPDATE tickets\nSET status = $2, updated_at = NOW()\nWHERE correlation_id = $1::uuid\nRETURNING id, status, updated_at, correlation_id;\n",
        "options": {
          "queryReplacement": "={{$json.correlation_id}},{{$json.new_status}}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "notesInFlow": true,
      "typeVersion": 2.6
    },
    {
      "id": "17b6b2df-3792-4460-8f55-c32422d3ba2f",
      "name": "04c1 DB: Ticketbesitzer abrufen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -448,
        192
      ],
      "parameters": {
        "query": "SELECT chat_id, correlation_id, status, subject\nFROM tickets\nWHERE correlation_id = $1::uuid;",
        "options": {
          "queryReplacement": "={{ $('04c DB: Update Ticket Status').item.json.correlation_id }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "19802b0c-d66b-4a6a-b009-8d7f721abcca",
      "name": "04c1a IF: Gelöst oder In Bearbeitung",
      "type": "n8n-nodes-base.if",
      "position": [
        -224,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "115bb477-3dfa-4d9b-8e4b-cd2ef15439e1",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json[\"status\"] }}",
              "rightValue": "resolved"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "da2d1a92-a349-40ba-8160-63847c560a23",
      "name": "05c1a Telegram: Gelöst benachrichtigen",
      "type": "n8n-nodes-base.telegram",
      "notes": "Sends user-facing messages back to Telegram. Content depends on workflow branch (acknowledgment, errors, updates).",
      "position": [
        224,
        0
      ],
      "webhookId": "834b2795-7e52-4264-b787-7280bf60de36",
      "parameters": {
        "text": "=🎉 Good news! Your ticket (<code>{{ $json.correlation_id }}</code>) has been resolved.  \nYou can check details anytime with:  \n/status <code>{{ $json.correlation_id }}</code>",
        "chatId": "={{ $json.chat_id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "PEoTj5wxpFTeQVpI",
          "name": "Ticket Intake"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "e2290e2c-1572-46ac-b690-46626ede3a35",
      "name": "05c1b Telegram: In Bearbeitung benachrichtigen",
      "type": "n8n-nodes-base.telegram",
      "notes": "Sends user-facing messages back to Telegram. Content depends on workflow branch (acknowledgment, errors, updates).",
      "position": [
        224,
        192
      ],
      "webhookId": "560dda9b-b8e5-4e5b-9705-4d6ed17ce50d",
      "parameters": {
        "text": "=🔄 Your ticket (<code>{{ $json.correlation_id }}.</code>) is now being worked on.  \nWe’ll notify you once it’s resolved.",
        "chatId": "={{ $json.chat_id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "PEoTj5wxpFTeQVpI",
          "name": "Ticket Intake"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "828e2442-5f9e-4d12-a671-57b90d49e807",
      "name": "05c Telegram: Bestätigung aktualisieren",
      "type": "n8n-nodes-base.telegram",
      "notes": "Sends user-facing messages back to Telegram. Content depends on workflow branch (acknowledgment, errors, updates).",
      "position": [
        -224,
        288
      ],
      "webhookId": "2e047d36-651f-4c1e-9970-8adf7029c70c",
      "parameters": {
        "text": "=✅ <b>Ticket <code>{{ $json.correlation_id }}</code></b> updated!\n📌 <b>New Status:</b> {{ $json[\"status\"] }}\n⏰ <b>Updated At:</b> {{ new Date($(\"04c DB: Update Ticket Status\").item.json.updated_at).toLocaleString() }}\n",
        "chatId": "={{ $json.chat_id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "PEoTj5wxpFTeQVpI",
          "name": "Ticket Intake"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "7c2d91ca-0014-4d8d-97a4-bbd479274f88",
      "name": "Fehlgeschlagen benachrichtigen?",
      "type": "n8n-nodes-base.if",
      "position": [
        448,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4eb644e5-1340-492e-96e7-66198d2d72ad",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ !!$json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "16995a07-e4ed-4ebc-88a4-ce430ab0eee0",
      "name": "Eine SQL Abfrage ausführen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        672,
        96
      ],
      "parameters": {
        "query": "INSERT INTO workflow_errors \n  (workflow_id, workflow_name, execution_id, error_message, json_payload)\nVALUES \n  ($1, $2, $3, $4, $5::jsonb);\n",
        "options": {
          "queryReplacement": "={{ $workflow.id }},\n{{ $workflow.name }},\n{{ $execution.id }},\n{{ $json.error?.message || 'unknown' }},\n{{ JSON.stringify($json) }}\n"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "1ba78ac5-24f1-4b4a-bc2b-ce8e14419884",
      "name": "04c2 DB: Audit-Zeile einfügen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -672,
        192
      ],
      "parameters": {
        "query": "INSERT INTO ticket_audit\n  (ticket_id, correlation_id, action, new_status, actor_chat_id)\nVALUES\n  ($1, $2, 'update', $3, $4);\n",
        "options": {
          "queryReplacement": "={{ $json.id }},\n{{ $json.correlation_id }},\n{{ $json.status }},\n{{ $('02 FN: Verify Signature + TTL').item.json.actor }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "d9707ad4-fe4b-4335-90ff-aeba6d90cffc",
      "name": "Text (ablehnen)",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -448,
        384
      ],
      "webhookId": "ec8dcd4d-28ad-478c-a1b5-0e87133ff7c5",
      "parameters": {
        "text": "=❌ Manager rejected update.\nTicket <code>{{ $('02 FN: Verify Signature + TTL').item.json.correlation_id }}</code> stays unchanged.",
        "chatId": "chat_id",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "PEoTj5wxpFTeQVpI",
          "name": "Ticket Intake"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ccc7b9c3-107b-48cf-b52b-12e86547d378",
      "name": "04r0 DB: Ticket-ID abrufen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -896,
        384
      ],
      "parameters": {
        "query": "SELECT id, correlation_id \nFROM tickets \nWHERE correlation_id = $1::uuid;",
        "options": {
          "queryReplacement": "={{$json.correlation_id}}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "3e11f388-20d3-46e3-b41c-be7602b5b6bf",
      "name": "Eine SQL Abfrage1 ausführen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -672,
        384
      ],
      "parameters": {
        "query": "INSERT INTO ticket_audit \n  (ticket_id, correlation_id, action, new_status, actor_chat_id)\nVALUES \n  ($1, $2, 'reject', $3, $4);\n",
        "options": {
          "queryReplacement": "={{$json.id}},  {{$json.correlation_id}},  {{ $('02 FN: Verify Signature + TTL').item.json.new_status }},  {{ $('02 FN: Verify Signature + TTL').item.json.actor }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "6b3aedec-d739-486c-ba9a-854a87973e1c",
      "name": "Wenn gelöst",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "dc1d552d-728a-46cd-9024-14d88b01f77f",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json[\"status\"] }}",
              "rightValue": "resolved"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "34b8c0a5-478d-4354-89f0-d053c75a9880",
      "name": "Wenn in Bearbeitung",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a4a97bc7-96b5-4e5b-8ade-fd4f9d292016",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json[\"status\"] }}",
              "rightValue": "in_progress"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0c522006-2356-4235-a8d9-57e0399439b9",
      "name": "Aktionen",
      "type": "n8n-nodes-base.switch",
      "position": [
        -1360,
        368
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "approve",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b720a50f-1e38-477b-b828-f85c8e4e10d9",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json[\"action\"] }}",
                    "rightValue": "approve"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "reject",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "1f0d9637-5986-4e90-9f64-3829a12c15ef",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json[\"action\"] }}",
                    "rightValue": "reject"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "expired",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2ad38675-da19-4380-882c-0c3da132eea1",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json[\"action\"] }}",
                    "rightValue": "expired"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "invalid",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "74c8e5cd-1441-43ef-bf17-98956cf7e63c",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json[\"action\"] }}",
                    "rightValue": "invalid"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "5a1ead63-50e5-4740-8a62-6d8390496901",
      "name": "04e DB: Audit abgelaufen einfügen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -896,
        576
      ],
      "parameters": {
        "query": "INSERT INTO ticket_audit\n  (correlation_id, action, new_status, actor_chat_id)\nVALUES\n  ($1, 'expired', $2, 'system');\n",
        "options": {
          "queryReplacement": "={{ $json.correlation_id }}, {{ $json.new_status }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "ca421ae6-3163-410d-bf0d-a4896adc16fa",
      "name": "04i DB: Audit ungültig einfügen",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -896,
        768
      ],
      "parameters": {
        "query": "INSERT INTO ticket_audit\n  (correlation_id, action, new_status, actor_chat_id)\nVALUES\n  ($1, 'invalid', $2, 'system');\n",
        "options": {
          "queryReplacement": "={{ $json.correlation_id }}, {{ $json.new_status }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "id": "DeyLRt5YrGqjUrds",
          "name": "Postgres account"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "553fa208-5f0c-4a79-aeed-5e03477ad32a",
      "name": "05e Telegram: Abgelaufen benachrichtigen",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -672,
        576
      ],
      "webhookId": "b98a6506-35d0-41a8-8807-574cf8bb60db",
      "parameters": {
        "text": "=⏰ Manager notice: approval link expired for ticket <code>{{ $('02 FN: Verify Signature + TTL').item.json.correlation_id }}</code>.",
        "chatId": "chat_id",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "id": "PEoTj5wxpFTeQVpI",
          "name": "Ticket Intake"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "00c9e4e8-3b06-4df5-a2b6-3d831084ac45",
      "name": "05i Telegram: Ungültig alarmieren",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -672,
        768
      ],
      "webhookId": "964c3124-8fd4-4e92-b310-8ff4fa58cba0",
      "parameters": {
        "text": "=🚨 Invalid approval attempt detected.\nTicket: <code>{{ $('02 FN: Verify Signature + TTL').item.json.correlation_id }}</code>",
        "chatId": "chat_id",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "id": "PEoTj5wxpFTeQVpI",
          "name": "Ticket Intake"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "625211e5-1974-43b0-9855-1ce71577e3f3",
      "name": "Haftnotiz",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4272,
        256
      ],
      "parameters": {
        "width": 832,
        "height": 576,
        "content": "## 🛑 Human-in-the-Loop Approval Flow (n8n + Postgres + Telegram)\n\nThis workflow adds a secure approval step into your automations.  \nManagers receive signed approval/reject links in Telegram.  \nLinks expire after TTL, and every action is logged in Postgres.\n\n### ✨ Features\n- HMAC signed approval links with TTL  \n- Status updates via Telegram  \n- Audit table in Postgres  \n- Auto-expiry handling  \n\n### 📒 Requirements\n- n8n instance  \n- Postgres with `tickets` + `approvals` tables  \n- Telegram bot token  \n- One secret key set in env (`SECRET_KEY`)  \n\n### ⚙️ Setup\n1. Import workflow JSON  \n2. Create audit table (SQL provided)  \n3. Configure `.env` (DB, Telegram, SECRET_KEY)  \n4. Run a test ticket  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "fb72674c-6184-4754-9c02-61a9382764d4",
      "name": "Haftnotiz1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1664,
        160
      ],
      "parameters": {
        "color": 5,
        "height": 224,
        "content": "### 🔐 Security Note\nThis Code node requires `SECRET_KEY` to be set as an environment variable.  \nThe workflow will fail if it’s missing — this is intentional for security.  \nAdd `SECRET_KEY=your-secret` to your `.env`.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a87e7f7c-ed16-47db-a3ff-f634c8fcc999",
      "name": "Haftnotiz2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        576
      ],
      "parameters": {
        "color": 4,
        "height": 256,
        "content": "### 📲 Telegram Chat IDs\n- User-facing nodes use `={{ $json.chat_id }}` pulled from the ticket.  \n- Manager/admin alerts (e.g., invalid attempts) may use fixed IDs or env vars.  \nUpdate these values to your actual team setup.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c1f22f77-f5b9-4b70-ae85-e49cbe888894",
      "name": "Haftnotiz3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2144,
        368
      ],
      "parameters": {
        "height": 304,
        "content": "### 🔑 Generate Approval Links\n- Code node creates signed URLs  \n- Uses HMAC with secret key  \n- Adds expiry timestamp (TTL)  \n### ✅ Verify Link & TTL\n- Validates HMAC signature  \n- Checks expiry timestamp  \n- Rejects invalid or expired clicks  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "5c439394-3545-4abb-a65b-0fecbe36a979",
      "name": "Haftnotiz4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3392,
        256
      ],
      "parameters": {
        "color": 5,
        "width": 1168,
        "height": 1568,
        "content": "## 🛠 Step-by-Step Setup (Beginner Friendly)\n\n1. **Set environment variable**  \n   - Open your `.env` file (or environment config in your server).  \n   - Add:  \n     ```\n     SECRET_KEY=mysecretkey\n     ```  \n   - Restart n8n so it picks up the new variable.\n\n2. **Create Postgres tables** (run these in order):\n   - **Tickets**  \n     ```sql\n     CREATE TABLE tickets (\n       id BIGSERIAL PRIMARY KEY,\n       correlation_id UUID,\n       status TEXT,\n       subject TEXT,\n       chat_id TEXT,\n       updated_at TIMESTAMP DEFAULT NOW()\n     );\n     ```\n   - **Audit log**  \n     ```sql\n     CREATE TABLE ticket_audit (\n       id BIGSERIAL PRIMARY KEY,\n       ticket_id BIGINT,\n       correlation_id UUID,\n       action TEXT,\n       new_status TEXT,\n       actor_chat_id TEXT,\n       created_at TIMESTAMP DEFAULT NOW()\n     );\n     ```\n   - **Workflow errors**  \n     ```sql\n     CREATE TABLE workflow_errors (\n       id BIGSERIAL PRIMARY KEY,\n       workflow_id TEXT,\n       workflow_name TEXT,\n       execution_id TEXT,\n       error_message TEXT,\n       json_payload JSONB,\n       created_at TIMESTAMP DEFAULT NOW()\n     );\n     ```\n\n3. **Add credentials in n8n**  \n   - Go to *Credentials → Telegram API* → paste your bot token.  \n   - Go to *Credentials → Postgres* → add DB connection details.  \n   - **Important:** Replace `chat_id` placeholders in Telegram nodes with your real Telegram ID (use `@userinfobot` in Telegram to get it).\n\n4. **Import the workflow JSON**  \n   - Click *Import workflow* in n8n.  \n   - Select this file.  \n   - Save and activate.\n\n5. **Test an approval link**  \n   - Open a URL like this in your browser (replace with your own values):  \n     ```\n     http://YOUR_N8N_HOST/approval?cid=<UUID>&status=in_progress&action=approve&exp=1735939200&sig=<hmac-signature>\n     ```  \n   - `cid` → ticket correlation ID from your DB  \n   - `status` → `resolved` or `in_progress`  \n   - `action` → `approve` or `reject`  \n   - `exp` → expiry time in epoch seconds  \n   - `sig` → HMAC-SHA256 signature of `cid|status|exp`  \n\n6. **Verify it works**  \n   - Ticket status changes in the `tickets` table.  \n   - Row is added to `ticket_audit`.  \n   - Telegram sends a notification.  \n   - If the link is invalid/expired, you get an alert and it’s logged in `workflow_errors`.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "0c522006-2356-4235-a8d9-57e0399439b9": {
      "main": [
        [
          {
            "node": "3b7594c2-07c0-4baa-906b-daacff925853",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ccc7b9c3-107b-48cf-b52b-12e86547d378",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "5a1ead63-50e5-4740-8a62-6d8390496901",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ca421ae6-3163-410d-bf0d-a4896adc16fa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6b3aedec-d739-486c-ba9a-854a87973e1c": {
      "main": [
        [
          {
            "node": "da2d1a92-a349-40ba-8160-63847c560a23",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "34b8c0a5-478d-4354-89f0-d053c75a9880": {
      "main": [
        [
          {
            "node": "e2290e2c-1572-46ac-b690-46626ede3a35",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7c2d91ca-0014-4d8d-97a4-bbd479274f88": {
      "main": [
        [
          {
            "node": "16995a07-e4ed-4ebc-88a4-ce430ab0eee0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3e11f388-20d3-46e3-b41c-be7602b5b6bf": {
      "main": [
        [
          {
            "node": "d9707ad4-fe4b-4335-90ff-aeba6d90cffc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ccc7b9c3-107b-48cf-b52b-12e86547d378": {
      "main": [
        [
          {
            "node": "3e11f388-20d3-46e3-b41c-be7602b5b6bf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "17b6b2df-3792-4460-8f55-c32422d3ba2f": {
      "main": [
        [
          {
            "node": "19802b0c-d66b-4a6a-b009-8d7f721abcca",
            "type": "main",
            "index": 0
          },
          {
            "node": "828e2442-5f9e-4d12-a671-57b90d49e807",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1ba78ac5-24f1-4b4a-bc2b-ce8e14419884": {
      "main": [
        [
          {
            "node": "17b6b2df-3792-4460-8f55-c32422d3ba2f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3b7594c2-07c0-4baa-906b-daacff925853": {
      "main": [
        [
          {
            "node": "1ba78ac5-24f1-4b4a-bc2b-ce8e14419884",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5a1ead63-50e5-4740-8a62-6d8390496901": {
      "main": [
        [
          {
            "node": "553fa208-5f0c-4a79-aeed-5e03477ad32a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ca421ae6-3163-410d-bf0d-a4896adc16fa": {
      "main": [
        [
          {
            "node": "00c9e4e8-3b06-4df5-a2b6-3d831084ac45",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "08db80ea-aad6-45f7-973a-a0fbfa9285e0": {
      "main": [
        [
          {
            "node": "0c522006-2356-4235-a8d9-57e0399439b9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "da2d1a92-a349-40ba-8160-63847c560a23": {
      "main": [
        [
          {
            "node": "7c2d91ca-0014-4d8d-97a4-bbd479274f88",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "19802b0c-d66b-4a6a-b009-8d7f721abcca": {
      "main": [
        [
          {
            "node": "6b3aedec-d739-486c-ba9a-854a87973e1c",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "34b8c0a5-478d-4354-89f0-d053c75a9880",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e2290e2c-1572-46ac-b690-46626ede3a35": {
      "main": [
        [
          {
            "node": "7c2d91ca-0014-4d8d-97a4-bbd479274f88",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "411a0468-c67b-4762-93e2-1d4e116f1181": {
      "main": [
        [
          {
            "node": "08db80ea-aad6-45f7-973a-a0fbfa9285e0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Häufig gestellte Fragen

Wie verwende ich diesen Workflow?

Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.

Für welche Szenarien ist dieser Workflow geeignet?

Experte - Content-Erstellung, Multimodales KI

Ist es kostenpflichtig?

Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.

Workflow-Informationen
Schwierigkeitsgrad
Experte
Anzahl der Nodes26
Kategorie2
Node-Typen7
Schwierigkeitsbeschreibung

Für fortgeschrittene Benutzer, komplexe Workflows mit 16+ Nodes

Autor

Automation consultant specializing in n8n workflows that save businesses time and reduce costs. Experienced in designing ticketing systems, email parsers, and integrations with Postgres, Telegram, and APIs. I publish workflows to help teams streamline operations and build internal efficiency.

Externe Links
Auf n8n.io ansehen

Diesen Workflow teilen

Kategorien

Kategorien: 34