# 💼 Casos de Uso e Exemplos Práticos
API Krayin CRM - Soluções Prontas
GuiaScriptsdee implementações prontas para usar Copy-paste friendly para agilizar integraçãocom N8N, WhatsApp (Evolution API) e Frontend Operaes.
📋🎯 Índice
CENÁRIOS 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 Inicial
da 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
Acesse N8N → Settings → Credentials
Clique Add Credential
Selecione Header Auth
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
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
- 📖
N8NConsulteDocs:ahttps://docs.n8n.iodocumentação técnica completa - 🔧
EvolutionUseAPI:oshttps://doc.evolution-api.comscripts de teste para validar implementações - 📊
KrayinMonitoreAPImétricasDocs:parahttps://crm.memudecore.com.br/api/admin/documentationotimização contínua
ÚltimaExemplos atualização:atualizados - Janeiro 2026
API Krayin CRM v2.1.1