AutomationFlowsWeb Scraping › Sofia - Follow-up Automatico

Sofia - Follow-up Automatico

Sofia - Follow-up Automatico. Uses httpRequest. Scheduled trigger; 19 nodes.

Cron / scheduled trigger★★★★☆ complexity19 nodesHTTP Request
Web Scraping Trigger: Cron / scheduled Nodes: 19 Complexity: ★★★★☆ Added:

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": "Sofia - Follow-up Automatico",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "id": "3e3ebf83-ffe5-4e34-943e-183176c538be",
      "name": "Schedule 5min",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -3264,
        192
      ]
    },
    {
      "parameters": {
        "jsCode": "const now = new Date();\nconst brt = new Date(now.getTime() - 3 * 60 * 60 * 1000);\n\nconst day = brt.getUTCDay();\nconst hour = brt.getUTCHours();\n\n// Agora v\u00e1lido todos os dias (0 a 6), s\u00f3 controlando hor\u00e1rio\nconst isOk = hour >= 8 && hour < 18;\n\nconst since72h = new Date(now.getTime() - 72 * 3600 * 1000).toISOString();\n\nconsole.log('[FollowUp] BRT day:', day, 'hour:', hour, 'ok:', isOk);\n\nreturn [{ json: { ok: isOk, since72h, day, hour } }];"
      },
      "id": "ac732290-75ed-41bb-9aec-b3d0518d3b34",
      "name": "Verificar Contexto",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2992,
        192
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "biz-hours-check",
              "leftValue": "={{ $json.ok }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "cc7885ad-f1fc-4025-89f7-c9745197eab2",
      "name": "Horario Comercial?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -2704,
        192
      ]
    },
    {
      "parameters": {
        "url": "=https://eepzmmproiijsqelsbhi.supabase.co/rest/v1/sofia_sessions?stage=not.in.(reuniao_agendada,lead_frio,em_atendimento,transferido)&follow_up_count=lt.6&created_at=gt.{{ $json.since72h }}&select=*&order=created_at.asc",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "id": "c2e7bf03-0ad2-40c8-9506-386d61e44fe2",
      "name": "Buscar Sessoes",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -2432,
        192
      ],
      "alwaysOutputData": true,
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const THRESHOLDS_H = [0.083, 0.25, 1, 4, 12, 24]; // 5min, 15min, 1h, 4h, 12h, 24h\nconst now = Date.now();\nconst MS_H = 3600000;\nconst items = $input.all();\nconst toProcess = items\n  .map(i => i.json)\n  .filter(s => {\n    if (!s.session_id) return false;\n    const count = s.follow_up_count || 0;\n    if (count >= 6) return false;\n    const ref = count === 0\n      ? (s.updated_at || s.created_at)\n      : (s.last_followup_at || s.updated_at || s.created_at);\n    const hoursElapsed = (now - new Date(ref).getTime()) / MS_H;\n    return hoursElapsed >= THRESHOLDS_H[count];\n  });\nconsole.log('[FollowUp] Sessions eligible:', toProcess.length);\nreturn toProcess.map(s => ({ json: s }));\n"
      },
      "id": "4fa45010-9568-42bb-86f0-edf99be0d517",
      "name": "Filtrar Timing",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2144,
        192
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "7c9f4c2f-cea1-4c37-a408-83743c66b5b1",
      "name": "Loop Follow-ups",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -1904,
        128
      ]
    },
    {
      "parameters": {
        "url": "=https://api.wts.chat/chat/v2/session/{{ $json.session_id }}?includeDetails=AgentDetails&includeDetails=DepartmentsDetails&includeDetails=ChannelTypeDetails&includeDetails=ClassificationDetails",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "options": {}
      },
      "id": "2b46bb85-f581-42b5-b176-9a08c9411349",
      "name": "Checar Dept WTS",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -1696,
        144
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "dept-check",
              "leftValue": "={{ $json.departmentDetails.name }}",
              "rightValue": "Automa\u00e7\u00e3o",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "dcc55cc4-2291-4304-a06c-fb096949227c",
      "name": "Ainda com Bot?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -1536,
        160
      ]
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://eepzmmproiijsqelsbhi.supabase.co/rest/v1/sofia_sessions?session_id=eq.{{ $('Loop Follow-ups').first().json.session_id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ \"stage\": \"transferido\", \"updated_at\": new Date().toISOString() }) }}",
        "options": {}
      },
      "id": "f257856c-7474-45e3-8217-b8514fd70f9c",
      "name": "Auto-corrigir Stage",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -1392,
        352
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "=https://api.wts.chat/chat/v1/message?SessionId={{ $json.id }}&PageSize=100",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": []
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        -1344,
        128
      ],
      "id": "508ba20a-f9b6-4560-af65-84c16eceac99",
      "name": "HTTP Request",
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const messages = $json.items || [];\n\n// Verifica se existe mensagem de AGENTE HUMANO\n// - direction: TO_HUB = mensagem enviada pro cliente\n// - origin: USER = mensagem manual de agente (n\u00e3o API/bot)\n// - userId n\u00e3o null = tem usu\u00e1rio do WTS associado\n// OU senderId n\u00e3o null = agente espec\u00edfico enviou\n\nconst hasHumanIntervention = messages.some(msg => \n  msg.direction === 'TO_HUB' && \n  (msg.origin === 'USER' || (msg.userId && msg.origin !== 'API'))\n);\n\nconsole.log('[FollowUp] Session:', $('Loop Follow-ups').first().json.session_id, \n            'Messages:', messages.length, \n            'HasHuman:', hasHumanIntervention);\n\nreturn [{\n  json: {\n    ...($('Loop Follow-ups').first().json),\n    hasHumanIntervention\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1136,
        128
      ],
      "id": "35732504-27b3-47ae-80bf-ec33355fbcd1",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "e3f934ee-46b7-47f4-abd8-e78aebd183ad",
              "leftValue": "={{ $json.hasHumanIntervention }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -848,
        96
      ],
      "id": "ebf962d7-dc04-4c7f-8c2c-ed8ac77cded9",
      "name": "If"
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://eepzmmproiijsqelsbhi.supabase.co/rest/v1/sofia_sessions?session_id=eq.{{ $('Loop Follow-ups').first().json.session_id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ \"stage\": \"em_atendimento\", \"updated_at\": new Date().toISOString() }) }}",
        "options": {}
      },
      "id": "32ae162a-cdee-4420-b56f-ea2613220fc5",
      "name": "Auto-corrigir Stage1",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -992,
        320
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const s = $json;\nconst count = s.follow_up_count || 0;\nconst name = (s.lead_name || '').trim();\nconst n = name ? name.split(' ')[0] : '';\n\nconst msgs = [\n  // F1 \u2014 check-in natural, sem pressao\n  n ? `Oi, ${n}! Sumiu. Ficou alguma coisa no ar?` : 'Oi! Sumiu. Ficou alguma coisa no ar?',\n  // F2 \u2014 FOMO: concorrencia ja agindo\n  n ? `${n}, so avisando: os concorrentes que a gente atende estao respondendo leads 24/7 enquanto voce decide.` : 'So avisando: os concorrentes que a gente atende estao respondendo leads 24/7 enquanto voce decide.',\n  // F3 \u2014 urgencia real: cada dia custa\n  n ? `${n}, cada dia parado e receita escapando. Nao precisa ser hoje, mas quando decidir agir vai querer ter conversado antes.` : 'Cada dia parado e receita escapando. Nao precisa ser hoje, mas quando decidir agir vai querer ter conversado antes.',\n  // F4 \u2014 forcando decisao: sim ou nao\n  n ? `${n}, sem enrolacao: faz sentido pra voce ou nao faz? Me da um sim ou um nao que eu respeito os dois.` : 'Sem enrolacao: faz sentido pra voce ou nao faz? Me da um sim ou um nao que eu respeito os dois.',\n  // F5 \u2014 escassez concreta: vaga passando\n  n ? `${n}, passei sua vaga pra outra empresa essa semana. Se quiser retomar e so falar, mas nao consigo segurar muito tempo.` : 'Passei sua vaga pra outra empresa essa semana. Se quiser retomar e so falar, mas nao consigo segurar muito tempo.',\n  // F6 \u2014 encerramento elegante\n  n ? `Ultima aqui, ${n}. Se um dia fizer sentido, sabe onde me achar.` : 'Ultima aqui. Se um dia fizer sentido, sabe onde me achar.',\n];\n\nconst message = msgs[count] || msgs[5];\nconsole.log('[FollowUp] F' + (count+1) + ':', message.substring(0, 60));\nreturn [{\n  json: {\n    message,\n    session_id: s.session_id,\n    phone: s.phone,\n    channel_key: s.channel_key,\n    card_id: s.card_id,\n    follow_up_count: count\n  }\n}];\n"
      },
      "id": "fa26da4f-c6d2-4204-93ed-7a451a4a2d28",
      "name": "Montar Mensagem",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -624,
        96
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.wts.chat/chat/v1/session/{{ $('Ainda com Bot?').item.json.id }}/message",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/*+json",
        "body": "={\"text\": {{ JSON.stringify($json.message) }} }",
        "options": {}
      },
      "id": "921c101c-da31-4aed-bf10-f67c01c30599",
      "name": "Enviar Mensagem",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -384,
        96
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://eepzmmproiijsqelsbhi.supabase.co/rest/v1/sofia_sessions?session_id=eq.{{ $('Montar Mensagem').first().json.session_id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ \"follow_up_count\": $('Montar Mensagem').first().json.follow_up_count + 1, \"last_followup_at\": new Date().toISOString() }) }}",
        "options": {}
      },
      "id": "11bcc203-2bf9-4804-856e-de901ed5b032",
      "name": "Atualizar Sessao",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -64,
        96
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "is-last-followup",
              "leftValue": "={{ $('Montar Mensagem').first().json.follow_up_count }}",
              "rightValue": 5,
              "operator": {
                "type": "number",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "4d900f8e-d1f2-4e7f-b575-a46bec4107be",
      "name": "Foi F6?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        208,
        96
      ]
    },
    {
      "parameters": {
        "method": "PUT",
        "url": "=https://api.wts.chat/crm/v2/panel/card/{{ $('Montar Mensagem').first().json.card_id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/*+json",
        "body": "{ \"fields\": [\"StepId\"], \"stepId\": \"9a14f72f-16ef-43f2-8fb4-cc6458247767\" }",
        "options": {}
      },
      "id": "550fef5d-2d02-47ef-9ef7-9ec87100e682",
      "name": "Finalizar CRM Lead Frio",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        496,
        -16
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "PUT",
        "url": "=https://api.wts.chat/chat/v1/session/{{ $('Montar Mensagem').first().json.session_id }}/transfer",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/*+json",
        "body": "{ \"type\": \"DEPARTMENT\", \"newDepartmentId\": \"d1bc5071-b1e9-432d-a420-33c9831557d3\", \"options\": { \"stopBotInExecution\": true } }",
        "options": {}
      },
      "id": "1629489b-24c5-44d3-a890-344fde5f6b24",
      "name": "Transferir Equipe Vendas",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        784,
        -16
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Schedule 5min": {
      "main": [
        [
          {
            "node": "Verificar Contexto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar Contexto": {
      "main": [
        [
          {
            "node": "Horario Comercial?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Horario Comercial?": {
      "main": [
        [
          {
            "node": "Buscar Sessoes",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Buscar Sessoes": {
      "main": [
        [
          {
            "node": "Filtrar Timing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtrar Timing": {
      "main": [
        [
          {
            "node": "Loop Follow-ups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Follow-ups": {
      "main": [
        [],
        [
          {
            "node": "Checar Dept WTS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Checar Dept WTS": {
      "main": [
        [
          {
            "node": "Ainda com Bot?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ainda com Bot?": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Auto-corrigir Stage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auto-corrigir Stage": {
      "main": [
        [
          {
            "node": "Loop Follow-ups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "Auto-corrigir Stage1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Montar Mensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auto-corrigir Stage1": {
      "main": [
        [
          {
            "node": "Loop Follow-ups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Montar Mensagem": {
      "main": [
        [
          {
            "node": "Enviar Mensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Enviar Mensagem": {
      "main": [
        [
          {
            "node": "Atualizar Sessao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Atualizar Sessao": {
      "main": [
        [
          {
            "node": "Foi F6?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Foi F6?": {
      "main": [
        [
          {
            "node": "Finalizar CRM Lead Frio",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Follow-ups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Finalizar CRM Lead Frio": {
      "main": [
        [
          {
            "node": "Transferir Equipe Vendas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transferir Equipe Vendas": {
      "main": [
        [
          {
            "node": "Loop Follow-ups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "tags": []
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

Sofia - Follow-up Automatico. Uses httpRequest. Scheduled trigger; 19 nodes.

Source: https://github.com/PEDROMORRAESS/genionos-genions-sofia/blob/6e619f9488fb26cf20f983b1bb04502e8cf50f62/genions/sofia/n8n/sofia-followup.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

This template runs two scheduled workflows to govern Microsoft Entra ID (Azure AD) guest accounts by detecting stale users via Microsoft Graph, staging deletions in SharePoint with a 72-hour window, n

Microsoft SharePoint, Microsoft Teams, Microsoft Entra +1
Web Scraping

Spotify-Sync-Surrealdb-V1. Uses httpRequest, n8n-nodes-surrealdb, spotify. Scheduled trigger; 62 nodes.

HTTP Request, N8N Nodes Surrealdb, Spotify
Web Scraping

As n8n instances scale, teams often lose track of sub-workflows—who uses them, where they are referenced, and whether they can be safely updated. This leads to inefficiencies like unnecessary copies o

HTTP Request, n8n, N8N Trigger +1
Web Scraping

This workflow is an improvement of this workflow by Greg Brzezinka.

HTTP Request, Email Send, XML +1
Web Scraping

N8N-Workflow-Github-Manager. Uses github, httpRequest, n8n. Scheduled trigger; 38 nodes.

GitHub, HTTP Request, n8n