Mis flujos de trabajo

Avanzado

Este es unContent Creation, Multimodal AIflujo de automatización del dominio deautomatización que contiene 26 nodos.Utiliza principalmente nodos como If, Code, Switch, Webhook, Postgres. Crear un proceso de aprobación humana seguro usando Postgres y Telegram

Requisitos previos
  • Punto final de HTTP Webhook (n8n generará automáticamente)
  • Información de conexión de la base de datos PostgreSQL
  • Bot Token de Telegram
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "meta": {
    "instanceId": "9c8d0d4640139c59e2bc183c0a14df0fbc0573cb91e494f5db8144fe78fe28ca"
  },
  "name": "My workflow",
  "tags": [],
  "nodes": [
    {
      "id": "411a0468-c67b-4762-93e2-1d4e116f1181",
      "name": "01 Webhook Disparador: Decisión de Aprobación",
      "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: Verificar Firma + 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 BD: Actualizar Estado del Ticket",
      "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 BD: Obtener Propietario del Ticket",
      "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 SI: Resuelto o En Progreso",
      "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: Notificar Resuelto",
      "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: Notificar En Progreso",
      "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: Confirmación de Actualización",
      "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": "¿Notificar Fallo?",
      "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": "Ejecutar consulta 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 BD: Insertar Fila de Auditoría",
      "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": "Texto (rechazar)",
      "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 BD: Obtener ID del Ticket",
      "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": "Ejecutar consulta SQL1",
      "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": "Si Resuelto",
      "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": "Si en_progreso",
      "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": "Acciones",
      "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 BD: Insertar Auditoría Expirada",
      "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 BD: Insertar Auditoría Inválida",
      "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: Notificar Expirado",
      "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: Alerta Inválida",
      "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": "Nota Adhesiva",
      "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": "Nota Adhesiva1",
      "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": "Nota Adhesiva2",
      "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": "Nota Adhesiva3",
      "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": "Nota Adhesiva4",
      "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
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Creación de contenido, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos26
Categoría2
Tipos de nodos7
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

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.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34