ChateandoendiaGuías prácticas sobre chat y mensajería instantánea

Mensajería Empresarial

Cómo conectar WhatsApp Business API a una CRM de código abierto

Procedimiento técnico detallado para sincronizar WhatsApp Cloud API con una CRM open source sin costes de licencia, centralizando la comunicación de ventas en un servidor propio.

Lucas Eduardo Silva
Lucas Eduardo SilvaAnalista de Seguridad y Privacidad8 min de lectura
Imagen editorial que ilustra Cómo conectar WhatsApp Business API a una CRM de código abierto

Gestionar una cartera de clientes sin abandonar el ecosistema de mensajería que ellos usan es el Santo Grial de las ventas en 2026. Sin embargo, los costes de plataformas como HubSpot o Salesforce se disparan cuando añades el conector de WhatsApp. La alternativa es construir tu propio puente tecnológico. Como analista de seguridad, he probado esta configuración en entornos controlados para asegurar que no comprometemos la privacidad del cliente al integrarlo.

He optado por una arquitectura basada en EspoCRM (una opción robusta, ligera y totalmente gratuita bajo licencia GNU AGPLv3) y la WhatsApp Cloud API. El proceso requiere conocimientos intermedios de línea de comandos, pero te libera de pagar tarifas mensuales por el "privilegio" de leer tus propios mensajes. Este método centraliza la conversación directamente en el fichero del cliente dentro de tu CRM, algo que las soluciones empresariales a menudo limitan a sus planes más caros.

Detalle fotográfico relacionado con Cómo conectar WhatsApp Business API a una CRM de código abierto

Requisitos previos de infraestructura y seguridad

Antes de escribir una sola línea de código, tu entorno debe estar blindado. No alojes esto en un servidor compartido barato; necesitas un VPS (Virtual Private Server) con al menos 2GB de RAM y acceso root. He utilizado Ubuntu 22.04 LTS para estas pruebas, aunque Debian 12 es igualmente viable. Necesitas cuatro componentes clave:

  1. Un domin propio: Requerido para los certificados SSL/TLS. La API de WhatsApp rechaza conexiones inseguras (HTTP) hacia tus webhooks.
  2. Docker y Docker Compose: Para aislar la base de datos y la aplicación CRM.
  3. Node.js (v20 LTS): Ejecutaremos un pequeño middleware que actúa como traductor entre Meta y tu CRM.
  4. Cuenta de Meta Business: Verificada con el número de teléfono real que usarás.

La protección de estos datos es crítica. A diferencia de cuando comparas herramientas de chat corporativo como Google Chat vs. Microsoft Teams, aquí estás gestionando datos personales (PII) sujetos al RGPD. Si tu servidor se compromete, filtrarás conversaciones privadas. Asegura tu firewall con ufw, permitiendo solo tráfico en los puertos 80, 443 y 22 (SSH), y cambia el puerto SSH por defecto inmediatamente.

Despliegue de la CRM de código abierto

Empezamos levantando el CRM. EspoCRM es ideal porque su API REST es documentada y predecible. Crea un directorio en tu servidor y prepara el archivo docker-compose.yml.

version: '3'
services:
  espocrm:
    image: espocrm/espocrm
    ports:
      - "8080:80"
    environment:
      ESPOCRM_DATABASE_HOST: db
      ESPOCRM_DATABASE_USER: espocrm
      ESPOCRM_DATABASE_PASSWORD: tu_contraseña_segura_aqui
      ESPOCRM_ADMIN_USERNAME: admin
      ESPOCRM_ADMIN_PASSWORD: otra_contraseña_segura
      ESPOCRM_SITE_URL: "https://crm.tu-dominio.com"
    depends_on:
      - db
    volumes:
      - ./espocrm:/var/www/html
  db:
    image: mariadb:10.6
    environment:
      MYSQL_ROOT_PASSWORD: root_password_segura
      MYSQL_DATABASE: espocrm
      MYSQL_USER: espocrm
      MYSQL_PASSWORD: tu_contraseña_segura_aqui

Ejecuta docker-compose up -d. Si todo sale bien, accede a https://crm.tu-dominio.com y finaliza la instalación desde el navegador. Dentro del panel de administración, ve a Administración > Integraciones y activa la "API Key". Genera una clave para el usuario que actuará como sistema (por ejemplo, "WhatsApp Bot"). Copia esta clave; la necesitaremos para que el middleware pueda escribir en el CRM.

Considera la normativa vigente: ¿Cuánto tiempo debe guardar mi empresa los registros de chat por ley?. Al alojar esto tú mismo, el control de retención es total, pero también es tu responsabilidad establecer políticas de borrado automático en la base de datos para cumplir con la normativa de minimización de datos.

Configuración de la WhatsApp Cloud API

En 2026, la API Cloud ha desplazado casi totalmente a la API On-Premise para PyMEs, ya que Meta gestiona la infraestructura de conexión. Ve a developers.facebook.com.

  1. Crea una nueva aplicación seleccionando "Business".
  2. En el producto "WhatsApp", busca la configuración de API.
  3. Añade tu número de teléfono y verifica el PIN que recibirás por SMS.
  4. Una vez verificado, anota el Phone Number ID y el Access Token (Token de acceso permanente). Genera uno con permisos de whatsapp_business_messaging.

Este token es la llave maestra. No lo subas nunca a un repositorio público de GitHub.

Desarrollo del middleware en Node.js

Aquí es donde ocurre la magia técnica. La CRM no entiende el formato de webhooks de WhatsApp de forma nativa, y WhatsApp no sabe cómo autenticarse en tu CRM. Necesitamos un script puente.

Crea una carpeta whatsapp-bridge e inicializa el proyecto: npm init -y e npm install express body-parser axios.

Crea un archivo server.js. Este script escuchará las notificaciones de Meta (cuando llega un mensaje) y realizará una petición POST a la API de EspoCRM para crear una nota en el contacto correspondiente.

const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');

const app = express();
app.use(bodyParser.json());

// Configuración
const PORT = process.env.PORT || 3000;
const CRM_URL = 'https://crm.tu-dominio.com/api/v1';
const CRM_API_KEY = 'TU_API_KEY_DE_ESPOCRM';
const VERIFY_TOKEN = 'MI_TOKEN_SECRETO_DE_VERIFICACION';

// 1. Verificación del Webhook (Requerido por Meta)
app.get('/webhook', (req, res) => {
    const mode = req.query['hub.mode'];
    const token = req.query['hub.verify_token'];
    const challenge = req.query['hub.challenge'];

    if (mode && token) {
        if (mode === 'subscribe' && token === VERIFY_TOKEN) {
            console.log('Webhook verificado');
            res.status(200).send(challenge);
        } else {
            res.sendStatus(403);
        }
    }
});

// 2. Recepción de mensajes
app.post('/webhook', async (req, res) => {
    const data = req.body;

    if (data.object === 'whatsapp_business_account') {
        // Iterar sobre las entradas
        data.entry.forEach(async (entry) => {
            const changes = entry.changes[0];
            const value = changes.value;
            
            if (value.messages) {
                const phoneNumber = value.messages[0].from;
                const messageBody = value.messages[0].text.body;
                
                await syncToCRM(phoneNumber, messageBody);
            }
        });
    }
    res.sendStatus(200);
});

// Función para buscar contacto y crear nota
async function syncToCRM(phone, text) {
    try {
        // A. Buscar contacto por número de teléfono en EspoCRM
        // Nota: EspoCRM filtra por cadena, ajusta según tu formato de números
        const searchResponse = await axios.get(`${CRM_URL}/Contact`, {
            headers: { 'X-Api-Key': CRM_API_KEY },
            params: {
                where: `[{"type":"equals","attribute":"phoneNumber","value":"${phone}"}]`
            }
        });

        let contactId;

        if (searchResponse.data.list.length > 0) {
            contactId = searchResponse.data.list[0].id;
        } else {
            // B. Crear contacto si no existe
            const createResponse = await axios.post(`${CRM_URL}/Contact`, {
                phoneNumber: phone,
                lastName: `Cliente WhatsApp ${phone}`
            }, {
                headers: { 'X-Api-Key': CRM_API_KEY }
            });
            contactId = createResponse.data.id;
        }

        // C. Crear nota en el CRM
        await axios.post(`${CRM_URL}/Note`, {
            parentId: contactId,
            parentType: 'Contact',
            post: `Mensaje WhatsApp: ${text}`,
            type: 'Post'
        }, {
            headers: { 'X-Api-Key': CRM_API_KEY }
        });

        console.log(`Sincronizado para ${phone}`);

    } catch (error) {
        console.error('Error sincronizando con CRM:', error.message);
    }
}

app.listen(PORT, () => {
    console.log(`Servidor puente escuchando en puerto ${PORT}`);
});

Este código es funcional, pero básico. En un entorno de producción, deberías añadir colas (como Redis) para manejar picos de tráfico sin bloquear el servidor.

Exposición y conexión del Webhook

Sube este código a tu VPS. Puedes usar PM2 para mantener el proceso corriendo: pm2 start server.js --name whatsapp-bridge.

Ahora, debemos decirle a Meta dónde enviar los datos. En el panel de desarrolladores de WhatsApp, en la sección de Configuration del Webhook:

  1. Callback URL: https://tu-dominio.com/webhook (asegúrate de configurar Nginx o Apache como proxy inverso para redirigir el tráfico del puerto 443 al puerto 3000 donde corre Node).
  2. Verify Token: El mismo que definiste en la variable VERIFY_TOKEN en el script.
  3. Suscríbete a los campos: messages.

Si usas Nginx, tu configuración del server block debería parecerse a esto para manejar el proxy inverso y los certificados SSL (usando Certbot):

location /webhook {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

Una vez verificado, envía un mensaje de prueba desde tu teléfono personal al número de WhatsApp Business conectado. Deberías ver aparecer una nota dentro del contacto correspondiente en EspoCRM en tiempo real.

¿Qué pasa con el envío de mensajes?

El código anterior solo recibe (Pull). Para enviar desde el CRM (Push), el proceso es inverso pero más complejo de integrar en la interfaz gráfica de una CRM open source sin modificar su código fuente core.

La solución práctica que he implementado es un flujo de trabajo interno. Cuando el agente de ventas crea una nota en el CRM que comienza con un comando específico, por ejemplo ENV:Hola, este es el stock disponible, un cron job o un proceso Node.js que escucha eventos de la API de EspoCRM detecta esto, extrae el mensaje y realiza una petición POST a la API de WhatsApp:

POST https://graph.facebook.com/v19.0/YOUR_PHONE_NUMBER_ID/messages

Esto evita tener que programar un plugin complejo dentro de la CRM, manteniendo la actualización del sistema más limpia.

Gestión de la notificación y control del flujo

Uno de los mayores riesgos de esta integración es la tormenta de notificaciones. Si recibes 50 mensajes por hora, no quieres 50 correos ni 50 alertas de escritorio. Aquí es donde la filosofía de reducir notificaciones intrusivas usando estados de enfoque es vital.

Configura tu CRM para que solo notifique agregados. Ajusta el middleware para que, si el mismo cliente envía 3 mensajes en 5 minutos, los agrupe en una sola nota en el CRM antes de alertar. Esto es fácil de implementar añadiendo una lógica de "debounce" en el script Node.js antes de llamar a la API de la CRM.

Además, organizar estas conversaciones es crucial. Si el CRM permite usar hilos o threads internos, asegúrate de que cada interacción de WhatsApp se ancle al cliente principal, no que se cree un ticket aislado por cada frase. Esto mantiene el contexto de venta unificado.

El trade-off de la autonomía técnica

He construido este sistema y he ahorrado cientos de euros en licencias anuales. Sin embargo, debo ser honesto sobre el coste oculto: el mantenimiento. Si Meta cambia la estructura del JSON de sus webhooks (algo que hacen con poca frecuencia pero ocurre), tu middleware dejará de funcionar hasta que actualices el código de parsing.

No existe un soporte técnico al que llamar quejándose de que los mensajes no llegan. Eres el administrador de la base de datos, el experto en seguridad y el desarrollador. Para una empresa pequeña con una mentalidad técnica y un deseo de soberanía de datos absoluta, es la mejor ruta posible. Para una empresa que quiere algo que "simplemente funcione" sin tocar el capó, las soluciones SaaS, aunque caras, siguen siendo menos arriesgadas operacionalmente.

El futuro de la mensajería empresarial no dependerá de una sola plataforma gigante, sino de la capacidad de las empresas para tejer sus propias comunicaciones. Al tener control sobre el código que conecta WhatsApp con tu base de datos, posees la propiedad intelectual de tu proceso de ventas. Si mañana surge una nueva aplicación de moda, solo tendrás que reescribir el middleware, no migrar toda tu base de clientes.

Lee a continuación