私のワークフロー

上級

これはContent Creation, Multimodal AI分野の自動化ワークフローで、26個のノードを含みます。主にIf, Code, Switch, Webhook, Postgresなどのノードを使用。 PostgresとTelegramを使用した安全な人間による承認プロセスの作成

前提条件
  • HTTP Webhookエンドポイント(n8nが自動生成)
  • PostgreSQLデータベース接続情報
  • Telegram Bot Token
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
  "meta": {
    "instanceId": "9c8d0d4640139c59e2bc183c0a14df0fbc0573cb91e494f5db8144fe78fe28ca"
  },
  "name": "My workflow",
  "tags": [],
  "nodes": [
    {
      "id": "411a0468-c67b-4762-93e2-1d4e116f1181",
      "name": "01 Webhook トリガー: 承認判断",
      "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: 署名+TTL検証",
      "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: チケットステータス更新",
      "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: チケット所有者取得",
      "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: 解決済みまたは進行中",
      "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: 解決通知",
      "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: 進行中通知",
      "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: 更新確認",
      "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": "通知失敗?",
      "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": "SQL クエリ実行",
      "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: 監査行挿入",
      "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": "テキスト (拒否)",
      "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: チケットID取得",
      "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": "SQL クエリ1実行",
      "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": "解決済みの場合",
      "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": "進行中の場合",
      "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": "アクション",
      "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: 期限切れ監査挿入",
      "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: 無効監査挿入",
      "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: 期限切れ通知",
      "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: 無効アラート",
      "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": "付箋",
      "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": "付箋1",
      "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": "付箋2",
      "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": "付箋3",
      "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": "付箋4",
      "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
          }
        ]
      ]
    }
  }
}
よくある質問

このワークフローの使い方は?

上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。

このワークフローはどんな場面に適していますか?

上級 - コンテンツ作成, マルチモーダルAI

有料ですか?

このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。

ワークフロー情報
難易度
上級
ノード数26
カテゴリー2
ノードタイプ7
難易度説明

上級者向け、16ノード以上の複雑なワークフロー

作成者

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.

外部リンク
n8n.ioで表示

このワークフローを共有

カテゴリー

カテゴリー: 34