8
n8n 한국어amn8n.com

제 작업 흐름

고급

이것은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 query1 실행",
      "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