AutomationFlowsSlack & Telegram › P2-c2 Detector De Promesas (skeleton)

P2-c2 Detector De Promesas (skeleton)

P2-C2 Detector de Promesas (Skeleton). Uses googleSheets, httpRequest, whatsApp. Webhook trigger; 14 nodes.

Webhook trigger★★★★☆ complexity14 nodesGoogle SheetsHTTP RequestWhatsApp
Slack & Telegram Trigger: Webhook Nodes: 14 Complexity: ★★★★☆ Added:

This workflow follows the Google Sheets → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "P2-C2 Detector de Promesas (Skeleton)",
  "nodes": [
    {
      "parameters": {
        "path": "cobranza-in",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        0
      ],
      "id": "b2c00001-2222-4b02-a001-000000000001",
      "name": "Verificacion GET"
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.query[\"hub.challenge\"] }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        208,
        0
      ],
      "id": "b2c00001-2222-4b02-a001-000000000002",
      "name": "Respond to Webhook"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "cobranza-in",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000003",
      "name": "Entrada POST"
    },
    {
      "parameters": {
        "jsCode": "// Desenvuelve el sobre de Meta y filtra: solo mensajes de texto\nconst value = $json.body?.entry?.[0]?.changes?.[0]?.value;\nif (!value?.messages?.[0]?.text?.body) return []; // ignora estados, reacciones, etc.\nreturn [{ json: value }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        208,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000004",
      "name": "Normalizar"
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "TU_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "facturas",
          "mode": "name"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "telefono",
              "lookupValue": "={{ $('Normalizar').item.json.messages[0].from }}"
            }
          ]
        },
        "combineFilters": "AND",
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        416,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000005",
      "name": "Buscar Factura",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "jsCode": "// Solo seguimos si el n\u00famero tiene una factura abierta (pendiente, recordada o promesa).\n// Si no es un deudor, este flujo lo ignora en silencio.\nconst abiertas = [\"pendiente\", \"recordada\", \"promesa\"];\nconst facturas = $input.all().map(i => i.json)\n  .filter(f => f.factura_id && abiertas.includes(String(f.estado || \"\").trim().toLowerCase()));\nif (!facturas.length) return [];\n// Si tiene varias facturas abiertas, tomamos la de vencimiento m\u00e1s antiguo\nfacturas.sort((a, b) => String(a.fecha_vencimiento).localeCompare(String(b.fecha_vencimiento)));\nconst msg = $('Normalizar').first().json;\nreturn [{ json: {\n  factura: facturas[0],\n  telefono: msg.messages[0].from,\n  nombre: msg.contacts?.[0]?.profile?.name || facturas[0].cliente || \"\",\n  mensaje: msg.messages[0].text.body\n} }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        624,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000006",
      "name": "Filtrar Deudor"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://generativelanguage.googleapis.com/v1beta/models/MODELO_GEMINI:generateContent",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "key",
              "value": "TU_GEMINI_API_KEY"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"contents\": [{\n    \"parts\": [{\n      \"text\": \"Extrae del siguiente mensaje SOLO un objeto JSON estricto con esta forma exacta: {\\\"hay_promesa\\\": <true|false>, \\\"fecha_prometida\\\": \\\"<YYYY-MM-DD o null>\\\", \\\"monto\\\": <n\u00famero o null>}.\\n\\nMensaje del cliente: {{ $json.mensaje }}\"\n    }]\n  }],\n  \"generationConfig\": { \"responseMimeType\": \"application/json\", \"temperature\": 0.1 }\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        832,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000007",
      "name": "Gemini Extrae Promesa"
    },
    {
      "parameters": {
        "jsCode": "// Convierte la respuesta de Gemini a objeto. Si algo falla,\n// hay_promesa queda en false y el caso se escala a gesti\u00f3n humana (nunca se pierde).\nlet out = { hay_promesa: false, fecha_prometida: null, monto: null };\n\ntry {\n  const raw = $input.first().json.candidates[0].content.parts[0].text;\n  const clean = raw.replace(/```json|```/g, \"\").trim();\n  const parsed = JSON.parse(clean);\n  out = { ...out, ...parsed };\n  if (out.fecha_prometida && !/^\\d{4}-\\d{2}-\\d{2}$/.test(String(out.fecha_prometida))) out.fecha_prometida = null;\n  if (out.hay_promesa && !out.fecha_prometida) out.hay_promesa = false; // sin fecha no hay promesa agendable\n  out.hay_promesa = out.hay_promesa === true || out.hay_promesa === \"true\";\n} catch (e) {\n  out.error_parseo = e.message;\n}\n\nconst d = $('Filtrar Deudor').first().json;\nout.telefono = d.telefono;\nout.nombre = d.nombre;\nout.mensaje = d.mensaje;\nout.factura_id = d.factura.factura_id;\nout.cliente = d.factura.cliente || d.nombre;\nout.monto_factura = d.factura.monto;\nout.hoy = new Date().toISOString().slice(0, 10);\n\nreturn [{ json: out }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1040,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000008",
      "name": "Parsear Promesa"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "b2c00001-2222-4b02-a001-000000000201",
              "leftValue": "={{ $json.hay_promesa }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1248,
        176
      ],
      "id": "b2c00001-2222-4b02-a001-000000000009",
      "name": "Hay Promesa"
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "TU_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "promesas",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "factura_id": "={{ $json.factura_id }}",
            "telefono": "={{ $json.telefono }}",
            "cliente": "={{ $json.cliente }}",
            "fecha_promesa": "={{ $json.hoy }}",
            "fecha_prometida": "={{ $json.fecha_prometida }}",
            "monto_prometido": "={{ $json.monto || $json.monto_factura }}",
            "estado": "activa",
            "recordada": "no",
            "mensaje_original": "={{ $json.mensaje }}"
          },
          "matchingColumns": [
            "factura_id"
          ],
          "schema": []
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1456,
        64
      ],
      "id": "b2c00001-2222-4b02-a001-000000000010",
      "name": "Registrar Promesa"
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "TU_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "facturas",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "factura_id": "={{ $('Parsear Promesa').item.json.factura_id }}",
            "estado": "promesa",
            "notas": "={{ 'Promesa: ' + $('Parsear Promesa').item.json.fecha_prometida + ' \u2014 \"' + $('Parsear Promesa').item.json.mensaje + '\"' }}"
          },
          "matchingColumns": [
            "factura_id"
          ],
          "schema": []
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1664,
        64
      ],
      "id": "b2c00001-2222-4b02-a001-000000000011",
      "name": "Marcar Factura Promesa"
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "send",
        "phoneNumberId": "TU_PHONE_NUMBER_ID",
        "recipientPhoneNumber": "={{ $('Parsear Promesa').item.json.telefono }}",
        "textBody": "=\u00a1Perfecto{{ $('Parsear Promesa').item.json.nombre ? ', ' + $('Parsear Promesa').item.json.nombre : '' }}! \ud83d\ude4c Anotamos tu pago de ${{ $('Parsear Promesa').item.json.monto || $('Parsear Promesa').item.json.monto_factura }} para el {{ $('Parsear Promesa').item.json.fecha_prometida }}. Ese d\u00eda te enviaremos un recordatorio. \u00a1Gracias!",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.whatsApp",
      "typeVersion": 1,
      "position": [
        1872,
        64
      ],
      "id": "b2c00001-2222-4b02-a001-000000000012",
      "name": "Confirmar al Cliente"
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "TU_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "facturas",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "factura_id": "={{ $('Parsear Promesa').item.json.factura_id }}",
            "estado": "gestion_humana",
            "notas": "={{ 'Respuesta sin promesa clara: \"' + $('Parsear Promesa').item.json.mensaje + '\"' }}"
          },
          "matchingColumns": [
            "factura_id"
          ],
          "schema": []
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1456,
        288
      ],
      "id": "b2c00001-2222-4b02-a001-000000000013",
      "name": "Marcar Gestion Humana"
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "send",
        "phoneNumberId": "TU_PHONE_NUMBER_ID",
        "recipientPhoneNumber": "TU_NUMERO_DUENO",
        "textBody": "=\u26a0\ufe0f COBRANZA \u2014 Requiere gesti\u00f3n humana\n{{ $('Parsear Promesa').item.json.cliente || $('Parsear Promesa').item.json.telefono }} respondi\u00f3 sobre la factura {{ $('Parsear Promesa').item.json.factura_id }} (${{ $('Parsear Promesa').item.json.monto_factura }}) y no se detect\u00f3 una promesa de pago clara:\n\"{{ $('Parsear Promesa').item.json.mensaje }}\"\nResponder personalmente.",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.whatsApp",
      "typeVersion": 1,
      "position": [
        1664,
        288
      ],
      "id": "b2c00001-2222-4b02-a001-000000000014",
      "name": "Alerta al Dueno"
    }
  ],
  "connections": {
    "Verificacion GET": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Entrada POST": {
      "main": [
        [
          {
            "node": "Normalizar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalizar": {
      "main": [
        [
          {
            "node": "Buscar Factura",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar Factura": {
      "main": [
        [
          {
            "node": "Filtrar Deudor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtrar Deudor": {
      "main": [
        [
          {
            "node": "Gemini Extrae Promesa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Extrae Promesa": {
      "main": [
        [
          {
            "node": "Parsear Promesa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsear Promesa": {
      "main": [
        [
          {
            "node": "Hay Promesa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hay Promesa": {
      "main": [
        [
          {
            "node": "Registrar Promesa",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Marcar Gestion Humana",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Registrar Promesa": {
      "main": [
        [
          {
            "node": "Marcar Factura Promesa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Marcar Factura Promesa": {
      "main": [
        [
          {
            "node": "Confirmar al Cliente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Marcar Gestion Humana": {
      "main": [
        [
          {
            "node": "Alerta al Dueno",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "timezone": "America/Guayaquil"
  },
  "tags": []
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

P2-C2 Detector de Promesas (Skeleton). Uses googleSheets, httpRequest, whatsApp. Webhook trigger; 14 nodes.

Source: https://gist.github.com/Omar8485/bd4b6387b78d98e37189e53d5c0b0be9 — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS

HTTP Request, Shopify, SendGrid +5
Slack & Telegram

WF_UNIFIED_LEGAL_AUTOMATION. Uses googleSheets, httpRequest, telegram, telegramTrigger. Webhook trigger; 53 nodes.

Google Sheets, HTTP Request, Telegram +1
Slack & Telegram

Automates LinkedIn job searches across multiple countries and categories, filters results with AI, stores data in Google Sheets, and sends weekly Telegram notifications. Perfect for professionals seek

Telegram Trigger, Item Lists, HTTP Request +3
Slack & Telegram

01_order_processing_tilda. Uses stickyNote, googleSheets, httpRequest, telegram. Webhook trigger; 25 nodes.

Google Sheets, HTTP Request, Telegram
Slack & Telegram

Turn every sales meeting into a coaching opportunity. This workflow automatically analyzes tldv meeting recordings using OpenAI (GPT-4) to provide instant, actionable feedback to your sales team.

HTTP Request, Slack, Google Sheets