Skip to main content

# 💼 Casos de Uso e Exemplos Práticos

API Krayin CRM - Soluções Prontas

GuiaScripts dee implementações prontas para usar Copy-paste friendly para agilizar integração com N8N, WhatsApp (Evolution API) e Frontend Operaes.


📋🎯 Índice

CENÁRIOS
    COMUNS
  1. DE N8N Integration
  2. WhatsApp (Evolution API)
  3. Frontend Central Memude
  4. Outras Integrações

1. N8N IntegrationINTEGRAÇÃO

Visão1. Geral📧 INTEGRAÇÃO COM FORMULÁRIO DE CONTATO

N8N

HTML é+ umaJavaScript plataforma(Frontend)

<!DOCTYPE html>
<html>
<head>
    <title>Contato - Captura de automaçãoLeads</title>
    que<script conectasrc="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
    <form id="contatoForm">
        <input type="text" id="nome" placeholder="Nome completo" required>
        <input type="email" id="email" placeholder="Email" required>
        <input type="tel" id="telefone" placeholder="Telefone">
        <input type="text" id="empresa" placeholder="Empresa">
        <select id="interesse">
            <option value="produto-a">Produto A</option>
            <option value="produto-b">Produto B</option>
            <option value="consultoria">Consultoria</option>
        </select>
        <textarea id="mensagem" placeholder="Como podemos ajudar?"></textarea>
        <button type="submit">Enviar</button>
    </form>

    <script>
        document.getElementById('contatoForm').addEventListener('submit', async (e) => {
            e.preventDefault();

            const dadosLead = {
                nome: document.getElementById('nome').value,
                email: document.getElementById('email').value,
                telefone: document.getElementById('telefone').value,
                empresa: document.getElementById('empresa').value,
                interesse: document.getElementById('interesse').value,
                mensagem: document.getElementById('mensagem').value
            };

            try {
                // Enviar para seu backend
                await axios.post('/api/criar-lead', dadosLead);

                // Feedback ao Krayinusuário
                viaalert('Obrigado! HTTPEntraremos Requestem nodes.

contato
┌─────────────┐em Webhookbreve.');
                ┌─────────────┐document.getElementById('contatoForm').reset();

                API// ┌─────────────┐Google Analytics Trigger/ Facebook ───────────────►Pixel
                gtag('event', N8N'lead_generated', {
                    ───────────►'event_category': 'lead',
                    Krayin'event_label': dadosLead.interesse
                });

            } catch (WhatsApp)error) {
                console.error('Erro:', Workflowerror);
                alert('Erro ao CRMenviar. Tente └─────────────┘novamente.');
            └─────────────┘}
        └─────────────┘});
    </script>
</body>
</html>

Backend (Node.js/Express)

// server.js
const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());

// Configuração Inicialda 

Passo 1: Obter Token doAPI Krayin

curlconst -XKRAYIN_CONFIG POST= "{
    baseURL: 'https://crm.memudecore.com.br/api/v1/login"v1',
    \token: -Hprocess.env.KRAYIN_TOKEN
"};

const krayin = axios.create({
    baseURL: KRAYIN_CONFIG.baseURL,
    headers: {
        'Authorization': `Bearer ${KRAYIN_CONFIG.token}`,
        'Content-Type:Type': 'application/x-www-form-urlencoded"json',
        \'Accept': -d'application/json'
    "email=admin@memudecore.com.br&password=sua_senha&device_name=N8N"}
});

Salve// Endpoint para receber leads do formulário app.post('/api/criar-lead', async (req, res) => { try { const { nome, email, telefone, empresa, interesse, mensagem } = req.body; // Validação tokenbásica retornado.

if

Passo(!nome 2:|| !email) { return res.status(400).json({ error: 'Nome e email são obrigatórios' }); } // Determinar valor estimado baseado no interesse const valoresInteresse = { 'produto-a': 5000, 'produto-b': 8000, 'consultoria': 15000 }; // Criar Credentiallead no N8N

  1. Acesse N8N → Settings → Credentials
  2. Clique Add Credential
  3. Selecione Header Auth
  4. Configure:
    • Name: Krayin API
    • const
    • leadData Header Name: Authorization
    • Header Value: Bearer {seu_token}

Workflow: Criar Lead de Formulário

┌─────────────────────────────────────────────────────────────────┐
│                         N8N WORKFLOW                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  [Webhook Trigger] → [Validate Data] → [HTTP Request] → [Done] │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Node 1: Webhook Trigger

{
  "httpMethod": "POST",
  "path": "form-to-krayin",
  "responseMode": "onReceived"
}

Node 2: Set Node (Transformar Dados)

return= {
            title: `$json.body.{empresa || 'Lead'} - $json.body.nome,{nome}`,
            source_id:description: `Interesse: ${interesse}\nMensagem: ${mensagem}`,
            lead_value: valoresInteresse[interesse] || 2000,
            lead_source_id: 1, // Site
            lead_type_id: 1,   sales_owner_id:// 1,Padrão
            value: parseFloat($json.body.valor) || 0,
  description: $json.body.mensagem || '',
  person_data:person: {
                name: $json.body.nome,
                email:job_title: empresa ? 'Contato' : null,
                emails: [
                    { value: email, label: 'work' }
                ],
                contact_numbers: telefone ? [
                    { value: telefone, label: 'mobile' }
                ] : []
            }
        };

        // Se tiver empresa, adicionar organização
        if (empresa) {
            leadData.person.organization = {
                name: empresa
            };
        }

        const response = await krayin.post('/leads', leadData);

        // Log para auditoria
        console.log(`✅ Lead criado: $json.body.email,{response.data.data.id} phone:- $json.body.telefone{nome}`);

        // Criar atividade de follow-up automático
        await criarFollowUpAutomatico(response.data.data.id, interesse);

        res.json({
            success: true,
            leadId: response.data.data.id,
            message: 'Lead criado com sucesso!'
        });

    } catch (error) {
        console.error('❌ Erro criando lead:', error.response?.data || error.message);

        res.status(500).json({
            error: 'Erro interno. Tente novamente.'
        });
    }
});

async function criarFollowUpAutomatico(leadId, interesse) {
    try {
        const dataFollowUp = new Date();
        dataFollowUp.setHours(dataFollowUp.getHours() + 2); // 2 horas depois

        const atividade = {
            title: `Follow-up: ${interesse}`,
            type: 'call',
            comment: 'Entrar em contato para qualificar lead',
            schedule_from: dataFollowUp.toISOString(),
            schedule_to: new Date(dataFollowUp.getTime() + 30*60000).toISOString(), // +30 min
            lead_id: leadId,
            user_id: 1 // Admin
        };

        await krayin.post('/activities', atividade);
        console.log(`📅 Follow-up agendado para lead ${leadId}`);

    } catch (error) {
        console.error('❌ Erro criando follow-up:', error.message);
    }
}

app.listen(3000, () => {
    console.log('🚀 Servidor rodando na porta 3000');
});

Node
3:

2. HTTP🛒 RequestINTEGRAÇÃO COM E-COMMERCE (CriarWOOCOMMERCE)

Contato)

Plugin WordPress/WooCommerce

<?php
// wp-content/plugins/krayin-integration/krayin-integration.php

/**
 * Plugin Name: Krayin CRM Integration
 * Description: Sincroniza pedidos WooCommerce com Krayin CRM
 * Version: 1.0.0
 */

class KrayinWooIntegration {
    "method":private "POST",$api_base;
    "url":private "$api_token;

    public function __construct() {
        $this->api_base = 'https://crm.memudecore.com.br/api/v1/contacts/persons"v1';
        $this->api_token = get_option('krayin_api_token');

        add_action('init', array($this, 'init'));
    }

    public function init() {
        // Hook para novos pedidos
        add_action('woocommerce_new_order', array($this, 'novo_pedido'), 10, 1);

        // Hook para mudança de status
        add_action('woocommerce_order_status_changed', array($this, 'status_mudou'), 10, 3);

        // Adicionar settings page
        add_action('admin_menu', array($this, 'admin_menu'));
    }

    public function novo_pedido($order_id) {
        $order = wc_get_order($order_id);

        if (!$order) return;

        // Criar lead no Krayin
        $lead_data = array(
            'title' => "Pedido #{$order_id} - {$order->get_billing_first_name()} {$order->get_billing_last_name()}",
            'description' => $this->get_order_description($order),
            'lead_value' => floatval($order->get_total()),
            'lead_source_id' => 2, // E-commerce
            'lead_type_id' => 1,
            'person' => array(
                'name' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
                'emails' => array(
                    array('value' => $order->get_billing_email(), 'label' => 'billing')
                ),
                'contact_numbers' => array(
                    array('value' => $order->get_billing_phone(), 'label' => 'billing')
                ),
                'organization' => $order->get_billing_company() ? array(
                    'name' => $order->get_billing_company(),
                    'address' => $this->get_billing_address($order)
                ) : null
            )
        );

        $response = $this->fazer_request('POST', '/leads', $lead_data);

        if ($response && !is_wp_error($response)) {
            // Salvar ID do lead no pedido
            $body = json_decode(wp_remote_retrieve_body($response), true);
            if (isset($body['data']['id'])) {
                update_post_meta($order_id, '_krayin_lead_id', $body['data']['id']);

                // Log
                error_log("✅ Lead {$body['data']['id']} criado para pedido #{$order_id}");

                // Criar atividade para pedido pago
                if ($order->is_paid()) {
                    $this->criar_atividade_pedido_pago($body['data']['id'], $order_id);
                }
            }
        }
    }

    public function status_mudou($order_id, $old_status, $new_status) {
        $lead_id = get_post_meta($order_id, '_krayin_lead_id', true);

        if (!$lead_id) return;

        $order = wc_get_order($order_id);

        // Criar atividade baseada no status
        $atividades_status = array(
            'processing' => array(
                'title' => "Pedido #{$order_id} em processamento",
                'type' => 'task',
                'comment' => 'Pedido confirmado e em processamento'
            ),
            'shipped' => array(
                'title' => "Pedido #{$order_id} enviado",
                'type' => 'task',
                'comment' => 'Produto enviado ao cliente'
            ),
            'completed' => array(
                'title' => "Pedido #{$order_id} concluído",
                'type' => 'task',
                'comment' => 'Pedido entregue e concluído - oportunidade para upsell'
            ),
            'cancelled' => array(
                'title' => "Pedido #{$order_id} cancelado",
                'type' => 'call',
                'comment' => 'Entender motivo do cancelamento e tentar recuperar'
            )
        );

        if (isset($atividades_status[$new_status])) {
            $atividade = $atividades_status[$new_status];
            $atividade['lead_id'] = $lead_id;
            $atividade['user_id'] = 1;

            $this->fazer_request('POST', '/activities', $atividade);
        }

        // Atualizar valor do lead se houver mudanças
        if ($new_status === 'refunded') {
            $this->atualizar_lead($lead_id, array(
                'lead_value' => 0,
                'status' => 'lost',
                'lost_reason' => 'Pedido reembolsado'
            ));
        }
    }

    private function get_order_description($order) {
        $items = array();

        foreach ($order->get_items() as $item) {
            $items[] = $item->get_name() . ' (x' . $item->get_quantity() . ')';
        }

        return "Produtos: " . implode(', ', $items) . "\n" .
               "Total: R$ " . $order->get_total() . "\n" .
               "Método de pagamento: " . $order->get_payment_method_title();
    }

    private function get_billing_address($order) {
        return $order->get_billing_address_1() . ', ' .
               $order->get_billing_city() . ' - ' .
               $order->get_billing_state() . ' ' .
               $order->get_billing_postcode();
    }

    private function criar_atividade_pedido_pago($lead_id, $order_id) {
        $atividade = array(
            'title' => "Follow-up pós-venda - Pedido #{$order_id}",
            'type' => 'call',
            'comment' => 'Verificar satisfação e oportunidades de cross-sell',
            'schedule_from' => date('c', strtotime('+7 days')),
            'schedule_to' => date('c', strtotime('+7 days +30 minutes')),
            'lead_id' => $lead_id,
            'user_id' => 1
        );

        $this->fazer_request('POST', '/activities', $atividade);
    }

    private function fazer_request($method, $endpoint, $data = null) {
        $url = $this->api_base . $endpoint;

        $args = array(
            'method' => $method,
            'headers' => array(
                'Authorization' => 'Bearer ' . $this->api_token,
                'Content-Type' => 'application/json',
                'Accept' => 'application/json'
            ),
            'timeout' => 30
        );

        if ($data) {
            $args['body'] = json_encode($data);
        }

        return wp_remote_request($url, $args);
    }

    private function atualizar_lead($lead_id, $updates) {
        return $this->fazer_request('PUT', "authentication": /leads/{$lead_id}"predefinedCredentialType", "nodeCredentialType":$updates);
    "httpHeaderAuth",}

    "sendHeaders":public true,function "headerParameters":admin_menu() {
        "Content-Type":add_options_page(
            "application/json"'Krayin Integration',
            'Krayin CRM',
            'manage_options',
            'krayin-settings',
            array($this, 'settings_page')
        );
    }

    public function settings_page() {
        if (isset($_POST['krayin_api_token'])) {
            update_option('krayin_api_token', sanitize_text_field($_POST['krayin_api_token']));
            echo '<div class="sendBody":notice true,notice-success"><p>Token salvo com sucesso!</p></div>';
        }

        $token = get_option('krayin_api_token', '');
        ?>
        <div class="bodyParameters":wrap">
            <h1>Configurações Krayin CRM</h1>
            <form method="post">
                <table class="form-table">
                    <tr>
                        <th scope="row">API Token</th>
                        <td>
                            <input type="password" name="krayin_api_token" value="<?php echo esc_attr($token); ?>" class="regular-text" />
                            <p class="description">Token de acesso da API Krayin</p>
                        </td>
                    </tr>
                </table>
                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }
}

// Inicializar plugin
new KrayinWooIntegration();
?>

3. 💬 INTEGRAÇÃO COM WHATSAPP BUSINESS

Webhook N8N + WhatsApp

{
  "name": "WhatsApp para Krayin CRM",
  "nodes": [
    {
      "parameters": {
        "path": "whatsapp-webhook",
        "options": {}
      },
      "name": "Webhook WhatsApp",
      "type": "n8n-nodes-base.webhook",
      "position": [240, 300]
    },
    {
      "parameters": {
        "jsCode": "// Processar mensagem do WhatsApp\nconst message ={{ $json.person_data.entry[0].changes[0].value.messages[0];\nconst contact = $json.entry[0].changes[0].value.contacts[0];\n\n// Extrair informações\nconst phone = message.from;\nconst name = contact.profile.name;\nconst messageText = message.text.body;\nconst timestamp = message.timestamp;\n\n// Detectar intenção (palavras-chave)\nconst isLead = /(preço|orçamento|produto|serviço|comprar|interessado)/i.test(messageText);\nconst isSupport = /(problema|erro|ajuda|suporte|dúvida)/i.test(messageText);\n\nreturn {\n  phone,\n  name,\n  message: messageText,\n  timestamp: new Date(parseInt(timestamp) * 1000).toISOString(),\n  isLead,\n  isSupport,\n  source: 'whatsapp'\n};"
      }}",
      "emails"name": "Processar Mensagem",
      "type": "n8n-nodes-base.code",
      "position": [460, 300]
    },
    {
      "value"parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.person_data.email }isLead}}",
              "label"value2": "work"}],
    "contact_numbers": [{"value": "={{ $json.person_data.phonetrue
            }}",
          "label": "work"}]
        }
      },
      
"name":

Node 4:Lead?", HTTP"type": Request"n8n-nodes-base.if", (Criar"position": Lead)

[680,
300]
    },
    {
      "method"parameters": "POST",{
        "url": "https://crm.memudecore.com.br/api/v1/leads",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "httpHeaderAuth"krayinApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{$credentials.krayinApi.token}}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "title"parameters": [
            {
              "name": "={{ $('Set').item.json.title }}"title",
    "source_id": 1,
    "lead_type_id": 1,
    "sales_owner_id": 1,
              "value": "=Lead WhatsApp - {{ $('Set').item.json.value }}",
    "contact_person_id": "={{ $json.data.id }}",
    "description": "={{ $('Set').item.json.description }name}}"
            }
}

Workflow: Sync Krayin → Google Sheets

// Node: Schedule Trigger (diário às 8h)

// Node: HTTP Request - Buscar leads do dia anterior,
            {
              "method"name": "GET"description",
              "value": "Mensagem inicial: {{$json.message}}"
            },
            {
              "name": "lead_source_id",
              "value": "3"
            },
            {
              "name": "lead_type_id",
              "value": "1"
            },
            {
              "name": "lead_value",
              "value": "2000"
            },
            {
              "name": "person",
              "value": {\n  \"name\": \"{{$json.name}}\",\n  \"contact_numbers\": [\n    {\n      \"value\": \"{{$json.phone}}\",\n      \"label\": \"whatsapp\"\n    }\n  ]\n}\n"
            }
          ]
        },
        "options": {}
      },
      "name": "Criar Lead Krayin",
      "type": "n8n-nodes-base.httpRequest",
      "position": [900, 200]
    },
    {
      "parameters": {
        "url": "https://api.whatsapp.com/send",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "phone",
              "value": "{{$json.phone}}"
            },
            {
              "name": "text",
              "value": "Olá {{$json.name}}! 👋\\n\\nObrigado pelo seu interesse! Nossa equipe entrará em contato em breve.\\n\\nEnquanto isso, que tal conhecer nossos produtos em nosso site?\\n\\n🌐 https://meusite.com.br"
            }
          ]
        }
      },
      "name": "Resposta Automática",
      "type": "n8n-nodes-base.httpRequest",
      "position": [1120, 200]
    },
    {
      "parameters": {
        "url": "https://crm.memudecore.com.br/api/v1/leads?created_after=activities",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "krayinApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{$credentials.krayinApi.token}}"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "Responder WhatsApp - {{$now.minus(1,json.name}}"
            'day'},
            {
              "name": "type",
              "value": "call"
            },
            {
              "name": "comment",
              "value": "Retornar contato via WhatsApp: {{$json.phone}}"
            },
            {
              "name": "schedule_from",
              "value": "{{DateTime.now().plus({hours: 2}).toISO() }}"
            },
            {
              "name": "schedule_to",
              "value": "{{DateTime.now().plus({hours: 2, minutes: 30}).toISO()}}"
            },
            {
              "name": "lead_id",
              "value": "{{$('Criar Lead Krayin').first().json.data.id}}"
            },
            {
              "name": "user_id",
              "value": "1"
            }
          ]
        }
      },
      "name": "Agendar Follow-up",
      "type": "n8n-nodes-base.httpRequest",
      "position": [1120, 400]
    }
  ],
  "connections": {
    "Webhook WhatsApp": {
      "main": [
        [
          {
            "node": "Processar Mensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Processar Mensagem": {
      "main": [
        [
          {
            "node": "É Lead?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "É Lead?": {
      "main": [
        [
          {
            "node": "Criar Lead Krayin",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Criar Lead Krayin": {
      "main": [
        [
          {
            "node": "Resposta Automática",
            "type": "main",
            "index": 0
          },
          {
            "node": "Agendar Follow-up",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

4. 📊 INTEGRAÇÃO COM GOOGLE SHEETS (RELATÓRIOS)

Google Apps Script

// Google Apps Script - Sincronizar leads para Google Sheets

function syncKrayinLeads() {
  const KRAYIN_TOKEN = PropertiesService.getScriptProperties().getProperty('KRAYIN_TOKEN');
  const SHEET_ID = 'your-sheet-id-here';

  try {
    // Obter leads da API
    const response = UrlFetchApp.fetch('https://crm.memudecore.com.br/api/v1/leads?limit=100', {
      headers: {
        'Authorization': `Bearer ${KRAYIN_TOKEN}`,
        'Accept': 'application/json'
      }
    });

    const data = JSON.parse(response.getContentText());
    const leads = data.data;

    // Abrir planilha
    const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('Leads');

    // Limpar dados existentes (manter cabeçalho)
    const lastRow = sheet.getLastRow();
    if (lastRow > 1) {
      sheet.deleteRows(2, lastRow - 1);
    }

    // Node:Cabeçalhos Google(se Sheetsnão -existirem)
    Appendif rows(sheet.getLastRow() === 0) {
      sheet.appendRow([
        'ID', 'Título', 'Valor', 'Status', 'Contato', 'Email',
        'Telefone', 'Empresa', 'Criado em', 'Atualizado em'
      ]);
    }

    // MapearAdicionar camposdados dos leads
    leads.forEach(lead => {
      const pessoa = lead.person || {};
      const email = pessoa.emails?.[0]?.value || '';
      const telefone = pessoa.contact_numbers?.[0]?.value || '';
      const empresa = pessoa.organization?.name || '';

      sheet.appendRow([
        lead.id,
        lead.title,
        `R$ ${lead.lead_value}`,
        lead.stage?.name || 'Novo',
        pessoa.name || '',
        email,
        telefone,
        empresa,
        new Date(lead.created_at),
        new Date(lead.updated_at)
      ]);
    });

    // Formatar dados
    formatSheet(sheet);

    // Log sucesso
    console.log(`✅ ${leads.length} leads sincronizados`);

    // Enviar relatório por email
    sendEmailReport(leads.length);

  } catch (error) {
    console.error('❌ Erro na sincronização:', error);

    // Notificar erro
    MailApp.sendEmail({
      to: 'admin@empresa.com',
      subject: '❌ Erro na sincronização Krayin-Sheets',
      body: `Erro: ${error.message}\n\nTimestamp: ${new Date()}`
    });
  }
}

function formatSheet(sheet) {
  const range = sheet.getDataRange();

  // Congelar cabeçalho
  sheet.setFrozenRows(1);

  // Formatar cabeçalho
  const headerRange = sheet.getRange(1, 1, 1, sheet.getLastColumn());
  headerRange.setBackground('#4285F4');
  headerRange.setFontColor('#FFFFFF');
  headerRange.setFontWeight('bold');

  // Auto-resize colunas
  for (let i = 1; i <= sheet.getLastColumn(); i++) {
    sheet.autoResizeColumn(i);
  }

  // Adicionar filtros
  range.createFilter();

  // Formatar datas
  const createdAtCol = 9; // Coluna "Criado em"
  const updatedAtCol = 10; // Coluna "Atualizado em"

  if (sheet.getLastRow() > 1) {
    sheet.getRange(2, createdAtCol, sheet.getLastRow() - 1, 1)
         .setNumberFormat('dd/mm/yyyy hh:mm');
    sheet.getRange(2, updatedAtCol, sheet.getLastRow() - 1, 1)
         .setNumberFormat('dd/mm/yyyy hh:mm');
  }
}

function sendEmailReport(totalLeads) {
  const recipients = ['gestor@empresa.com', 'vendas@empresa.com'];

  const emailBody = `
    📊 Relatório de Sincronização - Krayin CRM

    ✅ Total de leads sincronizados: ${totalLeads}
    📅 Data/Hora: ${new Date().toLocaleString('pt-BR')}
    🔗 Link da planilha: ${SpreadsheetApp.getActiveSpreadsheet().getUrl()}

    ---
    Dados atualizados automaticamente a cada 1 hora.
  `;

  recipients.forEach(email => {
    MailApp.sendEmail({
      to: email,
      subject: '📊 Relatório Leads - Krayin CRM',
      body: emailBody
    });
  });
}

// Configurar trigger automático
function setupTrigger() {
  // Deletar triggers existentes
  ScriptApp.getProjectTriggers().forEach(trigger => {
    if (trigger.getHandlerFunction() === 'syncKrayinLeads') {
      ScriptApp.deleteTrigger(trigger);
    }
  });

  // Criar novo trigger (executar a cada 1 hora)
  ScriptApp.newTrigger('syncKrayinLeads')
    .timeBased()
    .everyHours(1)
    .create();

  console.log('✅ Trigger configurado para executar a cada 1 hora');
}

// Dashboard função - Criar gráficos
function createDashboard() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  let dashSheet = ss.getSheetByName('Dashboard');

  // Criar sheet se não existir
  if (!dashSheet) {
    dashSheet = ss.insertSheet('Dashboard');
  }

  const leadsSheet = ss.getSheetByName('Leads');
  const data = leadsSheet.getDataRange().getValues();

  // Gráfico: Leads por mês
  const chart = dashSheet.newChart()
    .setChartType(Charts.ChartType.COLUMN)
    .addRange(leadsSheet.getRange('A:A')) // IDs
    .addRange(leadsSheet.getRange('I:I')) // Datas criação
    .setPosition(2, 2, 0, 0)
    .setOption('title', 'Leads por Mês')
    .setOption('hAxis.title', 'Mês')
    .setOption('vAxis.title', 'Quantidade')
    .build();

  dashSheet.insertChart(chart);

  // Adicionar métricas
  dashSheet.getRange('A1').setValue('📊 DASHBOARD LEADS');
  dashSheet.getRange('A3').setValue('Total de Leads:');
  dashSheet.getRange('B3').setFormula('=COUNTA(Leads!A:A)-1');

  dashSheet.getRange('A4').setValue('Valor Total:');
  dashSheet.getRange('B4').setFormula('=SUMPRODUCT(VALUE(SUBSTITUTE(SUBSTITUTE(Leads!C:C,"R$ ",""),".","")))/100');

  dashSheet.getRange('A5').setValue('Ticket Médio:');
  dashSheet.getRange('B5').setFormula('=B4/B3');
}

5. 🤖 CHATBOT INTEGRATION (DIALOGFLOW + KRAYIN)

Webhook Node.js para Dialogflow

// webhook-chatbot.js
const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());

// Configuração Krayin
const krayin = axios.create({
  baseURL: 'https://crm.memudecore.com.br/api/v1',
  headers: {
    'Authorization': `Bearer ${process.env.KRAYIN_TOKEN}`,
    'Content-Type': 'application/json'
  }
});

// Webhook para Dialogflow
app.post('/webhook', async (req, res) => {
  const { queryResult, session } = req.body;
  const { intent, parameters, queryText } = queryResult;

  let response = { fulfillmentText: 'Desculpe, não entendi.' };

  try {
    switch (intent.displayName) {
      case 'solicitar.orcamento':
        response = await handleOrcamentoRequest(parameters, session);
        break;

      case 'agendar.demonstracao':
        response = await handleAgendarDemo(parameters, session);
        break;

      case 'informacoes.produto':
        response = await handleInfoProduto(parameters);
        break;

      case 'suporte.tecnico':
        response = await handleSuporteTecnico(parameters, queryText);
        break;
    }
  } catch (error) {
    console.error('Erro no webhook:', error);
    response = {
      fulfillmentText: 'Estou com dificuldades no momento. Pode tentar novamente?'
    };
  }

  res.json(response);
});

async function handleOrcamentoRequest(params, session) {
  const { nome, email, telefone, empresa, produto } = params;

  // Criar lead no Krayin
  const leadData = {
    title: `Solicitação de Orçamento - ${produto || 'Produto'}`,
    description: `Solicitado via chatbot\nProduto interesse: ${produto}`,
    lead_value: getEstimatedValue(produto),
    lead_source_id: 4, // Chatbot
    person: {
      name: nome,
      emails: email ? [{ value: email, label: 'work' }] : [],
      contact_numbers: telefone ? [{ value: telefone, label: 'mobile' }] : [],
      organization: empresa ? { name: empresa } : null
    }
  };

  const leadResponse = await krayin.post('/leads', leadData);
  const leadId = leadResponse.data.data.id;

  // Agendar follow-up
  await scheduleFollowUp(leadId, 'Orçamento solicitado via chatbot');

  return {
    fulfillmentText: `Perfeito, ${nome}! 🎯\n\nSeu orçamento foi registrado no sistema (#${leadId}).\nNossa equipe entrará em contato em até 2 horas úteis.\n\nGostaria de agendar uma demonstração também?`,
    followupEventInput: {
      name: 'orcamento_criado',
      parameters: { leadId }
    }
  };
}

async function handleAgendarDemo(params, session) {
  const { nome, email, data_preferida, horario } = params;

  // Criar lead
  const leadData = {
    title: `Demo Agendada - ${nome}`,
    description: `Demonstração solicitada via chatbot\nData preferida: ${data_preferida}\nHorário: ${horario}`,
    lead_value: 5000, // Valor estimado para demos
    person: {
      name: nome,
      emails: [{ value: email, label: 'work' }]
    }
  };

  const leadResponse = await krayin.post('/leads', leadData);
  const leadId = leadResponse.data.data.id;

  // Criar atividade de demo
  const demoDate = parsePreferredDate(data_preferida, horario);

  const atividade = {
    title: `Demonstração - ${nome}`,
    type: 'meeting',
    comment: `Demo agendada via chatbot\nEmail: ${email}`,
    schedule_from: demoDate.toISOString(),
    schedule_to: new Date(demoDate.getTime() + 60*60*1000).toISOString(), // +1h
    lead_id: leadId,
    user_id: 1
  };

  await krayin.post('/activities', atividade);

  return {
    fulfillmentText: `Ótimo, ${nome}! 📅\n\nSua demonstração foi agendada:\n📍 ${data_preferida} às ${horario}\n\nVocê receberá um email de confirmação em breve.\nO link da reunião será enviado 1 dia antes.`
  };
}

async function handleInfoProduto(params) {
  const { produto } = params;

  // Base de conhecimento de produtos
  const produtos = {
    'crm': {
      descricao: '🎯 Nosso CRM completo para gestão de leads e vendas',
      preco: 'A partir de R$ 99/mês',
      features: ['Gestão de Leads', 'Pipeline de Vendas', 'Relatórios', 'Integração WhatsApp']
    },
    'automacao': {
      descricao: '🤖 Plataforma de automação de marketing e vendas',
      preco: 'A partir de R$ 199/mês',
      features: ['Email Marketing', 'Workflows', 'Lead Scoring', 'Integrações']
    }
  };

  const info = produtos[produto.toLowerCase()] || produtos['crm'];

  return {
    fulfillmentText: `${info.descricao}\n\n💰 ${info.preco}\n\n✨ Principais recursos:\n${info.features.map(f => `• ${f}`).join('\n')}\n\nGostaria de agendar uma demonstração?`,
    followupEventInput: {
      name: 'produto_consultado',
      parameters: { produto }
    }
  };
}

async function handleSuporteTecnico(params, queryText) {
  const { problema, urgencia } = params;

  // Criar ticket de suporte (como lead especial)
  const ticketData = {
    title: `Suporte: ${problema || 'Problema técnico'}`,
    description: `Questão técnica via chatbot: ${queryText}\nUrgência: ${urgencia || 'normal'}`,
    lead_type_id: 2, // Tipo "Suporte"
    lead_source_id: 4, // Chatbot
    person: {
      name: 'Cliente Chatbot',
      emails: []
    }
  };

  const ticketResponse = await krayin.post('/leads', ticketData);
  const ticketId = ticketResponse.data.data.id;

  const urgencyLevel = urgencia === 'alta' ? 'em até 30 minutos' : 'em até 2 horas';

  return {
    fulfillmentText: `Entendi seu problema técnico! 🔧\n\nTicket criado: #${ticketId}\nPrioridade: ${urgencia || 'Normal'}\n\nNossa equipe técnica retornará ${urgencyLevel}.\n\nEnquanto isso, já tentou reiniciar o sistema?`
  };
}

function getEstimatedValue(produto) {
  const valores = {
    'crm': 3000,
    'automacao': 5000,
    'integracao': 8000,
    'consultoria': 15000
  };

  return valores[produto?.toLowerCase()] || 2000;
}

function parsePreferredDate(dataStr, horario) {
  // Lógica para converter "amanhã", "próxima semana", etc.
  const hoje = new Date();
  const amanha = new Date(hoje.getTime() + 24*60*60*1000);

  // Simplificado - em produção usar biblioteca como moment.js
  return amanha;
}

async function scheduleFollowUp(leadId, comment) {
  const followUpDate = new Date(Date.now() + 2*60*60*1000); // +2h

  const atividade = {
    title: 'Follow-up ChatBot',
    type: 'call',
    comment,
    schedule_from: followUpDate.toISOString(),
    schedule_to: new Date(followUpDate.getTime() + 30*60*1000).toISOString(),
    lead_id: leadId,
    user_id: 1
  };

  return krayin.post('/activities', atividade);
}

app.listen(process.env.PORT || 3000, () => {
  console.log('🤖 Webhook chatbot rodando');
});

module.exports = app;

6. 📧 INTEGRAÇÃO COM EMAIL MARKETING (MAILCHIMP)

Sincronização Bidirecional

# mailchimp_sync.py
import requests
import mailchimp_marketing as MailchimpMarketing
from datetime import datetime, timedelta

class MailchimpKrayinSync:
    def __init__(self, krayin_token, mailchimp_key, audience_id):
        # Krayin API
        self.krayin = requests.Session()
        self.krayin.headers.update({
            'Authorization': f'Bearer {krayin_token}',
            'Content-Type': 'application/json'
        })
        self.krayin_base = 'https://crm.memudecore.com.br/api/v1'

        # Mailchimp API
        self.mailchimp = MailchimpMarketing.Client()
        self.mailchimp.set_config({
            'api_key': mailchimp_key,
            'server': mailchimp_key.split('-')[-1]
        })
        self.audience_id = audience_id

    def sync_leads_to_mailchimp(self):
        """Sincronizar leads do leadKrayin para colunasMailchimp"""
        print("🔄 Sincronizando leads Krayin → Mailchimp...")

        # Obter leads recentes do Krayin
        since = (datetime.now() - timedelta(days=1)).isoformat()
        response = self.krayin.get(f'{self.krayin_base}/leads', params={
            'created_at_from': since,
            'limit': 100
        })

        leads = response.json().get('data', [])
        synced = 0

        for lead in leads:
            pessoa = lead.get('person', {})
            email = self.get_primary_email(pessoa)

            if not email:
                continue

            try:
                # Preparar dados para Mailchimp
                member_data = {
                    'email_address': email,
                    'status': 'subscribed',
                    'merge_fields': {
                        'FNAME': pessoa.get('name', '').split()[0] if pessoa.get('name') else '',
                        'LNAME': ' '.join(pessoa.get('name', '').split()[1:]) if pessoa.get('name') else '',
                        'LEADID': str(lead['id']),
                        'LEADVALUE': str(lead.get('lead_value', 0)),
                        'COMPANY': pessoa.get('organization', {}).get('name', '') if pessoa.get('organization') else ''
                    },
                    'tags': [
                        'krayin-lead',
                        f"valor-{self.categorize_value(lead.get('lead_value', 0))}"
                    ]
                }

                # Adicionar ao Mailchimp
                self.mailchimp.lists.add_list_member(
                    self.audience_id,
                    member_data
                )

                synced += 1
                print(f"✅ Lead {lead['id']} → {email}")

            except Exception as e:
                if 'Member Exists' in str(e):
                    # Atualizar existente
                    self.update_mailchimp_member(email, member_data)
                else:
                    print(f"❌ Erro sincronizando {email}: {e}")

        print(f"📊 Total sincronizado: {synced} leads")
        return synced

    def sync_mailchimp_activities_to_krayin(self):
        """Sincronizar atividades do Mailchimp para Krayin"""
        print("🔄 Sincronizando atividades Mailchimp → Krayin...")

        try:
            # Obter atividades recentes
            activities = self.mailchimp.lists.get_list_recent_activity(
                self.audience_id,
                count=100
            )

            for activity in activities.get('activity', []):
                email = activity.get('email_address')
                action = activity.get('action')
                timestamp = activity.get('timestamp')

                if not email or action not in ['open', 'click', 'bounce']:
                    continue

                # Buscar lead correspondente no Krayin
                lead_id = self.find_lead_by_email(email)
                if not lead_id:
                    continue

                # Criar atividade no Krayin
                self.create_krayin_activity(lead_id, action, email, timestamp)

        except Exception as e:
            print(f"❌ Erro sincronizando atividades: {e}")

    def find_lead_by_email(self, email):
        """Encontrar lead no Krayin por email"""
        try:
            # Buscar por email (simplificado - em produção usar endpoint de busca)
            response = self.krayin.get(f'{self.krayin_base}/leads', params={
                'limit': 100
            })

            leads = response.json().get('data', [])

            for lead in leads:
                pessoa = lead.get('person', {})
                lead_email = self.get_primary_email(pessoa)

                if lead_email and lead_email.lower() == email.lower():
                    return lead['id']

        except Exception as e:
            print(f"❌ Erro buscando lead por email {email}: {e}")

        return None

    def create_krayin_activity(self, lead_id, action, email, timestamp):
        """Criar atividade no Krayin baseada em ação do Mailchimp"""
        action_map = {
            'open': {
                'title': f'Email aberto - {email}',
                'type': 'email',
                'comment': 'Cliente abriu email da planilhacampanha'
            },
            'click': {
                'title': f'Link clicado - {email}',
                'type': 'email',
                'comment': 'Cliente clicou em link do email'
            },
            'bounce': {
                'title': f'Email retornado - {email}',
                'type': 'email',
                'comment': 'Email retornou - verificar endereço'
            }
        }

        if action not in action_map:
            return

        activity_data = {
            **action_map[action],
            'lead_id': lead_id,
            'user_id': 1,
            'schedule_from': timestamp,
            'schedule_to': timestamp,
            'is_done': True
        }

        try:
            self.krayin.post(f'{self.krayin_base}/activities', json=activity_data)
            print(f"📧 Atividade '{action}' criada para lead {lead_id}")
        except Exception as e:
            print(f"❌ Erro criando atividade: {e}")

    def get_primary_email(self, pessoa):
        """Obter email principal da pessoa"""
        emails = pessoa.get('emails', [])
        return emails[0]['value'] if emails else None

    def categorize_value(self, value):
        """Categorizar valor do lead"""
        if value >= 10000:
            return 'alto'
        elif value >= 5000:
            return 'medio'
        else:
            return 'baixo'

    def update_mailchimp_member(self, email, data):
        """Atualizar membro existente no Mailchimp"""
        try:
            import hashlib
            subscriber_hash = hashlib.md5(email.lower().encode()).hexdigest()

            self.mailchimp.lists.update_list_member(
                self.audience_id,
                subscriber_hash,
                data
            )
            print(f"🔄 Atualizado: {email}")
        except Exception as e:
            print(f"❌ Erro atualizando {email}: {e}")

    def run_full_sync(self):
        """Executar sincronização completa"""
        print("🚀 Iniciando sincronização completa...")

        leads_synced = self.sync_leads_to_mailchimp()
        self.sync_mailchimp_activities_to_krayin()

        print(f"✅ Sincronização concluída! {leads_synced} leads processados")

# Uso do script
if __name__ == "__main__":
    import os

    sync = MailchimpKrayinSync(
        krayin_token=os.getenv('KRAYIN_TOKEN'),
        mailchimp_key=os.getenv('MAILCHIMP_API_KEY'),
        audience_id=os.getenv('MAILCHIMP_AUDIENCE_ID')
    )

    sync.run_full_sync()

2.🎯 WhatsAppSCRIPT (EvolutionDE API)TESTE COMPLETO

ArquiteturaTeste de Todas as Funcionalidades

┌─────────────┐#!/bin/bash
Mensagem# ┌─────────────┐test_krayin_api.sh Webhook- ┌─────────────┐Script completo WhatsAppde testes

───────────────►# Configurações
EvolutionAPI_BASE="https://crm.memudecore.com.br/api/v1"
EMAIL="admin@example.com"
───────────────►PASSWORD="admin123"

# N8NCores para output
(User)RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

echo "🚀 Testando API │                  │             │
└─────────────┘                  └─────────────┘                  └──────┬──────┘
                                                                         │
                                                                         │ API
                                                                         ▼
                                                                  ┌─────────────┐
                                                                  │   Krayin CRM..."

# CRM1. Fazer └─────────────┘login 
e

Configurarobter Evolutiontoken API

echo

Passo"📝 1:1. CriarFazendo Instâncialogin..." WhatsApp

LOGIN_RESPONSE=$(curl
curl-s -X POST "https:${API_BASE}/login" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Accept: application/json" \
  -d "email=${EMAIL}&password=${PASSWORD}&device_name=TestScript")

TOKEN=$(echo $LOGIN_RESPONSE | jq -r '.token')

if [ "$TOKEN" = "null" ] || [ -z "$TOKEN" ]; then
    echo -e "${RED}❌ Falha no login${NC}"
    echo $LOGIN_RESPONSE
    exit 1
fi

echo -e "${GREEN}✅ Login realizado com sucesso${NC}"
echo "Token: ${TOKEN:0:20}..."

# 2. Testar listagem de leads
echo -e "\n📋 2. Testando listagem de leads..."
LEADS_RESPONSE=$(curl -s -X GET "${API_BASE}/evolution.memudecore.com.br/instance/create"leads" \
  -H "Authorization: Bearer SUA_API_KEY"${TOKEN}" \
  -H "Accept: application/json")

LEADS_COUNT=$(echo $LEADS_RESPONSE | jq '.data | length')
echo -e "${GREEN}✅ ${LEADS_COUNT} leads encontrados${NC}"

# 3. Criar lead de teste
echo -e "\n🎯 3. Criando lead de teste..."
CREATE_RESPONSE=$(curl -s -X POST "${API_BASE}/leads" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "instanceName"title": "krayin-whatsapp"Lead de Teste - Script",
    "qrcode": true,
    "integration"description": "WHATSAPP-BAILEYS"Lead criado automaticamente para teste",
    "lead_value": 1500,
    "lead_source_id": 1,
    "lead_type_id": 1,
    "person": {
      "name": "João Teste",
      "emails": [
        {"value": "joao.teste@exemplo.com", "label": "work"}
      ],
      "contact_numbers": [
        {"value": "+5511999999999", "label": "mobile"}
      ]
    }
  }')

LEAD_ID=$(echo

Passo$CREATE_RESPONSE 2:| Configurarjq Webhook

-r
'.data.id')

if [ "$LEAD_ID" = "null" ]; then
    echo -e "${RED}❌ Falha ao criar lead${NC}"
    echo $CREATE_RESPONSE
else
    echo -e "${GREEN}✅ Lead criado: ID ${LEAD_ID}${NC}"
fi

# 4. Criar atividade para o lead
echo -e "\n📅 4. Criando atividade de follow-up..."
ACTIVITY_RESPONSE=$(curl -s -X POST "https:${API_BASE}//evolution.memudecore.com.br/webhook/set/krayin-whatsapp"activities" \
  -H "Authorization: Bearer SUA_API_KEY"${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"title\": \"Follow-up Lead Teste\",
    \"type\": \"call\",
    \"comment\": \"Entrar em contato sobre proposta\",
    \"schedule_from\": \"$(date -d '+1 day' -Iseconds)\",
    \"schedule_to\": \"$(date -d '+1 day +30 minutes' -Iseconds)\",
    \"lead_id\": ${LEAD_ID},
    \"user_id\": 1
  }")

ACTIVITY_ID=$(echo $ACTIVITY_RESPONSE | jq -r '.data.id')

if [ "$ACTIVITY_ID" = "null" ]; then
    echo -e "${YELLOW}⚠️ Falha ao criar atividade${NC}"
    echo $ACTIVITY_RESPONSE
else
    echo -e "${GREEN}✅ Atividade criada: ID ${ACTIVITY_ID}${NC}"
fi

# 5. Testar atualização do lead
echo -e "\n🔄 5. Atualizando lead..."
UPDATE_RESPONSE=$(curl -s -X PUT "${API_BASE}/leads/${LEAD_ID}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook": {
      "enabled": true,
      "url"description": "https://n8n.memudecore.com.br/webhook/whatsapp-krayin"Lead atualizado pelo script de teste",
    "events"lead_value": 2500
  }')

UPDATE_SUCCESS=$(echo $UPDATE_RESPONSE | jq -r '.data.id')

if [ "MESSAGES_UPSERT",$UPDATE_SUCCESS" = "CONNECTION_UPDATE"null" ]; }then
    }'echo 
-e

Workflow"${YELLOW}⚠️ N8N:Falha WhatsAppao atualizar lead${NC}" else echo -e "${GREEN}✅ Lead

Payloadatualizado com sucesso${NC}" fi # 6. Obter detalhes do Evolutionlead API

echo
{-e "event":\n🔍 "MESSAGES_UPSERT",6. "data":Obtendo {detalhes "key":do {
      "remoteJid": "5511987654321@s.whatsapp.net",
      "fromMe": false,
      "id": "ABC123"
    },
    "message": {
      "conversation": "Olá, tenho interesse no produto X"
    },
    "pushName": "João Silva"
  }
}

Node: Code (Extrair Dados)

const jid = $json.data.key.remoteJid;
const phone = '+' + jid.split('@')[0];
const name = $json.data.pushName || 'WhatsApp Contact';
const message = $json.data.message.conversation ||
                $json.data.message.extendedTextMessage?lead..text ||
                '[Mídia]';

return {
  phone: phone,
  name: name,
  message: message,
  source: 'whatsapp',
  jid: jid
};

Node: HTTP Request (Buscar Contato Existente)

{
  "method": "GET",
  "url": "https://crm.memudecore.com.br/api/v1/contacts/persons",
  "qs": {
    "search": "={{ $json.phone }}."
}
}

Node: IF DETAIL_RESPONSE=$(Contato Existe?)

Condition: {{ $json.data.length > 0 }}
True → Usar ID existente
False → Criar novo contato

Node: HTTP Request (Criar Lead)

{
  "method": "POST",
  "url": "https://crm.memudecore.com.br/api/v1/leads",
  "body": {
    "title": "WhatsAppcurl - {{ $('Code').item.json.name }}",
    "source_id": 5,
    "lead_type_id": 1,
    "sales_owner_id": 1,
    "contact_person_id": "{{ $json.person_id }}",
    "description": "Mensagem: {{ $('Code').item.json.message }}",
    "tags": ["whatsapp"]
  }
}

Enviar Resposta pelo WhatsApp

# Via Evolution API
curls -X POSTGET "https:${API_BASE}//evolution.memudecore.com.br/message/sendText/krayin-whatsapp"leads/${LEAD_ID}" \
  -H "Authorization: Bearer SUA_API_KEY"${TOKEN}" \
  -H "Content-Type:Accept: application/json")

LEAD_TITLE=$(echo $DETAIL_RESPONSE | jq -r '.data.title')
LEAD_VALUE=$(echo $DETAIL_RESPONSE | jq -r '.data.lead_value')

echo -e "${GREEN}✅ Detalhes obtidos:${NC}"
echo "   Título: $LEAD_TITLE"
echo "   Valor: R$ $LEAD_VALUE"

# 7. Testar endpoints de contatos
echo -e "\n👥 7. Testando endpoints de contatos..."
PERSONS_RESPONSE=$(curl -s -X GET "${API_BASE}/contacts/persons" \
  -dH "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/json")

PERSONS_COUNT=$(echo $PERSONS_RESPONSE | jq '{.data | length')
echo -e "number":${GREEN}✅ ${PERSONS_COUNT} pessoas encontradas${NC}"

# 8. Limpar dados de teste
echo -e "5511987654321",\n🗑️ 8. Limpando dados de teste..."
DELETE_RESPONSE=$(curl -s -X DELETE "text":${API_BASE}/leads/${LEAD_ID}" \
  -H "Olá!Authorization: RecebemosBearer sua${TOKEN}")

mensagem.if Em[ breve$? um-eq consultor0 entrará]; emthen
    contato.echo -e "${GREEN}✅ Lead de teste removido${NC}"
}'else
    echo -e "${YELLOW}⚠️ Falha ao remover lead de teste (ID: ${LEAD_ID})${NC}"
fi

# Resumo final
echo -e "\n📊 RESUMO DOS TESTES:"
echo -e "${GREEN}✅ Login e autenticação${NC}"
echo -e "${GREEN}✅ Listagem de leads${NC}"
echo -e "${GREEN}✅ Criação de lead${NC}"
echo -e "${GREEN}✅ Criação de atividade${NC}"
echo -e "${GREEN}✅ Atualização de dados${NC}"
echo -e "${GREEN}✅ Consulta de detalhes${NC}"
echo -e "${GREEN}✅ Endpoints de contatos${NC}"
echo -e "${GREEN}✅ Limpeza de dados${NC}"

echo -e "\n🎉 ${GREEN}Todos os testes concluídos com sucesso!${NC}"
echo "A API Krayin está funcionando corretamente e pronta para integração."

3.📋 FrontendCHECKLIST OperaesDE (TypeScript)IMPLEMENTAÇÃO

ConfiguraçAntes de Começar

  •  Obter credenciais de acesso ao Krayin
  •  Configurar ambiente de desenvolvimento
  •  Instalar dependências necessárias
  •  Testar conectividade com a API

Durante a Implementação

  •  Implementar autenticação dosegura
  • Cliente
  • APIAdicionar

    api/krayin.ts

    tratamento
    import axios, { AxiosInstance, AxiosError } from 'axios';
    
    interface KrayinConfig {
      baseURL: string;
      token?: string;
    }
    
    interface LoginResponse {
      token: string;
      message: string;
    }
    
    interface Lead {
      id: number;
      title: string;
      source_id: number;
      lead_type_id: number;
      sales_owner_id: number;
      status_id: number;
      value: number;
      expected_close_date?: string;
      description?: string;
      contact_person?: Person;
      organization?: Organization;
      created_at: string;
      updated_at: string;
    }
    
    interface Person {
      id: number;
      name: string;
      emails: Array<{ value: string; label: string }>;
      contact_numbers: Array<{ value: string; label: string }>;
    }
    
    interface Organization {
      id: number;
      name: string;
    }
    
    interface PaginatedResponse<T> {
      data: T[];
      links: {
        first: string;
        last: string;
        prev: string | null;
        next: string | null;
      };
      meta: {
        current_page: number;
        from: number;
        last_page: number;
        per_page: number;
        to: number;
        total: number;
      };
    }
    
    class KrayinAPI {
      private client: AxiosInstance;
      private token: string | null = null;
    
      constructor(config: KrayinConfig) {
        this.client = axios.create({
          baseURL: config.baseURL,
          headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
          },
        });
    
        if (config.token) {
          this.setToken(config.token);
        }
    
        // Interceptor parade erros this.client.interceptors.response.use(robusto
  • response
  • =>Configurar response,logs (error:detalhados
  • AxiosError)
  • =>Implementar {cache ifquando (error.response?.statusnecessário
  • ===
  • 401)Adicionar {testes //automatizados
  • Token expirado - redirecionar para login this.token = null; window.location.href = '/login'; } return Promise.reject(error); } ); } setToken(token: string) { this.token = token; this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`; } // ==================== AUTH ==================== async login(email: string, password: string): Promise<string> { const params = new URLSearchParams(); params.append('email', email); params.append('password', password); params.append('device_name', 'Operaes'); const response = await this.client.post<LoginResponse>('/login', params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); this.setToken(response.data.token); return response.data.token; } // ==================== LEADS ==================== async getLeads(params?: { page?: number; per_page?: number; search?: string; source_id?: number; status_id?: number; sales_owner_id?: number; }): Promise<PaginatedResponse<Lead>> { const response = await this.client.get<PaginatedResponse<Lead>>('/leads', { params }); return response.data; } async getLead(id: number): Promise<Lead> { const response = await this.client.get<{ data: Lead }>(`/leads/${id}`); return response.data.data; } async createLead(data: Partial<Lead>): Promise<Lead> { const response = await this.client.post<{ data: Lead }>('/leads', data); return response.data.data; } async updateLead(id: number, data: Partial<Lead>): Promise<Lead> { const response = await this.client.put<{ data: Lead }>(`/leads/${id}`, data); return response.data.data; } async deleteLead(id: number): Promise<void> { await this.client.delete(`/leads/${id}`); } async convertLead(id: number): Promise<void> { await this.client.post(`/leads/${id}/convert`); } // ==================== CONTACTS ==================== async getPersons(params?: { page?: number; search?: string; }): Promise<PaginatedResponse<Person>> { const response = await this.client.get<PaginatedResponse<Person>>('/contacts/persons', { params }); return response.data; } async createPerson(data: Partial<Person>): Promise<Person> { const response = await this.client.post<{ data: Person }>('/contacts/persons', data); return response.data.data; } // ==================== ACTIVITIES ==================== async getActivities(leadId: number): Promise<any[]> { const response = await this.client.get('/activities', { params: { lead_id: leadId } }); return response.data.data; } async createActivity(data: { type: 'call' | 'meeting' | 'lunch' | 'email' | 'note'; title: string; lead_id: number; description?: string; scheduled_from?: string; scheduled_to?: string; }): Promise<any> { const response = await this.client.post('/activities', data); return response.data.data; } } // Singleton export const krayinAPI = new KrayinAPI({ baseURL: 'https://crm.memudecore.com.br/api/v1', }); export default krayinAPI;

Hook ReactApós para LeadsImplementação

hooks/useLeads.ts

    import
  • {Testar useState,todos useEffect,os useCallbackfluxos }principais
  • from
  • 'react';Configurar importmonitoramento
  • krayinAPI
  • fromDocumentar '../api/krayin';integração
  • interface
  • UseLeadsOptionsTreinar {equipe
  • page?:
  • number;Planejar perPage?:manutenção
  • number; search?: string; } export function useLeads(options: UseLeadsOptions = {}) { const [leads, setLeads] = useState<any[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null); const [pagination, setPagination] = useState({ currentPage: 1, lastPage: 1, total: 0, }); const fetchLeads = useCallback(async () => { try { setLoading(true); const response = await krayinAPI.getLeads({ page: options.page || 1, per_page: options.perPage || 15, search: options.search, }); setLeads(response.data); setPagination({ currentPage: response.meta.current_page, lastPage: response.meta.last_page, total: response.meta.total, }); } catch (err) { setError(err as Error); } finally { setLoading(false); } }, [options.page, options.perPage, options.search]); useEffect(() => { fetchLeads(); }, [fetchLeads]); const createLead = async (data: any) => { const lead = await krayinAPI.createLead(data); setLeads(prev => [lead, ...prev]); return lead; }; const updateLead = async (id: number, data: any) => { const lead = await krayinAPI.updateLead(id, data); setLeads(prev => prev.map(l => l.id === id ? lead : l)); return lead; }; const deleteLead = async (id: number) => { await krayinAPI.deleteLead(id); setLeads(prev => prev.filter(l => l.id !== id)); }; return { leads, loading, error, pagination, refetch: fetchLeads, createLead, updateLead, deleteLead, }; }

    Componente de Lista de Leads

    components/LeadsList.tsx

    import React, { useState } from 'react';
    import { useLeads } from '../hooks/useLeads';
    
    export function LeadsList() {
      const [page, setPage] = useState(1);
      const [search, setSearch] = useState('');
    
      const { leads, loading, pagination, refetch } = useLeads({
        page,
        perPage: 10,
        search,
      });
    
      if (loading) return <div>Carregando...</div>;
    
      return (
        <div className="leads-list">
          <input
            type="text"
            placeholder="Buscar leads..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
    
          <table>
            <thead>
              <tr>
                <th>Título</th>
                <th>Valor</th>
                <th>Vendedor</th>
                <th>Status</th>
                <th>Ações</th>
              </tr>
            </thead>
            <tbody>
              {leads.map(lead => (
                <tr key={lead.id}>
                  <td>{lead.title}</td>
                  <td>R$ {lead.value?.toLocaleString('pt-BR')}</td>
                  <td>{lead.sales_owner?.name}</td>
                  <td>{lead.status?.name}</td>
                  <td>
                    <button onClick={() => window.location.href = `/leads/${lead.id}`}>
                      Ver
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
    
          <div className="pagination">
            <button
              disabled={page === 1}
              onClick={() => setPage(p => p - 1)}
            >
              Anterior
            </button>
            <span>Página {pagination.currentPage} de {pagination.lastPage}</span>
            <button
              disabled={page === pagination.lastPage}
              onClick={() => setPage(p => p + 1)}
            >
              Próxima
            </button>
          </div>
        </div>
      );
    }
    

4.🎯 OutrasCONCLUSÃO

Integraç

Este guia fornece soluções

Googleprontas Calendar

para

Oos Krayincenários temmais comuns de integração nativa com Googlea Calendar:API Krayin CRM. Cada exemplo pode ser adaptado às necessidades específicas do seu negócio.

#

Para .envsuporte GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=xxxxx GOOGLE_REDIRECT_URI=https://crm.memudecore.com.br/google/oauth GOOGLE_WEBHOOK_URI=https://crm.memudecore.com.br/google/webhook

IMAP Email

Configuração em: Settings → Email Configurationadicional:

WebForms

Criar formulários de captura em: Settings → WebForms


📚 Recursos Adicionais

  • 📖 N8NConsulte Docs:a https://docs.n8n.iodocumentação técnica completa
  • 🔧 EvolutionUse API:os https://doc.evolution-api.comscripts de teste para validar implementações
  • 📊 KrayinMonitore APImétricas Docs:para https://crm.memudecore.com.br/api/admin/documentationotimização contínua

ÚltimaExemplos atualização:atualizados - Janeiro 2026 API Krayin CRM v2.1.1