# Evolution API — Guía Técnica de Referencia Completa

**Documento para desarrollo de WhatsApp Lite Personal · Junio 2026**

> ⚠️ **Nota:** Este documento se basa en investigación activa realizada el 17 de junio de 2026 sobre Evolution API v2.3.7 (estable) y v2.4.0-rc2 (pre-release). Algunos endpoints pueden variar. Siempre verifica contra la [documentación oficial](https://doc.evolution-api.com/).

---

## Índice de Contenidos

1. [Introducción a Evolution API](#1-introducción-a-evolution-api)
2. [Instalación y despliegue rápido](#2-instalación-y-despliegue-rápido)
3. [Autenticación y gestión de instancias](#3-autenticación-y-gestión-de-instancias)
4. [Gestión de mensajes — Envío](#4-gestión-de-mensajes--envío)
5. [Gestión de mensajes — Recepción](#5-gestión-de-mensajes--recepción)
6. [Historial de conversaciones (chats)](#6-historial-de-conversaciones-chats)
7. [Estados de mensaje (sent/delivered/read/played)](#7-estados-de-mensaje-sentdeliveredreadplayed)
8. [Contactos](#8-contactos)
9. [Estados / Stories de WhatsApp](#9-estados--stories-de-whatsapp)
10. [Grupos y comunidades](#10-grupos-y-comunidades)
11. [Webhooks y eventos en tiempo real](#11-webhooks-y-eventos-en-tiempo-real)
12. [Multimedia: carga, descarga y límites](#12-multimedia-carga-descarga-y-límites)
13. [Limitaciones, cuotas y buenas prácticas](#13-limitaciones-cuotas-y-buenas-prácticas)
14. [Apéndice A: Comparativa Baileys vs Cloud API](#14-apéndice-a-comparativa-baileys-vs-cloud-api)
15. [Apéndice B: Referencia rápida de endpoints](#15-apéndice-b-referencia-rápida-de-endpoints)

---

## 1. Introducción a Evolution API

### ¿Qué es Evolution API?

Evolution API es una plataforma **open-source** de integración con WhatsApp que expone una **API RESTful completa** sobre dos backends: **Baileys** (WhatsApp Web multidispositivo, gratuito) y **WhatsApp Cloud API** (Meta Graph API, oficial). Permite construir clientes WhatsApp personalizados, chatbots, CRMs y aplicaciones de mensajería sin tratar directamente con el protocolo de WhatsApp.

A junio de 2026, el proyecto cuenta con **~8,700 estrellas** en GitHub, **~6,700 forks**, y una comunidad activa. El repositorio migró de `EvolutionAPI` a `evolution-foundation` en GitHub.

### Arquitectura de alto nivel

```mermaid
graph TD
    A[Tu Aplicación / WhatsApp Lite] -->|REST API| B[Evolution API]
    A -->|WebSocket Socket.IO| B
    B -->|Baileys| C[WhatsApp Web MD]
    B -->|Meta Graph API| D[WhatsApp Cloud API]
    B -->|Webhook HTTP| A
    B -->|RabbitMQ/Kafka/SQS/NATS| E[Colas de mensajes]
    
    B --> F[(PostgreSQL)]
    B --> G[(Redis)]
    
    style A fill:#4CAF50,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#9C27B0,color:#fff
```

### Backends disponibles

| Backend | Tipo | Conexión | Costo | Verificación |
|---------|------|----------|-------|--------------|
| **Baileys** | WhatsApp Web (no oficial) | QR Code | Gratis | No requerida |
| **Cloud API** | Meta Graph API (oficial) | Token permanente | Pago por conversación | Business verification |

> ⚠️ **Nota crítica:** Muchas funcionalidades (stories, grupos sin OBA, botones nativos) **solo están disponibles en Baileys**. Cloud API ofrece estabilidad oficial y templates de WhatsApp Business, pero con funcionalidad más limitada.

### Versiones documentadas

- **Estable:** v2.3.7 (5 diciembre 2025)
- **Pre-release:** v2.4.0-rc2 (17 mayo 2026)

---

## 2. Instalación y despliegue rápido

### Requisitos mínimos

| Recurso | Mínimo | Recomendado |
|---------|--------|-------------|
| RAM | 1 GB | 4 GB |
| CPU | 1 vCPU | 2+ vCPU |
| Disco | 5 GB | 20 GB SSD |
| Node.js | ≥ 18.x | 20 LTS |
| Base de datos | SQLite (desarrollo) | PostgreSQL (producción) |
| Cache | Ninguno (desarrollo) | Redis (producción) |

### Docker (recomendado)

```bash
# docker-compose.yml
version: '3.8'
services:
  evolution-api:
    image: atendai/evolution-api:latest
    container_name: evolution-api
    restart: always
    ports:
      - "8080:8080"
    environment:
      - AUTHENTICATION_API_KEY=tu-api-key-global-super-segura
      - AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
      - DATABASE_ENABLED=true
      - DATABASE_PROVIDER=postgresql
      - DATABASE_CONNECTION_URI=postgresql://user:pass@postgres:5432/evolution
      - REDIS_ENABLED=true
      - REDIS_URI=redis://redis:6379
      - WEBSOCKET_ENABLED=true
      - WEBHOOK_GLOBAL_ENABLED=true
      - WEBHOOK_GLOBAL_URL=https://tu-app.com/webhook
      - DEL_INSTANCE=false
    depends_on:
      - postgres
      - redis

  postgres:
    image: postgres:15
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: evolution
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:
```

```bash
# Levantar servicios
docker-compose up -d

# Verificar salud
curl http://localhost:8080/health
```

### Variables de entorno esenciales

| Variable | Descripción | Ejemplo |
|----------|-------------|---------|
| `AUTHENTICATION_API_KEY` | API Key global maestra | `sk-abc123...` |
| `DATABASE_ENABLED` | Activar persistencia | `true` |
| `DATABASE_PROVIDER` | Motor de BD | `postgresql` |
| `REDIS_ENABLED` | Activar Redis (cache sesiones) | `true` |
| `WEBSOCKET_ENABLED` | Activar WebSocket nativo | `true` |
| `WEBHOOK_GLOBAL_ENABLED` | Webhook global | `true` |
| `DEL_INSTANCE` | Borrar instancia al hacer logout | `false` |

---

## 3. Autenticación y gestión de instancias

### Concepto de instancia

Cada número de WhatsApp conectado a Evolution API es una **instancia** independiente con su propio `instanceName`, token de acceso y sesión. Una instancia puede estar en uno de estos estados:

```mermaid
stateDiagram-v2
    [*] --> created: POST /instance/create
    created --> qr_ready: GET /instance/connect/{instance}
    qr_ready --> connected: Usuario escanea QR
    connected --> disconnected: Pérdida de conexión
    disconnected --> connected: Reconexión automática
    connected --> logged_out: DELETE /instance/logout/{instance}
    logged_out --> [*]
    
    state connected {
        [*] --> sending_receiving
        sending_receiving --> [*]
    }
```

### Crear instancia

```bash
curl -X POST {{BASE_URL}}/instance/create \
  -H "apikey: {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -d '{
    "instanceName": "whatsapp-lite",
    "token": "mi-token-secreto-instancia",
    "qrcode": true,
    "webhook": {
      "enabled": true,
      "url": "https://mi-app.com/webhook",
      "events": ["MESSAGES_UPSERT", "MESSAGES_UPDATE", "CONNECTION_UPDATE"]
    }
  }'
```

**Respuesta esperada:**

```json
{
  "instance": {
    "instanceName": "whatsapp-lite",
    "instanceId": "instance-abc123",
    "status": "created"
  },
  "hash": {
    "apikey": "..."
  }
}
```

### Conectar vía QR

```bash
curl -X GET {{BASE_URL}}/instance/connect/whatsapp-lite \
  -H "apikey: {{API_KEY}}"
```

**Respuesta:** Objeto JSON con `code` (QR en base64) y `base64` (imagen QR).

```javascript
// JavaScript/Node.js: obtener QR y mostrarlo
async function getQRCode(instanceName) {
  const response = await fetch(
    `${BASE_URL}/instance/connect/${instanceName}`,
    { headers: { 'apikey': API_KEY } }
  );
  const data = await response.json();
  // data.base64 contiene la imagen QR
  return data.base64;
}
```

### Estados de conexión

El webhook `CONNECTION_UPDATE` emite:

```json
{
  "event": "connection.update",
  "instance": "whatsapp-lite",
  "data": {
    "state": "open",
    "statusReason": ""
  }
}
```

| Estado | Significado |
|--------|-------------|
| `open` | Conectado y funcional |
| `connecting` | Intentando reconectar |
| `close` | Desconectado |
| `refused` | Conexión rechazada (posible ban) |

### Logout / Desconexión

```bash
curl -X DELETE {{BASE_URL}}/instance/logout/whatsapp-lite \
  -H "apikey: {{API_KEY}}"
```

> 💡 **Tip:** Configura `DEL_INSTANCE=false` en producción para no perder la sesión al hacer logout. Las credenciales de sesión Baileys se almacenan en Redis o sistema de archivos.

---

## 4. Gestión de mensajes — Envío

Esta es la sección central para construir tu WhatsApp Lite. Evolution API soporta una amplia variedad de tipos de mensaje.

### Enviar texto

```bash
curl -X POST {{BASE_URL}}/message/sendText/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "5511999999999",
    "text": "¡Hola desde WhatsApp Lite!",
    "delay": 1200,
    "linkPreview": true,
    "mentionsEveryOne": false
  }'
```

```javascript
// JavaScript: enviar texto
async function sendText(number, text) {
  const res = await fetch(`${BASE_URL}/message/sendText/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      number: number,
      text: text,
      delay: 1200  // ms, simula escritura humana
    })
  });
  return res.json();
}
```

### Responder mensajes (citar)

```json
{
  "number": "5511999999999",
  "text": "¡Gracias por tu mensaje!",
  "quoted": {
    "key": {
      "remoteJid": "5511999999999@s.whatsapp.net",
      "fromMe": false,
      "id": "MESSAGE_ID_ORIGINAL"
    },
    "message": {
      "conversation": "Texto original citado"
    }
  }
}
```

### Enviar imagen

```bash
curl -X POST {{BASE_URL}}/message/sendMedia/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "5511999999999",
    "mediatype": "image",
    "media": "https://ejemplo.com/foto.jpg",
    "caption": "Mira esta foto",
    "mimetype": "image/jpeg"
  }'
```

### Enviar video

```json
{
  "number": "5511999999999",
  "mediatype": "video",
  "media": "https://ejemplo.com/video.mp4",
  "caption": "Video desde WhatsApp Lite",
  "mimetype": "video/mp4"
}
```

### Enviar audio / nota de voz

```json
{
  "number": "5511999999999",
  "mediatype": "audio",
  "media": "https://ejemplo.com/nota.ogg",
  "mimetype": "audio/ogg; codecs=opus",
  "ptt": true
}
```

> ⚠️ **Nota:** Evolution API convierte audio automáticamente a formato compatible con WhatsApp (libopus, 48kHz, mono). Configura `ptt: true` para enviar como nota de voz (Push-to-Talk).

### Enviar documento

```json
{
  "number": "5511999999999",
  "mediatype": "document",
  "media": "https://ejemplo.com/archivo.pdf",
  "fileName": "reporte-final.pdf",
  "mimetype": "application/pdf",
  "caption": "Aquí está el reporte"
}
```

### Enviar sticker

```bash
curl -X POST {{BASE_URL}}/message/sendSticker/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "5511999999999",
    "sticker": "https://ejemplo.com/sticker.webp"
  }'
```

> ⚠️ **Nota importante sobre stickers:**
> - WhatsApp requiere stickers en formato **WebP** (estático o animado).
> - Dimensiones: **512×512 píxeles**.
> - Tamaño máximo: **~100 KB**.
> - Fondo transparente recomendado.
> - Evolution API v2.4.0-rc2 preserva animación en stickers GIF y WebP.
> - Debes **pre-convertir** tus imágenes a WebP antes de enviarlas como sticker.

```javascript
// Enviar sticker desde base64 (útil para stickers generados dinámicamente)
async function sendStickerBase64(number, webpBase64) {
  return fetch(`${BASE_URL}/message/sendSticker/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      number: number,
      sticker: `data:image/webp;base64,${webpBase64}`
    })
  });
}
```

### Enviar ubicación

```json
{
  "number": "5511999999999",
  "name": "Oficina Central",
  "address": "Av. Paulista, 1000 - São Paulo, SP",
  "latitude": -23.5665,
  "longitude": -46.6532
}
```

### Enviar contacto (vCard)

```json
{
  "number": "5511999999999",
  "contact": [
    {
      "fullName": "María García",
      "wuid": "5511888888888",
      "phoneNumber": "+55 11 88888-8888",
      "organization": "Empresa S.A.",
      "email": "maria@empresa.com",
      "url": "https://empresa.com"
    }
  ]
}
```

### Enviar encuesta

```json
{
  "number": "5511999999999",
  "name": "¿Qué día prefieres?",
  "selectableCount": 1,
  "values": ["Lunes", "Miércoles", "Viernes"]
}
```

### Enviar botones (solo Baileys)

```json
{
  "number": "5511999999999",
  "title": "Confirmar pedido",
  "description": "¿Deseas confirmar tu pedido #1234?",
  "footer": "Gracias por tu preferencia",
  "buttons": [
    { "buttonText": { "displayText": "✅ Sí, confirmar" }, "buttonId": "confirm_yes" },
    { "buttonText": { "displayText": "❌ Cancelar" }, "buttonId": "confirm_no" }
  ]
}
```

> ⚠️ **Nota urgente:** Issue #2351 reporta botones y listas **no funcionales** en WhatsApp en v2.3.x. Se espera corrección en v2.4.0 estable.

### Enviar listas (solo Baileys)

```json
{
  "number": "5511999999999",
  "title": "Selecciona una opción",
  "description": "Menú principal",
  "buttonText": "Ver opciones",
  "footer": "WhatsApp Lite",
  "sections": [
    {
      "title": "Servicios",
      "rows": [
        { "title": "Soporte técnico", "rowId": "opt_1" },
        { "title": "Ventas", "rowId": "opt_2" }
      ]
    }
  ]
}
```

### Enviar template (principalmente Cloud API)

```json
{
  "number": "5511999999999",
  "name": "order_confirmation",
  "language": "es",
  "components": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "text": "#12345" },
        { "type": "text", "text": "$150.00" }
      ]
    }
  ]
}
```

### Enviar reacción

```json
{
  "key": {
    "remoteJid": "5511999999999@s.whatsapp.net",
    "fromMe": true,
    "id": "MESSAGE_ID"
  },
  "reaction": "❤️"
}
```

### Resumen: tipos de mensaje por backend

| Tipo | Endpoint | Baileys | Cloud API |
|------|----------|---------|-----------|
| Texto | `sendText` | ✅ | ✅ |
| Imagen | `sendMedia` (image) | ✅ | ✅ |
| Video | `sendMedia` (video) | ✅ | ✅ |
| Audio | `sendMedia` (audio) | ✅ | ✅ |
| Documento | `sendMedia` (document) | ✅ | ✅ |
| Sticker | `sendSticker` | ✅ | ✅ |
| Ubicación | `sendLocation` | ✅ | ✅ |
| Contacto | `sendContact` | ✅ | ✅ |
| Encuesta | `sendPoll` | ✅ | ✅ |
| Reacción | `sendReaction` | ✅ | ✅ |
| Botones | `sendButtons` | ✅ (bugs v2.3.x) | Vía templates |
| Listas | `sendList` | ✅ (bugs v2.3.x) | Vía templates |
| Template | `sendTemplate` | ❌ | ✅ |
| Status/Story | `sendStatus` | ✅ | ❌ |

---

## 5. Gestión de mensajes — Recepción

Para recibir mensajes en tiempo real, Evolution API ofrece **tres mecanismos**:

### Opción 1: WebSocket (recomendado para apps interactivas)

```javascript
// Conexión WebSocket nativa con Socket.IO
import { io } from 'socket.io-client';

const socket = io('wss://api.evolution.com/whatsapp-lite', {
  transports: ['websocket']
});

socket.on('connect', () => {
  console.log('✅ Conectado a Evolution API WebSocket');
});

socket.on('messages-upsert', (data) => {
  console.log('📩 Nuevo mensaje:', data);
  // data.data.key.remoteJid → quién envió
  // data.data.message.conversation → texto
  // data.data.message.imageMessage → imagen
  // data.data.message.videoMessage → video
  // data.data.message.audioMessage → audio
  // data.data.message.documentMessage → documento
});

socket.on('messages-update', (data) => {
  console.log('🔄 Estado actualizado:', data);
});

socket.on('connection-update', (data) => {
  console.log('🔌 Estado conexión:', data.data.state);
});

socket.on('disconnect', () => {
  console.log('❌ Desconectado, reconectando...');
});
```

**Modos de WebSocket:**

| Modo | URL | Eventos |
|------|-----|---------|
| **Global** | `wss://host` | Todas las instancias |
| **Por instancia** | `wss://host/instanceName` | Una instancia específica |

### Opción 2: Webhook HTTP

Configura una URL donde Evolution API enviará POST por cada evento:

```json
// POST /webhook/set/whatsapp-lite
{
  "webhook": {
    "enabled": true,
    "url": "https://mi-app.com/evolution-webhook",
    "events": [
      "MESSAGES_UPSERT",
      "MESSAGES_UPDATE",
      "MESSAGES_DELETE",
      "CONNECTION_UPDATE",
      "PRESENCE_UPDATE"
    ],
    "webhook_by_events": false,
    "webhook_base64": false,
    "headers": {
      "Authorization": "Bearer mi-token-interno"
    }
  }
}
```

Tu servidor recibe POST:

```json
{
  "event": "messages.upsert",
  "instance": "whatsapp-lite",
  "data": {
    "key": {
      "remoteJid": "5511999999999@s.whatsapp.net",
      "fromMe": false,
      "id": "BAE5F3A2C1D4E6"
    },
    "pushName": "Juan Pérez",
    "messageType": "conversation",
    "message": {
      "conversation": "Hola, ¿cómo estás?"
    }
  }
}
```

### Opción 3: Colas de mensajes

Evolution API soporta: **RabbitMQ, Kafka, SQS, Pusher, NATS**. Configurables desde variables de entorno.

### Formato de payload por tipo de mensaje

| messageType | Campo en payload |
|-------------|-----------------|
| `conversation` | `message.conversation` |
| `imageMessage` | `message.imageMessage` (url, caption, mimetype, jpegThumbnail) |
| `videoMessage` | `message.videoMessage` (url, caption, mimetype, seconds, gifPlayback) |
| `audioMessage` | `message.audioMessage` (url, mimetype, seconds) |
| `documentMessage` | `message.documentMessage` (url, fileName, mimetype, pageCount) |
| `stickerMessage` | `message.stickerMessage` (url, isAnimated) |
| `locationMessage` | `message.locationMessage` (degreesLatitude, degreesLongitude) |
| `contactMessage` | `message.contactMessage` (displayName, vcard) |
| `reactionMessage` | `message.reactionMessage` (text, key) |

### Deserialización en JavaScript

```javascript
function parseMessage(data) {
  const msg = data.data;
  const sender = msg.key.remoteJid;
  const isGroup = sender.endsWith('@g.us');
  const fromMe = msg.key.fromMe;

  switch (msg.messageType) {
    case 'conversation':
      return { type: 'text', text: msg.message.conversation, sender, isGroup, fromMe };

    case 'imageMessage':
      return { type: 'image', url: msg.message.imageMessage.url,
               caption: msg.message.imageMessage.caption, sender, isGroup, fromMe };

    case 'videoMessage':
      return { type: 'video', url: msg.message.videoMessage.url,
               caption: msg.message.videoMessage.caption, sender, isGroup, fromMe };

    case 'audioMessage':
      return { type: 'audio', url: msg.message.audioMessage.url,
               seconds: msg.message.audioMessage.seconds, sender, isGroup, fromMe };

    case 'documentMessage':
      return { type: 'document', url: msg.message.documentMessage.url,
               fileName: msg.message.documentMessage.fileName, sender, isGroup, fromMe };

    case 'stickerMessage':
      return { type: 'sticker', url: msg.message.stickerMessage.url,
               animated: msg.message.stickerMessage.isAnimated, sender, isGroup, fromMe };

    case 'locationMessage':
      return { type: 'location',
               lat: msg.message.locationMessage.degreesLatitude,
               lon: msg.message.locationMessage.degreesLongitude, sender, isGroup, fromMe };

    default:
      return { type: 'unknown', raw: msg, sender, isGroup, fromMe };
  }
}
```

---

## 6. Historial de conversaciones (chats)

### Cargar lista de chats

```bash
curl -X POST {{BASE_URL}}/chat/findChats/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "limit": 50,
    "offset": 0,
    "sort": {
      "field": "updatedAt",
      "order": "desc"
    }
  }'
```

Devuelve lista de chats sincronizados desde WhatsApp con último mensaje, timestamp, y `remoteJid`.

### Buscar mensajes por chat/contacto

**Endpoint:** `POST /chat/findMessages/{instance}`

```bash
curl -X POST {{BASE_URL}}/chat/findMessages/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {
      "key": {
        "remoteJid": "5511999999999@s.whatsapp.net"
      }
    },
    "limit": 100,
    "offset": 0,
    "sort": {
      "field": "messageTimestamp",
      "order": "desc"
    }
  }'
```

```javascript
// Cargar historial con paginación para tu WhatsApp Lite
async function loadChatHistory(contactJid, page = 0, pageSize = 50) {
  const res = await fetch(`${BASE_URL}/chat/findMessages/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      where: { key: { remoteJid: contactJid } },
      limit: pageSize,
      offset: page * pageSize,
      sort: { field: 'messageTimestamp', order: 'desc' }
    })
  });
  return res.json();
}
```

> ⚠️ **Nota:** El endpoint es **POST**, no GET. El filtro se pasa en el body como `where.key.remoteJid`.
>
> ⚠️ **Bug conocido:** El campo `pushName` puede aparecer vacío debido al bug #2426. Usa `remoteJid` como identificador confiable.
>
> 💡 **Tip:** El evento webhook `MESSAGES_SET` se emite al completar la sincronización masiva de historial, con `isLatest: true` y `progress` (porcentaje). Ideal para mostrar una barra de progreso en tu WhatsApp Lite.

### Marcar mensaje de audio como reproducido

```bash
curl -X POST {{BASE_URL}}/chat/markMessageAsPlayed/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "key": {
      "remoteJid": "5511999999999@s.whatsapp.net",
      "fromMe": true,
      "id": "MESSAGE_ID"
    }
  }'
```

---

## 7. Estados de mensaje (sent/delivered/read/played)

### Ciclo de vida de un mensaje

```mermaid
sequenceDiagram
    participant App as WhatsApp Lite
    participant Evo as Evolution API
    participant WA as WhatsApp
    
    App->>Evo: POST /message/sendText
    Evo->>WA: Enviar mensaje
    Evo-->>App: Webhook MESSAGES_UPSERT (status: PENDING)
    WA-->>Evo: Confirmación de envío
    Evo-->>App: Webhook MESSAGES_UPDATE (status: SENT)
    WA-->>Evo: Entrega a destinatario
    Evo-->>App: Webhook MESSAGES_UPDATE (status: DELIVERED)
    WA-->>Evo: Destinatario abre chat
    Evo-->>App: Webhook MESSAGES_UPDATE (status: READ)
```

### Códigos de estado

| Código | Estado | Significado |
|--------|--------|-------------|
| 0 | ERROR | Fallo al enviar |
| 1 | PENDING | En cola de envío |
| 2 | SENT | Enviado desde servidor |
| 3 | DELIVERED | Llegó al dispositivo |
| 4 | READ | Destinatario leyó |
| 5 | PLAYED | Audio/voz reproducido |

### Evento `MESSAGES_UPDATE`

```json
{
  "event": "messages.update",
  "instance": "whatsapp-lite",
  "data": {
    "key": {
      "remoteJid": "5511999999999@s.whatsapp.net",
      "id": "BAE5F3A2C1D4E6",
      "fromMe": true
    },
    "status": "READ"
  }
}
```

### Manejo en tu WhatsApp Lite

```javascript
// Socket.IO: escuchar cambios de estado
socket.on('messages-update', (data) => {
  const { key, status } = data.data;

  // Actualizar UI con el nuevo estado
  updateMessageStatus(key.id, status);
  // Ejemplo: cambiar doble check gris → doble check azul
});

// Función helper para interpretar estados
function getDisplayStatus(statusCode) {
  const statusMap = {
    0: 'error',
    1: 'pending',
    2: 'sent',
    3: 'delivered',
    4: 'read',
    5: 'played'
  };
  return statusMap[statusCode] || 'unknown';
}
```

### Eventos relacionados

| Evento | Cuándo se emite |
|--------|----------------|
| `MESSAGES_UPSERT` | Mensaje nuevo (entrante o saliente) |
| `MESSAGES_UPDATE` | Cambio de estado (sent→delivered→read) |
| `MESSAGES_EDITED` | Mensaje editado |
| `MESSAGES_DELETE` | Mensaje eliminado por remitente |
| `MESSAGES_SET` | Sincronización de historial completada |

---

## 8. Contactos

### Obtener todos los contactos

```bash
curl -X POST {{BASE_URL}}/chat/findContacts/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "limit": 200,
    "offset": 0,
    "sort": {
      "field": "pushName",
      "order": "asc"
    }
  }'
```

**Respuesta:**

```json
[
  {
    "id": 1,
    "remoteJid": "5511999999999@s.whatsapp.net",
    "pushName": "Juan Pérez",
    "profilePictureUrl": "https://...",
    "owner": "whatsapp-lite",
    "createdAt": "2026-06-15T10:30:00Z",
    "updatedAt": "2026-06-17T14:22:00Z"
  }
]
```

### Campos disponibles

| Campo | Descripción | Siempre presente |
|-------|-------------|-----------------|
| `remoteJid` | Identificador WhatsApp (`número@s.whatsapp.net`) | ✅ |
| `pushName` | Nombre público en WhatsApp | ⚠️ Puede vacío por bug #2426 |
| `profilePictureUrl` | URL de foto de perfil | Condicional |
| `owner` | Instancia propietaria | ✅ |
| `createdAt` | Fecha de creación del registro | ✅ |
| `updatedAt` | Última actualización | ✅ |

> ⚠️ **Limitaciones detectadas:**
> - `verifiedName` e `isBusiness` **no están expuestos** en la respuesta de `findContacts`.
> - El campo `pushName` puede aparecer vacío (bug #2004, #2426).
> - **No existe endpoint documentado para bloquear/desbloquear contactos.**

### Sincronización de contactos

Evolution API sincroniza automáticamente los contactos desde WhatsApp Web (Baileys). Los eventos `CONTACTS_SET`, `CONTACTS_UPSERT` y `CONTACTS_UPDATE` se emiten cuando hay cambios.

### Presencia y última conexión

El evento `PRESENCE_UPDATE` informa cambios de presencia:

```json
{
  "event": "presence.update",
  "instance": "whatsapp-lite",
  "data": {
    "id": "5511999999999@s.whatsapp.net",
    "presences": {
      "5511999999999@s.whatsapp.net": {
        "lastKnownPresence": "available",
        "lastSeen": 1687000000
      }
    }
  }
}
```

| Presencia | Significado |
|-----------|-------------|
| `available` | En línea |
| `unavailable` | Fuera de línea |
| `composing` | Escribiendo... |
| `recording` | Grabando audio... |

```javascript
// WebSocket: detectar cuando alguien está escribiendo
socket.on('presence-update', (data) => {
  const presences = data.data.presences;
  for (const [jid, presence] of Object.entries(presences)) {
    if (presence.lastKnownPresence === 'composing') {
      showTypingIndicator(jid);
    }
  }
});
```

### Foto de perfil

```bash
curl -X POST {{BASE_URL}}/chat/fetchProfilePictureUrl/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "5511999999999"
  }'
```

---

## 9. Estados / Stories de WhatsApp

> ⚠️ **Disponible solo en backend Baileys.** Cloud API de Meta no expone endpoints de stories.

### Publicar un estado (story)

**Endpoint:** `POST /message/sendStatus/{instance}`

```bash
curl -X POST {{BASE_URL}}/message/sendStatus/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "image",
    "content": "https://ejemplo.com/status-foto.jpg",
    "caption": "Mi estado del día"
  }'
```

### Tipos de contenido para status

| Tipo | Ejemplo payload |
|------|----------------|
| `text` | `{"type":"text","content":"Hola mundo","backgroundColor":"#FF5733"}` |
| `image` | `{"type":"image","content":"https://...","caption":"..."}` |
| `video` | `{"type":"video","content":"https://...","caption":"..."}` |
| `audio` | `{"type":"audio","content":"https://..."}` |

```javascript
// Publicar estado tipo texto con fondo personalizado
async function postTextStatus(text, bgColor = '#2ECC71') {
  return fetch(`${BASE_URL}/message/sendStatus/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      type: 'text',
      content: text,
      backgroundColor: bgColor
    })
  });
}

// Publicar estado con imagen
async function postImageStatus(imageUrl, caption = '') {
  return fetch(`${BASE_URL}/message/sendStatus/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      type: 'image',
      content: imageUrl,
      caption: caption
    })
  });
}
```

> ⚠️ **Advertencia oficial de Evolution API:** "This endpoint is currently under review. The Status/Story functionality may have limitations depending on the WhatsApp client version and account type."

### Leer stories de otros contactos

**No se encontró endpoint para obtener/leer stories de otros contactos.** Evolution API solo expone el envío de stories, no la lectura del feed. Esta es una limitación importante para un WhatsApp Lite que quiera mostrar los estados de los contactos.

---

## 10. Grupos y comunidades

### Crear grupo

```bash
curl -X POST {{BASE_URL}}/group/create/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Equipo WhatsApp Lite",
    "participants": ["5511999999999", "5511888888888"],
    "description": "Grupo de colaboración",
    "promoteParticipants": false
  }'
```

**Respuesta:**

```json
{
  "groupJid": "120363123456789@g.us",
  "subject": "Equipo WhatsApp Lite",
  "participants": [
    {
      "id": "5511999999999@s.whatsapp.net",
      "isAdmin": false,
      "isSuperAdmin": false
    }
  ],
  "createdAt": 1709553600
}
```

### Endpoints de grupo

| Endpoint | Método | Descripción |
|----------|--------|-------------|
| `/group/create/{instance}` | POST | Crear grupo nuevo |
| `/group/addParticipants/{instance}` | POST | Añadir participantes |
| `/group/removeParticipants/{instance}` | POST | Eliminar participantes |
| `/group/setAdmin/{instance}` | POST | Promover a administrador |
| `/group/removeAdmin/{instance}` | POST | Remover administrador |
| `/group/updateGroupPicture/{instance}` | POST | Cambiar foto del grupo |
| `/group/updateGroupSubject/{instance}` | POST | Cambiar asunto |
| `/group/updateGroupDescription/{instance}` | POST | Cambiar descripción |
| `/group/fetchInviteCode/{instance}` | GET | Obtener código de invitación |
| `/group/revokeInviteCode/{instance}` | POST | Revocar código de invitación |
| `/group/findGroupInfo/{instance}` | POST | Buscar información del grupo |
| `/group/leaveGroup/{instance}` | POST | Salir del grupo |

```javascript
// Añadir participante a grupo
async function addParticipant(groupJid, phoneNumber) {
  return fetch(`${BASE_URL}/group/addParticipants/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      groupJid: groupJid,
      participants: [phoneNumber]
    })
  });
}
```

### Menciones

```json
{
  "groupJid": "120363123456789@g.us",
  "text": "Hola @todos",
  "mentionsEveryOne": true,
  "mentions": [
    "5511999999999@s.whatsapp.net"
  ]
}
```

> ⚠️ **Bug #1807:** `mentionsEveryOne` puede no etiquetar a todos los miembros en algunas versiones. Las menciones individuales son más confiables.

### Comunidades

Soporte **inicial** en v2.4.0-rc2. Endpoints específicos aún no detallados en la documentación pública.

### Restricción Cloud API para Grupos

WhatsApp Cloud API **solo permite crear grupos a Official Business Accounts (OBA)** con green tick. Para cuentas estándar: la funcionalidad de grupos no está disponible en Cloud API.

---

## 11. Webhooks y eventos en tiempo real

### Eventos disponibles (40+ tipos)

#### Categoría: Instancia

| Evento | Descripción |
|--------|-------------|
| `APPLICATION_STARTUP` | Evolution API inició |
| `INSTANCE_CREATE` | Nueva instancia creada |
| `INSTANCE_DELETE` | Instancia eliminada |
| `QRCODE_UPDATED` | QR code refrescado |
| `CONNECTION_UPDATE` | Cambio de estado de conexión |
| `REMOVE_INSTANCE` | Instancia removida |
| `LOGOUT_INSTANCE` | Instancia deslogueada |

#### Categoría: Mensajes

| Evento | Descripción |
|--------|-------------|
| `MESSAGES_SET` | Sincronización de historial completada |
| `MESSAGES_UPSERT` | Mensaje nuevo o actualizado |
| `MESSAGES_UPDATE` | Cambio de estado (sent/delivered/read) |
| `MESSAGES_EDITED` | Mensaje editado |
| `MESSAGES_DELETE` | Mensaje eliminado |

#### Categoría: Contactos y Chats

| Evento | Descripción |
|--------|-------------|
| `CONTACTS_SET` | Sincronización de contactos completada |
| `CONTACTS_UPSERT` | Contacto nuevo o actualizado |
| `CONTACTS_UPDATE` | Cambio en contacto |
| `CHATS_SET` | Sincronización de chats completada |
| `CHATS_UPSERT` | Chat nuevo o actualizado |
| `CHATS_UPDATE` | Cambio en chat |
| `CHATS_DELETE` | Chat eliminado |

#### Categoría: Grupos y Presencia

| Evento | Descripción |
|--------|-------------|
| `GROUPS_UPSERT` | Grupo nuevo o actualizado |
| `GROUPS_UPDATE` | Cambio en grupo |
| `GROUPS_PARTICIPANTS_UPDATE` | Cambio en participantes |
| `PRESENCE_UPDATE` | Cambio de presencia de contacto |
| `LABELS_EDIT` | Etiquetas editadas |
| `LABELS_ASSOCIATION` | Asociación de etiquetas |

### Configuración de webhook por instancia

```bash
curl -X POST {{BASE_URL}}/webhook/set/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook": {
      "enabled": true,
      "url": "https://mi-app.com/webhook",
      "events": [
        "MESSAGES_UPSERT",
        "MESSAGES_UPDATE",
        "MESSAGES_DELETE",
        "CONNECTION_UPDATE",
        "PRESENCE_UPDATE",
        "GROUPS_UPSERT",
        "GROUPS_PARTICIPANTS_UPDATE"
      ],
      "webhook_by_events": false,
      "webhook_base64": false,
      "headers": {
        "Authorization": "Bearer mi-token-secreto"
      }
    }
  }'
```

### Configuración global (.env)

```env
WEBHOOK_GLOBAL_ENABLED=true
WEBHOOK_GLOBAL_URL=https://mi-app.com/webhook-global
WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
```

### Reintentos

Evolution API implementa **retry automático con exponential backoff** para webhooks. El número máximo de reintentos y el intervalo exacto no están documentados públicamente.

### Verificación de firma

> ⚠️ **No se encontró documentación de firma criptográfica** tipo `X-Hub-Signature-256` como ofrece Meta. Evolution API confía en el header `Authorization` configurable + `apikey`. Debes implementar tu propia capa de verificación si la necesitas.

### WebSocket: eventos en tiempo real

Todos los eventos de webhook también están disponibles vía WebSocket (Socket.IO):

```javascript
socket.on('messages-upsert', handleNewMessage);
socket.on('messages-update', handleStatusUpdate);
socket.on('messages-delete', handleMessageDelete);
socket.on('messages-edited', handleMessageEdit);
socket.on('presence-update', handlePresenceChange);
socket.on('connection-update', handleConnectionChange);
socket.on('contacts-upsert', handleContactUpdate);
socket.on('groups-upsert', handleGroupUpdate);
```

---

## 12. Multimedia: carga, descarga y límites

### Métodos de envío de archivos

Evolution API soporta **tres métodos** para enviar archivos multimedia:

| Método | Formato | Cuándo usar |
|--------|---------|-------------|
| **URL pública** | `"media": "https://..."` | Archivos ya alojados |
| **Base64** | `"media": "data:image/jpeg;base64,..."` | Archivos generados dinámicamente |
| **Multipart/form-data** | Upload binario directo | Subida directa desde cliente |

### Ejemplo con multipart/form-data

```bash
curl -X POST {{BASE_URL}}/message/sendMedia/whatsapp-lite \
  -H "apikey: {{INSTANCE_TOKEN}}" \
  -F "number=5511999999999" \
  -F "mediatype=image" \
  -F "media=@/ruta/local/foto.jpg" \
  -F "caption=Mira esta foto"
```

### Tipos MIME soportados

| Tipo | Formatos |
|------|----------|
| Imagen | `image/jpeg`, `image/png`, `image/gif`, `image/webp` |
| Video | `video/mp4`, `video/3gpp` |
| Audio | `audio/mp4`, `audio/ogg; codecs=opus`, `audio/mpeg` |
| Documento | Cualquier MIME type (`application/pdf`, `application/zip`, etc.) |
| Sticker | `image/webp` (estático y animado) |

### Límites de tamaño

| Tipo | WhatsApp Web (Baileys) | Cloud API |
|------|------------------------|-----------|
| Imagen | ~5 MB | 5 MB |
| Video | ~16 MB | 16 MB |
| Audio | ~16 MB | 16 MB |
| Documento | ~100 MB | 100 MB |
| Sticker | ~100 KB | 100 KB |

> ⚠️ **Evolution API no impone límites adicionales.** Hereda los límites del backend correspondiente.

### Conversión automática de audio

Evolution API convierte audio a formato compatible con WhatsApp:
- **libopus** codec
- **48 kHz** sample rate
- **Mono** channel

Esto asegura compatibilidad con la reproducción nativa de WhatsApp.

### Descarga de multimedia recibida

Cuando recibes un mensaje multimedia vía webhook/websocket, el payload incluye una URL para descargar:

```javascript
socket.on('messages-upsert', async (data) => {
  const msg = data.data;

  if (msg.messageType === 'imageMessage') {
    const imageUrl = msg.message.imageMessage.url;

    // Descargar la imagen
    const response = await fetch(imageUrl);
    const buffer = await response.arrayBuffer();

    // Guardar localmente o mostrar en UI
    saveMedia(buffer, msg.message.imageMessage.mimetype);
  }
});
```

### Stickers: especificaciones técnicas

| Propiedad | Requisito |
|-----------|-----------|
| Formato | WebP (`.webp`) |
| Dimensiones | 512 × 512 píxeles |
| Tamaño máximo | ~100 KB |
| Fondo | Transparente (recomendado) |
| Animación | WebP animado (soportado desde v2.4.0-rc2) |

---

## 13. Limitaciones, cuotas y buenas prácticas

### Límites oficiales WhatsApp Cloud API

| Métrica | Estándar | Upgrade |
|---------|----------|---------|
| Request rate | 10 req/s | — |
| Throughput mensajes | 80 msg/s | Hasta 1,000 msg/s |
| On-premise API | 13 msg/s | — |

### Límites para Baileys (no oficiales)

No hay límites documentados porque Baileys emula WhatsApp Web. Sin embargo:

> ⚠️ **Riesgo real de ban:** Comportamiento no humano puede resultar en bloqueo temporal o permanente del número.

**Recomendaciones de la comunidad:**

- No exceder ~5-10 mensajes/segundo sostenidos.
- Simular pausas humanas entre mensajes (`delay` en payload).
- Evitar enviar a muchos números nuevos en corto tiempo.
- Usar números de teléfono "envejecidos".
- No enviar mensajes masivos idénticos.
- Mantener la instancia conectada de forma estable.
- No crear muchas instancias desde la misma IP.

### Buenas prácticas para tu WhatsApp Lite

```javascript
// Enviar con delay humano
async function sendTextLikeHuman(number, text) {
  const minDelay = 800;   // mínimo 0.8s
  const maxDelay = 3000;  // máximo 3s
  const delay = Math.floor(Math.random() * (maxDelay - minDelay) + minDelay);

  return fetch(`${BASE_URL}/message/sendText/whatsapp-lite`, {
    method: 'POST',
    headers: {
      'apikey': INSTANCE_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      number: number,
      text: text,
      delay: delay
    })
  });
}
```

### Checklist anti-ban

- [ ] Usar WebSocket para recibir mensajes (no polling).
- [ ] Configurar Redis para producción multi-instancia.
- [ ] PostgreSQL como base de datos persistente.
- [ ] No enviar mensajes a números que no aceptaron términos de WhatsApp.
- [ ] Rotar user-agent y fingerprints.
- [ ] Evitar horarios no humanos (madrugada).
- [ ] Mantener un intervalo mínimo de 500ms entre mensajes.
- [ ] Configurar `webhook_base64: false` (URLs son más eficientes).

### Límites internos de Evolution API

Evolution API no documenta rate limiting interno explícito. La limitación depende de tu infraestructura (nginx, API gateway) y los límites del backend WhatsApp.

---

## 14. Apéndice A: Comparativa Baileys vs Cloud API

### Tabla de funcionalidades

| Funcionalidad | Baileys | Cloud API | Notas |
|---------------|---------|-----------|-------|
| **Costo** | Gratis | Pago por conversación | Cloud API: primeras 1,000 conversaciones/mes gratis |
| **Conexión** | QR Code efímero | Token permanente | Baileys requiere re-escanear si se desconecta mucho tiempo |
| **Verificación** | No requerida | Business Verification (Meta) | OBA necesario para grupos, flows |
| **Texto** | ✅ | ✅ | Igual en ambos |
| **Imagen** | ✅ | ✅ | Igual en ambos |
| **Video** | ✅ | ✅ | Igual en ambos |
| **Audio** | ✅ (conversión auto) | ✅ | Baileys convierte a opus/48kHz/mono |
| **Documento** | ✅ | ✅ | Igual en ambos |
| **Sticker** | ✅ | ✅ | WebP requerido en ambos |
| **Ubicación** | ✅ | ✅ | Igual en ambos |
| **Contacto (vCard)** | ✅ | ✅ | Igual en ambos |
| **Encuesta** | ✅ | ✅ | Igual en ambos |
| **Reacción** | ✅ | ✅ | Igual en ambos |
| **Botones** | ✅ (bugs v2.3.x) | Vía templates | Baileys: nativos, Cloud: interactive templates |
| **Listas** | ✅ (bugs v2.3.x) | Vía templates | Baileys: nativas, Cloud: interactive templates |
| **Templates** | ❌ | ✅ | Exclusivo Cloud API |
| **Stories/Status** | ✅ | ❌ | Exclusivo Baileys |
| **Grupos (crear)** | ✅ | Solo OBA | Cloud API requiere Official Business Account |
| **Comunidades** | ✅ (v2.4.0-rc2) | Solo OBA | En desarrollo en Evolution API |
| **Catálogos** | ❌ | ✅ (vía Meta) | No gestionado por Evolution API |
| **Flows** | ❌ | ✅ (vía Meta, OBA) | No gestionado por Evolution API |
| **Rate limits** | No oficial (riesgo ban) | 80 msg/s documentado | Baileys: autorregulación requerida |
| **Estabilidad** | Depende de reverse-engineering | Oficial, garantizada | Cloud API es la opción "segura" |
| **Anti-ban** | Riesgo presente | Sin riesgo | Cloud API es oficial, no hay ban |

### ¿Cuál elegir para tu WhatsApp Lite?

| Caso de uso | Backend recomendado | Razón |
|-------------|---------------------|-------|
| Uso personal, todas las features | **Baileys** | Gratis, acceso a stories, grupos sin OBA, botones nativos |
| Negocio, mensajería transaccional | **Cloud API** | Estabilidad, templates, sin riesgo de ban, rate limits predecibles |
| Híbrido | Ambos | Usa Baileys para features no disponibles en Cloud API |

---

## 15. Apéndice B: Referencia rápida de endpoints

### Gestión de instancias

| Método | Endpoint | Descripción |
|--------|----------|-------------|
| POST | `/instance/create` | Crear instancia |
| GET | `/instance/connect/{instance}` | Obtener QR de conexión |
| DELETE | `/instance/logout/{instance}` | Desloguear instancia |
| DELETE | `/instance/delete/{instance}` | Eliminar instancia |
| GET | `/instance/fetchInstances` | Listar todas las instancias |
| GET | `/instance/connectionState/{instance}` | Estado de conexión |

### Mensajería

| Método | Endpoint | Descripción |
|--------|----------|-------------|
| POST | `/message/sendText/{instance}` | Enviar texto |
| POST | `/message/sendMedia/{instance}` | Enviar multimedia |
| POST | `/message/sendSticker/{instance}` | Enviar sticker |
| POST | `/message/sendLocation/{instance}` | Enviar ubicación |
| POST | `/message/sendContact/{instance}` | Enviar contacto |
| POST | `/message/sendPoll/{instance}` | Enviar encuesta |
| POST | `/message/sendReaction/{instance}` | Enviar reacción |
| POST | `/message/sendList/{instance}` | Enviar lista |
| POST | `/message/sendButtons/{instance}` | Enviar botones |
| POST | `/message/sendTemplate/{instance}` | Enviar template |
| POST | `/message/sendStatus/{instance}` | Publicar estado/story |

### Chats e Historial

| Método | Endpoint | Descripción |
|--------|----------|-------------|
| POST | `/chat/findChats/{instance}` | Listar chats |
| POST | `/chat/findMessages/{instance}` | Buscar mensajes por JID |
| POST | `/chat/findContacts/{instance}` | Listar contactos |
| POST | `/chat/markMessageAsPlayed/{instance}` | Marcar audio como reproducido |
| POST | `/chat/fetchProfilePictureUrl/{instance}` | Obtener foto de perfil |

### Grupos

| Método | Endpoint | Descripción |
|--------|----------|-------------|
| POST | `/group/create/{instance}` | Crear grupo |
| POST | `/group/addParticipants/{instance}` | Añadir participantes |
| POST | `/group/removeParticipants/{instance}` | Eliminar participantes |
| POST | `/group/setAdmin/{instance}` | Promover admin |
| POST | `/group/removeAdmin/{instance}` | Remover admin |
| POST | `/group/updateGroupPicture/{instance}` | Cambiar foto |
| POST | `/group/updateGroupSubject/{instance}` | Cambiar asunto |
| POST | `/group/updateGroupDescription/{instance}` | Cambiar descripción |
| GET | `/group/fetchInviteCode/{instance}` | Código de invitación |
| POST | `/group/revokeInviteCode/{instance}` | Revocar código |
| POST | `/group/findGroupInfo/{instance}` | Info del grupo |
| POST | `/group/leaveGroup/{instance}` | Salir del grupo |

### Webhooks

| Método | Endpoint | Descripción |
|--------|----------|-------------|
| POST | `/webhook/set/{instance}` | Configurar webhook |
| GET | `/webhook/find/{instance}` | Ver configuración |

---

## Solución de problemas comunes

### "No se pudo conectar el QR"

1. Verifica que la instancia esté creada: `GET /instance/connectionState/{instance}`
2. Asegúrate de que WhatsApp en tu teléfono esté actualizado.
3. Reintenta: `DELETE /instance/logout/{instance}` y luego `GET /instance/connect/{instance}`
4. Verifica que `DEL_INSTANCE=false` en tu `.env`.

### "pushName aparece vacío"

Bug conocido (#2004, #2426). Usa `remoteJid` como identificador único. Para mostrar el nombre, mantén un caché local con el último `pushName` no vacío.

### "Botones/Listas no funcionan"

Bug #2351 en v2.3.x. Espera a v2.4.0 estable o usa templates de Cloud API como alternativa.

### "No recibo webhooks"

1. Verifica que `WEBHOOK_GLOBAL_ENABLED=true` esté configurado.
2. Asegúrate de que la URL del webhook sea accesible desde Evolution API.
3. Revisa `GET /webhook/find/{instance}` para confirmar la configuración.
4. Prueba con WebSocket como alternativa (`WEBSOCKET_ENABLED=true`).

### "Desconexiones frecuentes"

- Usa Redis para mantener sesiones persistentes.
- Evita múltiples reconexiones rápidas.
- Asegura conectividad estable desde el servidor de Evolution API.
- Revisa logs del contenedor: `docker logs evolution-api`.

---

## Preguntas frecuentes

**P: ¿Puedo usar Evolution API para un cliente WhatsApp Lite personal?**
R: Sí. Evolution API está diseñada precisamente para eso. Conéctate vía WebSocket, obtén tus chats con `findChats`, historial con `findMessages`, y envía/recibe mensajes en tiempo real.

**P: ¿Puedo ver los estados/stories de mis contactos?**
R: **No directamente.** Evolution API permite PUBLICAR estados (`sendStatus`) pero no tiene endpoint para LEER el feed de stories de otros contactos. Esta es una limitación conocida.

**P: ¿Cómo envío stickers animados?**
R: Convierte tus animaciones a formato WebP animado, dimensiones 512×512px, máximo ~100KB, y usa `POST /message/sendSticker/{instance}`.

**P: ¿Puedo saber si mi mensaje fue leído?**
R: Sí. Suscríbete al evento `MESSAGES_UPDATE` vía WebSocket o webhook. Recibirás notificaciones con estados: SENT(2), DELIVERED(3), READ(4), PLAYED(5).

**P: ¿Cuántos mensajes puedo recuperar del historial?**
R: Evolution API no documenta un límite máximo en `findMessages`. Usa paginación con `limit`/`offset` para recuperar grandes volúmenes.

**P: ¿Baileys o Cloud API?**
R: Para uso personal con todas las features: **Baileys**. Para negocio con estabilidad garantizada: **Cloud API**.

**P: ¿Hay riesgo de que me baneen la cuenta?**
R: Con Baileys: **sí**, si abusas (spam, alta frecuencia, comportamiento no humano). Con Cloud API: **no**, es el canal oficial de Meta.

---

## Referencias y recursos adicionales

1. **Evolution API GitHub**: https://github.com/evolution-foundation/evolution-api
2. **Documentación oficial**: https://doc.evolution-api.com/
3. **Evolution Foundation Docs**: https://docs.evolutionfoundation.com.br/en/evolution-api
4. **Postman Collection oficial**: https://www.postman.com/agenciadgcode/evolution-api
5. **CHANGELOG oficial**: https://github.com/evolution-foundation/evolution-api/blob/main/CHANGELOG.md
6. **Baileys Library**: https://github.com/WhiskeySockets/Baileys
7. **Meta WhatsApp Cloud API**: https://developers.facebook.com/docs/whatsapp/cloud-api
8. **Evolution API Lite**: https://github.com/evolution-foundation/evolution-api-lite
9. **Evolution R Package (CRAN)**: https://cran.r-project.org/web/packages/evolution/
10. **DeepWiki API Reference**: https://deepwiki.com/EvolutionAPI/evolution-api/7-api-reference

---

## Diagrama: Flujo completo de WhatsApp Lite con Evolution API

```mermaid
flowchart TB
    subgraph Cliente["WhatsApp Lite (Tu App)"]
        UI[Interfaz de Usuario]
        WS[WebSocket Client]
        REST[REST Client]
    end

    subgraph Evolution["Evolution API"]
        Auth[Auth & Instance Manager]
        MsgHandler[Message Handler]
        ChatManager[Chat & Contact Manager]
        GroupManager[Group Manager]
        StatusMgr[Status/Story Manager]
        EventBus[Event Bus]
    end

    subgraph Backend["WhatsApp Backend"]
        Baileys[Baileys / WA Web]
        Cloud[Cloud API / Meta]
    end

    subgraph Storage["Almacenamiento"]
        PG[(PostgreSQL)]
        Redis[(Redis)]
    end

    UI -->|Conexión QR| REST
    UI -->|Enviar mensaje| REST
    UI -->|Recibir eventos| WS

    REST --> Auth
    REST --> MsgHandler
    REST --> ChatManager
    REST --> GroupManager
    REST --> StatusMgr

    Auth --> PG
    Auth --> Redis
    MsgHandler --> EventBus
    ChatManager --> EventBus
    GroupManager --> EventBus

    MsgHandler --> Baileys
    MsgHandler --> Cloud
    ChatManager --> Baileys
    GroupManager --> Baileys
    StatusMgr --> Baileys

    Baileys --> EventBus
    Cloud --> EventBus
    EventBus --> WS

    style Cliente fill:#4CAF50,color:#fff
    style Evolution fill:#2196F3,color:#fff
    style Backend fill:#FF9800,color:#fff
    style Storage fill:#9E9E9E,color:#fff
```

---

*Documento generado el 17 de junio de 2026. Basado en investigación de 20+ fuentes incluyendo GitHub, documentación oficial de Evolution API, Meta for Developers, y recursos comunitarios.*

*Los fragmentos de código en este documento deben verificarse contra una instancia real de Evolution API antes de usarse en producción.*