# Ver los mensajes de WhatsApp en tu CRM

> Registra cada mensaje entrante en la ficha del cliente de tu CRM y responde desde tu sistema.

Tu equipo de ventas trabaja en un CRM (HubSpot, Pipedrive, Zoho, Kommo, uno propio…) y quiere ver ahí lo que los clientes escriben por WhatsApp. Con el webhook `message.received`, cada mensaje llega a tu servidor y lo guardas en la ficha del cliente.

```mermaid
sequenceDiagram
    participant C as Cliente
    participant E as MINDO
    participant S as Tu servidor
    participant R as Tu CRM
    C->>E: "¿Me pasan el precio del plan anual?"
    E->>S: webhook message.received
    S->>R: Busca o crea el contacto por teléfono
    S->>R: Agrega la nota con el mensaje
    Note over S,E: (opcional) responde con POST /messages
```

## 1. Crea el webhook

En **Ajustes › API y webhooks › Nuevo webhook**, pega la URL de tu servidor y marca **Mensaje recibido**. Si también quieres registrar a los contactos nuevos, marca **Contacto nuevo**. Guarda el secreto de firma. Te lo explicamos paso a paso en [Webhooks](/api/webhooks/introduccion).

## 2. Recibe y registra los mensajes

```javascript server.js
import express from "express"
import crypto from "node:crypto"

const app = express()
const SECRET = process.env.MINDO_WEBHOOK_SECRET
const procesados = new Set() // en producción, usa tu base de datos

app.post("/webhooks/mindo", express.raw({ type: "application/json" }), async (req, res) => {
  const raw = req.body.toString("utf8")
  if (!firmaValida(raw, req.get("x-mindo-signature") ?? "")) return res.sendStatus(401)
  res.sendStatus(200)

  const evento = JSON.parse(raw)
  if (evento.test || procesados.has(evento.id)) return
  procesados.add(evento.id)

  if (evento.event === "message.received") {
    const { contact, text, type, receivedAt, conversationId } = evento.data
    const cliente = await crm.buscarOCrearPorTelefono(contact.phone ?? contact.instagram, contact.name)
    await crm.agregarNota(cliente.id, {
      titulo: "Mensaje de WhatsApp",
      texto: text ?? `(${type})`,
      fecha: receivedAt,
      link: `https://app.mindo.ar/chat/${conversationId}`,
    })
  }
})

function firmaValida(raw, header) {
  const p = Object.fromEntries(header.split(",").map((x) => x.split("=")))
  if (!p.t || Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false
  const esperada = crypto.createHmac("sha256", SECRET).update(`${p.t}.${raw}`).digest("hex")
  return p.v1?.length === esperada.length && crypto.timingSafeEqual(Buffer.from(p.v1), Buffer.from(esperada))
}

app.listen(3000)
```

`crm.buscarOCrearPorTelefono` y `crm.agregarNota` representan las llamadas a la API de tu CRM.

<Tip>
  El link `https://app.mindo.ar/chat/<conversationId>` abre la conversación en MINDO. Así tu vendedor pasa del CRM al chat con un clic.
</Tip>

## 3. Responder desde tu sistema (opcional)

Como el cliente acaba de escribir, la [ventana de 24 horas](/conceptos/ventana-24-horas) está abierta y puedes mandarle texto libre:

```javascript
await fetch("https://app.mindo.ar/api/v1/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MINDO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: evento.data.contact.phone,
    phoneNumberId: evento.data.phoneNumberId, // responde desde el mismo número
    text: "¡Gracias por escribirnos! Un asesor te responde en unos minutos.",
  }),
})
```

La respuesta aparece en el chat de MINDO como enviada por quien creó la clave de API, así el resto del equipo la ve.

<Warning>
  Por la API solo puedes responder por **WhatsApp**. Los mensajes de Instagram (los que traen `channel: "instagram"`) se responden desde el chat de MINDO.
</Warning>

## Ideas para ir más lejos

- **Asignar al vendedor**: busca en tu CRM quién atiende a ese cliente y avísale por email o Slack.
- **Crear oportunidades**: si el texto menciona “precio”, “cotización” o “presupuesto”, crea una oportunidad en tu embudo.
- **Registrar lecturas**: con [`message.status`](/api/webhooks/eventos#message-status) marcas en el CRM cuándo el cliente leyó tu mensaje.
