AutomationFlows โ€บ Web Scraping โ€บ Fluxo Principal โ€” Peddi Order

Fluxo Principal โ€” Peddi Order

Original n8n title: ๐Ÿค– Fluxo Principal โ€” Peddi Order

๐Ÿค– Fluxo Principal โ€” Peddi Order. Uses httpRequest. Webhook trigger; 44 nodes.

Webhook triggerโ˜…โ˜…โ˜…โ˜…โ˜… complexity44 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 44 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": "\ud83e\udd16 Fluxo Principal \u2014 Peddi Order",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "peddi-whatsapp-webhook",
        "responseMode": "lastNode",
        "options": {}
      },
      "name": "\ud83d\udce9 Webhook Trigger (WhatsApp)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        0,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const body = $input.first().json.body;\nconst telefone = (body.telefone || body.from || '').toString().replace(/[^0-9]/g, '');\nconst mensagem = (body.mensagem || body.message || body.text || '').toString().trim().toLowerCase();\nconst restaurante_id = body.restaurante_id || body.business_id || '';\n\nreturn {\n  telefone,\n  mensagem,\n  restaurante_id,\n  message_type: body.type || 'text',\n  raw: body\n};"
      },
      "name": "\ud83d\udd27 1. Normalizar entrada",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/sessoes?cliente_id=eq.{{ $json.telefone }}&restaurante_id=eq.{{ $json.restaurante_id }}&status=eq.ativa&select=*",
        "authentication": "genericCredentialType",
        "sendQuery": false,
        "sendBody": false,
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udd0e 2. Buscar sess\u00e3o ativa",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        500,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const sessions = $input.first().json;\nif (Array.isArray(sessions) && sessions.length > 0) {\n  return { session: sessions[0], exists: true };\n}\nreturn { session: null, exists: false };"
      },
      "name": "\ud83d\udd27 2b. Verificar se sess\u00e3o existe",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        750,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.exists }}",
              "value2": "true"
            }
          ]
        }
      },
      "name": "\u2753 Sess\u00e3o existe?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1000,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/sessoes",
        "authentication": "genericCredentialType",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "restaurante_id",
              "value": "={{ $json.restaurante_id }}"
            },
            {
              "name": "cliente_id",
              "value": "={{ $json.telefone }}"
            },
            {
              "name": "etapa_atual",
              "value": "inicio"
            },
            {
              "name": "carrinho",
              "value": "[]"
            },
            {
              "name": "bump_ofertado",
              "value": "false"
            },
            {
              "name": "upsell_ofertado",
              "value": "false"
            },
            {
              "name": "downsell_ofertado",
              "value": "false"
            },
            {
              "name": "status",
              "value": "ativa"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=representation"
            }
          ]
        }
      },
      "name": "\ud83c\udd95 2c. Criar nova sess\u00e3o",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1250,
        200
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/restaurantes?id=eq.{{ $json.restaurante_id }}&select=*",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83c\udfea 3. Buscar restaurante",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1250,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst restaurante = Array.isArray(data) ? data[0] : data;\nconst agora = new Date();\nconst horaAtual = agora.getHours() * 60 + agora.getMinutes();\n\nfunction toMinutos(h) {\n  if (!h) return null;\n  const partes = h.split(':').map(Number);\n  return partes[0] * 60 + (partes[1] || 0);\n}\n\nconst abertura = toMinutos(restaurante.horario_abertura);\nconst fechamento = toMinutos(restaurante.horario_fechamento);\n\nlet aberto = true;\nlet motivo = '';\n\nif (!restaurante.ativo) {\n  aberto = false;\n  motivo = 'Estamos fechados no momento! Aguarde nosso retorno. \ud83d\ude0a';\n} else if (abertura !== null && fechamento !== null) {\n  if (horaAtual < abertura || horaAtual > fechamento) {\n    aberto = false;\n    motivo = `Estamos fechados! Abrimos \u00e0s ${restaurante.horario_abertura}. \ud83d\ude0a`;\n  }\n}\n\nreturn {\n  restaurante,\n  aberto,\n  motivo,\n  horaAtual,\n  abertura,\n  fechamento\n};"
      },
      "name": "\ud83d\udd27 3b. Validar hor\u00e1rio",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        1500,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.aberto }}",
              "value2": "true"
            }
          ]
        }
      },
      "name": "\u2753 Est\u00e1 aberto?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1750,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\n// Enviar mensagem de fechado via Z-API\nconst telefone = data.telefone || data.cliente?.telefone;\nconst message = data.motivo || 'Estamos fechados! \ud83d\ude0a';\n\n// This node signals the webhook response\nreturn {\n  to: telefone,\n  message,\n  action: 'send_message'\n};"
      },
      "name": "\ud83d\udeab Enviar fora do hor\u00e1rio",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2000,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "// Merge session data with input\nconst input = $input.first().json;\nconst sessionData = $('\ud83d\udd0e 2. Buscar sess\u00e3o ativa').first().json;\nconst session = Array.isArray(sessionData) && sessionData.length > 0 ? sessionData[0] : null;\n\nconst menuMsg = input.mensagem;\nconst etapa = session?.etapa_atual || 'inicio';\nconst carrinho = session?.carrinho || [];\n\n// Comandos globais\nif (menuMsg === 'cancelar') {\n  return { acao: 'cancelar', etapa, carrinho };\n}\n\nswitch (etapa) {\n  case 'inicio': return { acao: 'boas_vindas', etapa, carrinho };\n  case 'menu': return { acao: 'categoria', etapa, carrinho, opcao: menuMsg };\n  case 'categoria': return { acao: 'adicionar_item', etapa, carrinho, opcao: menuMsg };\n  case 'bump': return { acao: 'resposta_bump', etapa, carrinho, opcao: menuMsg };\n  case 'carrinho':\n    if (menuMsg === '2') return { acao: 'upsell', etapa, carrinho };\n    return { acao: 'adicionar_mais', etapa, carrinho };\n  case 'upsell':\n    if (menuMsg === '1') return { acao: 'aceitar_upsell', etapa, carrinho };\n    return { acao: 'downsell', etapa, carrinho };\n  case 'downsell':\n    if (menuMsg === '1') return { acao: 'aceitar_downsell', etapa, carrinho };\n    return { acao: 'localizacao', etapa, carrinho };\n  case 'localizacao': return { acao: 'coletar_pagamento', etapa, carrinho, localizacao: menuMsg };\n  case 'pagamento': return { acao: 'confirmar', etapa, carrinho, pagamento: input.pagamento || menuMsg };\n  case 'confirmacao':\n    if (menuMsg === '1') return { acao: 'handoff', etapa, carrinho };\n    if (menuMsg === '2') return { acao: 'editar', etapa, carrinho };\n    return { acao: 'cancelar', etapa, carrinho };\n  default: return { acao: 'menu', etapa, carrinho };\n}"
      },
      "name": "\ud83d\udd00 4. Roteador principal",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        1500,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.acao }}",
              "value2": "boas_vindas"
            }
          ]
        }
      },
      "name": "\u2753 Rota: Boas-vindas?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1750,
        100
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/clientes?telefone=eq.{{ $json.telefone }}&restaurante_id=eq.{{ $json.restaurante_id }}&select=*",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udc64 5. Buscar/cliente",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        2000,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const clienteData = $input.first().json;\nconst cliente = Array.isArray(clienteData) ? clienteData[0] : clienteData;\nconst restaurante = $('\ud83c\udfea 3. Buscar restaurante').first().json;\nconst r = Array.isArray(restaurante) ? restaurante[0] : restaurante;\nconst nomeRestaurante = r?.nome || 'Restaurante';\n\nlet message = '';\nlet isNovo = false;\n\nif (!cliente || cliente.total_pedidos === 0) {\n  isNovo = true;\n  message = `Bem-vindo(a) ao ${nomeRestaurante}! \ud83d\udc4b\\n\\nSomos especialistas em deliver! \ud83d\ude0a\\n\\n1\ufe0f\u20e3 Ver card\u00e1pio\\n2\ufe0f\u20e3 Repetir \u00faltimo pedido\\n3\ufe0f\u20e3 Falar com atendente`;\n} else {\n  message = `Ol\u00e1 ${cliente.nome}! Que bom ter voc\u00ea de volta! \ud83d\ude0a\\n\\n1\ufe0f\u20e3 Ver card\u00e1pio\\n2\ufe0f\u20e3 Repetir \u00faltimo pedido\\n3\ufe0f\u20e3 Falar com atendente`;\n}\n\nreturn { message, isNovo, nome: cliente?.nome || '', total_pedidos: cliente?.total_pedidos || 0 };"
      },
      "name": "\ud83d\udcac 5b. Montar boas-vindas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2250,
        0
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/cardapio?restaurante_id=eq.{{ $json.restaurante_id }}&disponivel=eq.true&select=distinct.categoria",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udccb 6. Card\u00e1pio din\u00e2mico",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        2000,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "const categorias = $input.first().json;\nconst lista = Array.isArray(categorias) ? categorias : [];\n\nlet message = '\ud83c\udf7d\ufe0f Card\u00e1pio:\\n\\n';\nlista.forEach((cat, i) => {\n  message += `${i + 1}\ufe0f\u20e3 ${cat.categoria}\\n`;\n});\nmessage += '\\n0\ufe0f\u20e3 Voltar';\n\nreturn {\n  message,\n  categorias: lista,\n  categoria_atual: null\n};"
      },
      "name": "\ud83d\udcac 6b. Montar lista categorias",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2250,
        200
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/cardapio?restaurante_id=eq.{{ $json.restaurante_id }}&disponivel=eq.true&order=nome.asc",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83c\udf54 7. Buscar itens do card\u00e1pio",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        2250,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const itens = $input.first().json;\nconst lista = Array.isArray(itens) ? itens : [];\nconst opcao = parseInt($('\ud83d\udd00 4. Roteador principal').first().json.opcao) - 1;\nconst categorias = $('\ud83d\udccb 6. Card\u00e1pio din\u00e2mico').first().json;\nconst cats = Array.isArray(categorias) ? categorias : [];\n\n// Se estamos na etapa categoria, filtra pela categoria escolhida\nconst etapa = $('\ud83d\udd00 4. Roteador principal').first().json.etapa;\n\nlet itensFiltrados;\nif (etapa === 'categoria' && cats[opcao]) {\n  const catNome = cats[opcao].categoria;\n  itensFiltrados = lista.filter(i => i.categoria === catNome);\n} else {\n  itensFiltrados = lista;\n}\n\nlet message = 'Itens dispon\u00edveis:\\n\\n';\nitensFiltrados.forEach((item, i) => {\n  message += `${i + 1}\ufe0f\u20e3 ${item.nome} \u2014 R$ ${item.preco.toFixed(2)}\\n`;\n  if (item.descricao) message += `   ${item.descricao}\\n`;\n});\nmessage += '\\n0\ufe0f\u20e3 Voltar';\n\nreturn {\n  message,\n  itens: itensFiltrados,\n  item_escolhido: null\n};"
      },
      "name": "\ud83d\udcac 7b. Montar lista itens",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2500,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const itens = $('\ud83c\udf54 7. Buscar itens do card\u00e1pio').first().json;\nconst lista = Array.isArray(itens) ? itens : [];\nconst opcao = parseInt($('\ud83d\udd00 4. Roteador principal').first().json.opcao || '0');\nconst carrinhoAtual = $('\ud83d\udd00 4. Roteador principal').first().json.carrinho || [];\n\nif (opcao <= 0 || opcao > lista.length) {\n  return { acao: 'invalido', carrinho: carrinhoAtual };\n}\n\nconst itemEscolhido = lista[opcao - 1];\nconst novoCarrinho = [...carrinhoAtual, {\n  id: itemEscolhido.id,\n  nome: itemEscolhido.nome,\n  preco: itemEscolhido.preco,\n  categoria: itemEscolhido.categoria\n}];\n\n// Verificar se tem bump\nif (itemEscolhido.bump_sugerido_id) {\n  return {\n    acao: 'bump',\n    carrinho: novoCarrinho,\n    item_adicionado: itemEscolhido,\n    bump_id: itemEscolhido.bump_sugerido_id,\n    bump_preco: itemEscolhido.bump_preco,\n    bump_nome: ''\n  };\n}\n\nreturn {\n  acao: 'carrinho',\n  carrinho: novoCarrinho,\n  item_adicionado: itemEscolhido,\n  bump_id: null\n};"
      },
      "name": "\u2795 7c. Adicionar item ao carrinho",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2750,
        400
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/cardapio?id=eq.{{ $json.bump_id }}&select=*",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udd0d Buscar bump sugerido",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        3000,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const bumpData = $input.first().json;\nconst bump = Array.isArray(bumpData) ? bumpData[0] : bumpData;\n\nreturn {\n  message: `\u2705 Item adicionado!\\n\\n\ud83d\udd25 Por +R$ ${bump.preco.toFixed(2)} adicione ${bump.nome}!\\n\\n1\ufe0f\u20e3 Sim\\n2\ufe0f\u20e3 N\u00e3o obrigado`,\n  bump_item: bump\n};"
      },
      "name": "\ud83d\udcac 8a. Montar oferta bump",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3250,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst carrinhoAtual = $('\ud83d\udd00 4. Roteador principal').first().json.carrinho || [];\nconst opcao = $('\ud83d\udd00 4. Roteador principal').first().json.opcao || '';\n\nif (opcao === '1') {\n  // Aceitou bump\n  const bumpItem = $('\ud83d\udd0d Buscar bump sugerido').first().json;\n  const bump = Array.isArray(bumpItem) ? bumpItem[0] : bumpItem;\n  const novoCarrinho = [...carrinhoAtual, {\n    id: bump.id,\n    nome: `${bump.nome} (bump)`,\n    preco: bump.preco,\n    categoria: bump.categoria\n  }];\n\n  return {\n    acao: 'carrinho',\n    carrinho: novoCarrinho,\n    message: '\u00d3timo! Adicionado! \ud83c\udf89\\n\\n1\ufe0f\u20e3 Adicionar mais\\n2\ufe0f\u20e3 Fechar pedido',\n    bump_aceito: true\n  };\n}\n\nreturn {\n  acao: 'carrinho',\n  carrinho: carrinhoAtual,\n  message: 'Tudo bem! \ud83d\ude0a\\n\\n1\ufe0f\u20e3 Adicionar mais\\n2\ufe0f\u20e3 Fechar pedido',\n  bump_aceito: false\n};"
      },
      "name": "\ud83d\udd27 8b. Processar resposta bump",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3000,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "const carrinho = $('\ud83d\udd00 4. Roteador principal').first().json.carrinho || [];\nconst sessionData = $('\ud83d\udd0e 2. Buscar sess\u00e3o ativa').first().json;\nconst session = Array.isArray(sessionData) && sessionData.length > 0 ? sessionData[0] : null;\n\n// Verificar upsell j\u00e1 ofertado\nif (session?.upsell_ofertado) {\n  return { acao: 'pular_upsell', carrinho, upsell_ofertado: true };\n}\n\nconst restauranteData = $('\ud83c\udfea 3. Buscar restaurante').first().json;\nconst restaurante = Array.isArray(restauranteData) ? restauranteData[0] : restauranteData;\nconst ticketMedio = restaurante?.ticket_medio || 30;\n\nconst totalAtual = carrinho.reduce((sum, item) => sum + (item.preco || 0), 0);\n\nif (totalAtual < ticketMedio) {\n  // Buscar item de upsell\n  return {\n    acao: 'oferecer_upsell',\n    carrinho,\n    totalAtual,\n    diferenca: ticketMedio - totalAtual,\n    upsell_ofertado: false\n  };\n}\n\nreturn { acao: 'pular_upsell', carrinho, upsell_ofertado: false };"
      },
      "name": "\ud83d\udcb8 9. Verificar upsell",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2750,
        600
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/cardapio?restaurante_id=eq.{{ $json.restaurante_id }}&disponivel=eq.true&order=preco.desc&limit=1&select=*",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udd0d Buscar item upsell",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        3000,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "const upsellData = $input.first().json;\nconst upsell = Array.isArray(upsellData) ? upsellData[0] : upsellData;\nconst diff = $('\ud83d\udcb8 9. Verificar upsell').first().json.diferenca;\n\nif (!upsell) {\n  return { acao: 'pular_upsell', message: '' };\n}\n\nreturn {\n  acao: 'mostrar_upsell',\n  message: `\ud83c\udf54 Que tal completar seu pedido?\\n\\nAdicione ${upsell.nome} por apenas R$ ${upsell.preco.toFixed(2)}!\\n\\n1\ufe0f\u20e3 Aceitar\\n2\ufe0f\u20e3 N\u00e3o obrigado`,\n  upsell_item: upsell\n};"
      },
      "name": "\ud83d\udcac 9b. Montar oferta upsell",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3250,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "const opcao = $('\ud83d\udd00 4. Roteador principal').first().json.opcao || '';\nconst carrinhoAtual = $('\ud83d\udcb8 9. Verificar upsell').first().json.carrinho || [];\n\nif (opcao === '1') {\n  const upsellItem = $('\ud83d\udd0d Buscar item upsell').first().json;\n  const item = Array.isArray(upsellItem) ? upsellItem[0] : upsellItem;\n  const novoCarrinho = [...carrinhoAtual, {\n    id: item.id,\n    nome: `${item.nome} (upsell)`,\n    preco: item.preco,\n    categoria: item.categoria\n  }];\n\n  return {\n    acao: 'localizacao',\n    carrinho: novoCarrinho,\n    message: '',\n    upsell_aceito: true\n  };\n}\n\nreturn {\n  acao: 'downsell',\n  carrinho: carrinhoAtual,\n  message: '',\n  upsell_aceito: false\n};"
      },
      "name": "\ud83d\udd27 9c. Processar resposta upsell",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3500,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "const sessionData = $('\ud83d\udd0e 2. Buscar sess\u00e3o ativa').first().json;\nconst session = Array.isArray(sessionData) && sessionData.length > 0 ? sessionData[0] : null;\nconst carrinhoAtual = $('\ud83d\udd00 4. Roteador principal').first().json.carrinho || [];\n\nif (session?.downsell_ofertado) {\n  return { acao: 'pular_downsell', carrinho: carrinhoAtual };\n}\n\nreturn {\n  acao: 'oferecer_downsell',\n  carrinho: carrinhoAtual,\n  downsell_ofertado: false\n};"
      },
      "name": "\ud83d\udcb8 10. Verificar downsell",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2750,
        800
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/cardapio?restaurante_id=eq.{{ $json.restaurante_id }}&disponivel=eq.true&order=preco.asc&limit=1&select=*",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udd0d Buscar item downsell",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        3000,
        800
      ]
    },
    {
      "parameters": {
        "jsCode": "const downsellData = $input.first().json;\nconst downsell = Array.isArray(downsellData) ? downsellData[0] : downsellData;\n\nif (!downsell) {\n  return { acao: 'pular_downsell', message: '' };\n}\n\nreturn {\n  acao: 'mostrar_downsell',\n  message: `\ud83d\ude0a Tudo bem! Que tal experimentar ${downsell.nome} por apenas R$ ${downsell.preco.toFixed(2)}?\\n\\n1\ufe0f\u20e3 Sim\\n2\ufe0f\u20e3 N\u00e3o, quero finalizar`,\n  downsell_item: downsell\n};"
      },
      "name": "\ud83d\udcac 10b. Montar oferta downsell",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3250,
        800
      ]
    },
    {
      "parameters": {
        "jsCode": "const opcao = $('\ud83d\udd00 4. Roteador principal').first().json.opcao || '';\nconst carrinhoAtual = $('\ud83d\udcb8 10. Verificar downsell').first().json.carrinho || [];\n\nif (opcao === '1') {\n  const downsellItem = $('\ud83d\udd0d Buscar item downsell').first().json;\n  const item = Array.isArray(downsellItem) ? downsellItem[0] : downsellItem;\n  const novoCarrinho = [...carrinhoAtual, {\n    id: item.id,\n    nome: `${item.nome} (downsell)`,\n    preco: item.preco,\n    categoria: item.categoria\n  }];\n\n  return {\n    acao: 'localizacao',\n    carrinho: novoCarrinho,\n    message: '',\n    downsell_aceito: true\n  };\n}\n\nreturn {\n  acao: 'localizacao',\n  carrinho: carrinhoAtual,\n  message: '',\n  downsell_aceito: false\n};"
      },
      "name": "\ud83d\udd27 10c. Processar resposta downsell",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3500,
        800
      ]
    },
    {
      "parameters": {
        "jsCode": "return {\n  message: '\ud83d\udccd Seu pedido \u00e9 para:\\n\\n1\ufe0f\u20e3 Entrega (delivery)\\n2\ufe0f\u20e3 Retirada no balc\u00e3o\\n\\n0\ufe0f\u20e3 Voltar'\n};"
      },
      "name": "\ud83d\udcac 11. Perguntar localiza\u00e7\u00e3o",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2750,
        1000
      ]
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst opcao = $('\ud83d\udd00 4. Roteador principal').first().json.opcao || '';\n\nlet tipo = '';\nlet message = '';\n\nif (opcao === '1') {\n  tipo = 'entrega';\n  message = '\ud83d\udccd Manda seu endere\u00e7o: Rua, n\u00famero, bairro';\n} else if (opcao === '2') {\n  tipo = 'retirada';\n  message = '\ud83d\udecd\ufe0f OK! Retirada no balc\u00e3o!\\n\\nQual forma de pagamento?';\n}\n\nreturn { tipo, message, endereco: null };"
      },
      "name": "\ud83d\udd27 11b. Processar tipo entrega",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3000,
        1000
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/restaurantes?id=eq.{{ $json.restaurante_id }}&select=formas_pagamento&select=*",
        "authentication": "genericCredentialType",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            }
          ]
        }
      },
      "name": "\ud83d\udcb3 12. Buscar formas pagamento",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        2750,
        1200
      ]
    },
    {
      "parameters": {
        "jsCode": "const pagData = $input.first().json;\nconst restaurante = Array.isArray(pagData) ? pagData[0] : pagData;\nconst formas = restaurante?.formas_pagamento || ['Pix', 'Dinheiro', 'Cart\u00e3o', 'D\u00e9bito'];\n\nlet message = '\ud83d\udcb3 Formas de pagamento:\\n\\n';\nformas.forEach((f, i) => {\n  message += `${i + 1}\ufe0f\u20e3 ${f}\\n`;\n});nmessage += '\\n0\ufe0f\u20e3 Voltar';\n\nreturn { message, formas };"
      },
      "name": "\ud83d\udcac 12b. Montar menu pagamento",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3000,
        1200
      ]
    },
    {
      "parameters": {
        "jsCode": "const opcaoIndex = parseInt($('\ud83d\udd00 4. Roteador principal').first().json.opcao || '0') - 1;\nconst formas = $('\ud83d\udcac 12b. Montar menu pagamento').first().json.formas || [];\nconst pagamento = formas[opcaoIndex] || 'Pix';\n\nlet message = pagamento === 'Dinheiro' ? '\ud83d\udcb0 Troco para quanto?' : '';\n\nreturn { pagamento, precisa_troco: pagamento === 'Dinheiro', message };"
      },
      "name": "\ud83d\udd27 12c. Processar pagamento",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3250,
        1200
      ]
    },
    {
      "parameters": {
        "jsCode": "const carrinho = $('\ud83d\udd00 4. Roteador principal').first().json.carrinho || [];\nconst restauranteData = $('\ud83c\udfea 3. Buscar restaurante').first().json;\nconst restaurante = Array.isArray(restauranteData) ? restauranteData[0] : restauranteData;\nconst tipo = $('\ud83d\udd27 11b. Processar tipo entrega').first().json.tipo;\nconst pagamento = $('\ud83d\udd27 12c. Processar pagamento').first().json.pagamento;\nconst troco = $('\ud83d\udd00 4. Roteador principal').first().json.opcao || null;\n\nconst totalItens = carrinho.reduce((sum, item) => sum + (item.preco || 0), 0);\nconst freteGratis = restaurante?.valor_frete_gratis || 50;\nconst frete = totalItens >= freteGratis ? 0 : (restaurante?.valor_minimo || 5);\nconst totalFinal = totalItens + frete;\n\nconst endereco = $('\ud83d\udd27 11b. Processar tipo entrega').first().json.endereco || 'A confirmar';\n\nlet resumo = `\ud83d\udccb RESUMO DO PEDIDO\\n\\n`;\ncarrinho.forEach((item, i) => {\n  resumo += `${i + 1}x ${item.nome} \u2014 R$ ${item.preco.toFixed(2)}\\n`;\n});\nresumo += `\\n\ud83d\udcb0 Total itens: R$ ${totalItens.toFixed(2)}`;\nresumo += `\\n\ud83d\ude9a Frete: ${frete === 0 ? 'GR\u00c1TIS \ud83c\udf89' : 'R$ ' + frete.toFixed(2)}`;\nresumo += `\\n\ud83d\udcb5 Total final: R$ ${totalFinal.toFixed(2)}`;\nresumo += `\\n\ud83d\udccd ${tipo === 'entrega' ? 'Entrega em: ' + endereco : 'Retirada no balc\u00e3o'}`;\nresumo += `\\n\ud83d\udcb3 Pagamento: ${pagamento}`;\nif (troco) resumo += `\\n\ud83d\udcb0 Troco para: R$ ${troco}`;\nresumo += `\\n\\n1\ufe0f\u20e3 \u2705 Confirmar\\n2\ufe0f\u20e3 \u270f\ufe0f Editar\\n3\ufe0f\u20e3 \u274c Cancelar`;\n\nreturn {\n  message: resumo,\n  total_itens: totalItens,\n  frete,\n  total_final: totalFinal,\n  tipo,\n  endereco,\n  pagamento,\n  troco\n};"
      },
      "name": "\ud83d\udccb 13. Montar resumo + confirma\u00e7\u00e3o",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2750,
        1400
      ]
    },
    {
      "parameters": {
        "jsCode": "const sessionData = $('\ud83d\udd0e 2. Buscar sess\u00e3o ativa').first().json;\nconst session = Array.isArray(sessionData) && sessionData.length > 0 ? sessionData[0] : null;\nconst clienteData = $('\ud83d\udc64 5. Buscar/cliente').first().json;\nconst cliente = Array.isArray(clienteData) ? clienteData[0] : clienteData;\nconst resumo = $('\ud83d\udccb 13. Montar resumo + confirma\u00e7\u00e3o').first().json;\nconst bumps = resumo.itens?.filter(i => i.nome?.includes('(bump)')) || [];\n\nconst pedido = {\n  restaurante_id: $json.restaurante_id,\n  cliente_id: cliente?.id || $json.telefone,\n  itens: (resumo.itens || []).map(i => ({\n    nome: i.nome?.replace(' (bump)', '').replace(' (upsell)', '').replace(' (downsell)', ''),\n    preco: i.preco\n  })),\n  bumps: bumps.map(b => ({ nome: b.nome, preco: b.preco })),\n  upsell: $('\ud83d\udd27 9c. Processar resposta upsell').first().json.upsell_aceito || false,\n  total: resumo.total_final,\n  tipo: resumo.tipo,\n  endereco: resumo.endereco,\n  pagamento: resumo.pagamento,\n  troco: resumo.troco,\n  status: 'aguardando_pagamento'\n};\n\nreturn { pedido, message: '' };"
      },
      "name": "\ud83d\udce6 14. Montar payload pedido",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3000,
        1600
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/pedidos",
        "authentication": "genericCredentialType",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "restaurante_id",
              "value": "={{ $json.pedido.restaurante_id }}"
            },
            {
              "name": "cliente_id",
              "value": "={{ $json.pedido.cliente_id }}"
            },
            {
              "name": "itens",
              "value": "={{ $json.pedido.itens }}"
            },
            {
              "name": "bumps",
              "value": "={{ $json.pedido.bumps }}"
            },
            {
              "name": "upsell",
              "value": "={{ $json.pedido.upsell }}"
            },
            {
              "name": "total",
              "value": "={{ $json.pedido.total }}"
            },
            {
              "name": "tipo",
              "value": "={{ $json.pedido.tipo }}"
            },
            {
              "name": "endereco",
              "value": "={{ $json.pedido.endereco }}"
            },
            {
              "name": "pagamento",
              "value": "={{ $json.pedido.pagamento }}"
            },
            {
              "name": "troco",
              "value": "={{ $json.pedido.troco }}"
            },
            {
              "name": "status",
              "value": "={{ $json.pedido.status }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=representation"
            }
          ]
        }
      },
      "name": "\ud83d\udcbe 14b. Salvar pedido no Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        3250,
        1600
      ]
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "={{ $env.SUPABASE_URL }}/rest/v1/sessoes?id=eq.{{ $json.session_id }}",
        "authentication": "genericCredentialType",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "aguardando_pagamento"
            },
            {
              "name": "etapa_atual",
              "value": "finalizado"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Authorization",
              "value": "Bearer {{ $env.SUPABASE_SERVICE_KEY }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "name": "\ud83d\udd04 14c. Atualizar sess\u00e3o",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        3500,
        1600
      ]
    },
    {
      "parameters": {
        "jsCode": "const pedidoId = $('\ud83d\udcbe 14b. Salvar pedido no Supabase').first().json[0]?.id || '';\n\nreturn {\n  to: $json.telefone,\n  message: `\u2705 Pedido #${pedidoId.slice(0, 8)} recebido!\\n\\nUm atendente vai confirmar seu pagamento agora. Em breve voc\u00ea recebe a confirma\u00e7\u00e3o! \ud83d\ude0a\\n\\nAcompanhe pelo WhatsApp. \ud83d\ude80`\n};"
      },
      "name": "\ud83d\udcac 14d. Mensagem confirma\u00e7\u00e3o",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        3750,
        1600
      ]
    },
    {
      "parameters": {
        "jsCode": "const sessionData = $('\ud83d\udd0e 2. Buscar sess\u00e3o ativa').first().json;\nconst session = Array.isArray(sessionData) && sessionData.length > 0 ? sessionData[0] : null;\n\nif (!session) {\n  return { message: 'N\u00e3o entendi \ud83d\ude05 Digite o n\u00famero da op\u00e7\u00e3o ou 1 para o card\u00e1pio.' };\n}\n\nreturn { message: 'Op\u00e7\u00e3o inv\u00e1lida! Digite o n\u00famero da op\u00e7\u00e3o \ud83d\ude0a' };"
      },
      "name": "\ud83d\udcac Op\u00e7\u00e3o inv\u00e1lida (default)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2000,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "// Cancelar fluxo - resetar sess\u00e3o\nreturn {\n  message: '\u274c Pedido cancelado. Digite 1 para voltar ao card\u00e1pio! \ud83d\ude0a'\n};"
      },
      "name": "\ud83d\udcac Cancelar fluxo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2000,
        800
      ]
    },
    {
      "parameters": {
        "jsCode": "// Handoff manual para atendente\nreturn {\n  to: $json.telefone,\n  message: '\ud83d\udd01 Transferindo para um atendente...\\n\\nEm breve algu\u00e9m vai te atender! \ud83d\ude0a'\n};"
      },
      "name": "\ud83d\udcac Handoff atendente",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        2750,
        100
      ]
    },
    {
      "parameters": {
        "jsCode": "// Z-API send text\nconst config = $('\ud83d\udce9 Webhook Trigger (WhatsApp)').first().json;\nconst body = $input.first().json;\n\nreturn {\n  url: 'https://api.z-api.io/instances/{{INSTANCE_ID}}/token/{{TOKEN}}/send-text',\n  body: {\n    phone: body.to || body.telefone,\n    message: body.message\n  }\n};"
      },
      "name": "\ud83d\udce4 Enviar WhatsApp (Z-API)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        4000,
        100
      ]
    }
  ],
  "connections": {
    "\ud83d\udce9 Webhook Trigger (WhatsApp)": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 1. Normalizar entrada",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 1. Normalizar entrada": {
      "main": [
        [
          {
            "node": "\ud83d\udd0e 2. Buscar sess\u00e3o ativa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0e 2. Buscar sess\u00e3o ativa": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 2b. Verificar se sess\u00e3o existe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 2b. Verificar se sess\u00e3o existe": {
      "main": [
        [
          {
            "node": "\u2753 Sess\u00e3o existe?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83c\udfea 3. Buscar restaurante",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\u2753 Sess\u00e3o existe?": {
      "main": [
        [
          {
            "node": "\ud83d\udd00 4. Roteador principal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83c\udd95 2c. Criar nova sess\u00e3o",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83c\udd95 2c. Criar nova sess\u00e3o": {
      "main": [
        [
          {
            "node": "\ud83c\udfea 3. Buscar restaurante",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udfea 3. Buscar restaurante": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 3b. Validar hor\u00e1rio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 3b. Validar hor\u00e1rio": {
      "main": [
        [
          {
            "node": "\u2753 Est\u00e1 aberto?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2753 Est\u00e1 aberto?": {
      "main": [
        [
          {
            "node": "\ud83d\udd00 4. Roteador principal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udeab Enviar fora do hor\u00e1rio",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83d\udeab Enviar fora do hor\u00e1rio": {
      "main": [
        [
          {
            "node": "\ud83d\udce4 Enviar WhatsApp (Z-API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd00 4. Roteador principal": {
      "main": [
        [
          {
            "node": "\u2753 Rota: Boas-vindas?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2753 Rota: Boas-vindas?": {
      "main": [
        [
          {
            "node": "\ud83d\udc64 5. Buscar/cliente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udccb 6. Card\u00e1pio din\u00e2mico",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83d\udc64 5. Buscar/cliente": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 5b. Montar boas-vindas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 5b. Montar boas-vindas": {
      "main": [
        [
          {
            "node": "\ud83d\udce4 Enviar WhatsApp (Z-API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udccb 6. Card\u00e1pio din\u00e2mico": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 6b. Montar lista categorias",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 6b. Montar lista categorias": {
      "main": [
        [
          {
            "node": "\ud83c\udf54 7. Buscar itens do card\u00e1pio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udf54 7. Buscar itens do card\u00e1pio": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 7b. Montar lista itens",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 7b. Montar lista itens": {
      "main": [
        [
          {
            "node": "\u2795 7c. Adicionar item ao carrinho",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2795 7c. Adicionar item ao carrinho": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d Buscar bump sugerido",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udcb8 9. Verificar upsell",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83d\udd0d Buscar bump sugerido": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 8a. Montar oferta bump",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 8a. Montar oferta bump": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 8b. Processar resposta bump",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 8b. Processar resposta bump": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 7b. Montar lista itens",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcb8 9. Verificar upsell": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d Buscar item upsell",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udcac 11. Perguntar localiza\u00e7\u00e3o",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83d\udd0d Buscar item upsell": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 9b. Montar oferta upsell",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 9b. Montar oferta upsell": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 9c. Processar resposta upsell",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 9c. Processar resposta upsell": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 11. Perguntar localiza\u00e7\u00e3o",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udcb8 10. Verificar downsell",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83d\udcb8 10. Verificar downsell": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d Buscar item downsell",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udcac 11. Perguntar localiza\u00e7\u00e3o",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "\ud83d\udd0d Buscar item downsell": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 10b. Montar oferta downsell",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 10b. Montar oferta downsell": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 10c. Processar resposta downsell",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 10c. Processar resposta downsell": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 11. Perguntar localiza\u00e7\u00e3o",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 11. Perguntar localiza\u00e7\u00e3o": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 11b. Processar tipo entrega",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 11b. Processar tipo entrega": {
      "main": [
        [
          {
            "node": "\ud83d\udcb3 12. Buscar formas pagamento",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcb3 12. Buscar formas pagamento": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 12b. Montar menu pagamento",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 12b. Montar menu pagamento": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 12c. Processar pagamento",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 12c. Processar pagamento": {
      "main": [
        [
          {
            "node": "\ud83d\udccb 13. Montar resumo + confirma\u00e7\u00e3o",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udccb 13. Montar resumo + confirma\u00e7\u00e3o": {
      "main": [
        [
          {
            "node": "\ud83d\udce6 14. Montar payload pedido",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce6 14. Montar payload pedido": {
      "main": [
        [
          {
            "node": "\ud83d\udcbe 14b. Salvar pedido no Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcbe 14b. Salvar pedido no Supabase": {
      "main": [
        [
          {
            "node": "\ud83d\udd04 14c. Atualizar sess\u00e3o",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd04 14c. Atualizar sess\u00e3o": {
      "main": [
        [
          {
            "node": "\ud83d\udcac 14d. Mensagem confirma\u00e7\u00e3o",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcac 14d. Mensagem confirma\u00e7\u00e3o": {
      "main": [
        [
          {
            "node": "\ud83d\udce4 Enviar WhatsApp (Z-API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "timezone": "America/Sao_Paulo",
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all",
    "executionOrder": "v1"
  },
  "tags": [
    "peddi-order",
    "fluxo-principal",
    "delivery"
  ]
}
Pro

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

About this workflow

๐Ÿค– Fluxo Principal โ€” Peddi Order. Uses httpRequest. Webhook trigger; 44 nodes.

Source: https://github.com/Yuriwzzkk/peddi-order-flow/blob/cc29256d71ab236933109e1ff4d785240710cce2/public/n8n-workflows/fluxo-principal.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 n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports โ€“ get proper commit history, visual di

n8n, Execute Workflow Trigger, HTTP Request +1
Web Scraping

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.

HTTP Request
Web Scraping

This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia

HTTP Request
Web Scraping

This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c

HTTP Request