--- id: "SAAS-014" title: "WhatsApp Business API" type: "Module" status: "Published" priority: "P2" module: "whatsapp" version: "1.0.0" created_date: "2026-01-10" updated_date: "2026-01-10" --- # SAAS-014: WhatsApp Business API ## Metadata | Campo | Valor | |-------|-------| | Codigo | SAAS-014 | | Modulo | WhatsApp | | Prioridad | P2 | | Estado | Completado | | Fase | 5 - Integraciones | | Sprint | Sprint 5 | | Fecha Implementacion | 2026-01-10 | | Ultima Actualizacion | 2026-01-10 | --- ## Descripcion Integracion con WhatsApp Business API (Meta Cloud API) para envio de mensajes y notificaciones via WhatsApp. Permite a los tenants configurar su cuenta de WhatsApp Business y enviar mensajes de texto o templates pre-aprobados a sus usuarios. --- ## Objetivos 1. Proporcionar un canal adicional de comunicacion para notificaciones 2. Permitir configuracion por tenant de credenciales WhatsApp 3. Soportar envio de mensajes de texto y templates 4. Implementar tracking de estado de entrega 5. Aplicar rate limiting por tenant --- ## Alcance ### Incluido - Configuracion de credenciales WhatsApp Business por tenant - Envio de mensajes de texto simples - Envio de templates pre-aprobados por Meta - Webhook para recibir status de entrega (sent, delivered, read, failed) - Rate limiting configurable por tenant - Historial de mensajes enviados - Pagina de configuracion en portal admin - Integracion con sistema de notificaciones existente ### Excluido - Chatbots interactivos - Mensajes multimedia (imagenes, videos, documentos) - Grupos de WhatsApp - Recepcion de mensajes entrantes (solo outbound) - Flujos conversacionales --- ## Modelo de Datos ### Schema: whatsapp #### Tabla: whatsapp_configs | Columna | Tipo | Descripcion | |---------|------|-------------| | id | uuid | PK, generado | | tenant_id | uuid | FK a tenants.id | | phone_number_id | varchar(50) | ID del numero en Meta | | waba_id | varchar(50) | WhatsApp Business Account ID | | access_token | text | Token de acceso (encriptado) | | is_active | boolean | Si la integracion esta activa | | rate_limit_per_minute | integer | Limite de mensajes por minuto | | webhook_verify_token | varchar(100) | Token para verificar webhooks | | created_at | timestamp | Fecha de creacion | | updated_at | timestamp | Fecha de actualizacion | **Indices:** - `idx_whatsapp_configs_tenant` ON (tenant_id) - `UNIQUE` ON (tenant_id) - Solo una config por tenant **RLS:** Si, filtrado por tenant_id #### Tabla: whatsapp_messages | Columna | Tipo | Descripcion | |---------|------|-------------| | id | uuid | PK, generado | | tenant_id | uuid | FK a tenants.id | | config_id | uuid | FK a whatsapp_configs.id | | to_phone | varchar(20) | Numero destino (formato E.164) | | message_type | enum | 'text', 'template' | | template_name | varchar(100) | Nombre del template (si aplica) | | template_language | varchar(10) | Idioma del template (ej: 'es_MX') | | content | text | Contenido del mensaje | | status | enum | 'pending', 'sent', 'delivered', 'read', 'failed' | | wamid | varchar(100) | WhatsApp Message ID | | sent_at | timestamp | Cuando se envio | | delivered_at | timestamp | Cuando se entrego | | read_at | timestamp | Cuando se leyo | | error_code | varchar(20) | Codigo de error si fallo | | error_message | text | Mensaje de error si fallo | | metadata | jsonb | Metadata adicional | | created_at | timestamp | Fecha de creacion | **Indices:** - `idx_whatsapp_messages_tenant` ON (tenant_id) - `idx_whatsapp_messages_status` ON (status) - `idx_whatsapp_messages_wamid` ON (wamid) - `idx_whatsapp_messages_created` ON (created_at DESC) **RLS:** Si, filtrado por tenant_id ### Enums ```sql CREATE TYPE whatsapp.message_status AS ENUM ( 'pending', 'sent', 'delivered', 'read', 'failed' ); CREATE TYPE whatsapp.message_type AS ENUM ( 'text', 'template' ); CREATE TYPE whatsapp.message_direction AS ENUM ( 'outbound', 'inbound' -- Para uso futuro ); ``` --- ## Endpoints API ### Configuracion | Metodo | Ruta | Descripcion | |--------|------|-------------| | GET | `/whatsapp/config` | Obtener configuracion actual del tenant | | POST | `/whatsapp/config` | Crear/actualizar configuracion | | PUT | `/whatsapp/config` | Actualizar configuracion | | DELETE | `/whatsapp/config` | Desactivar integracion | ### Mensajes | Metodo | Ruta | Descripcion | |--------|------|-------------| | POST | `/whatsapp/send` | Enviar mensaje | | POST | `/whatsapp/test` | Enviar mensaje de prueba | | GET | `/whatsapp/messages` | Listar historial de mensajes | | GET | `/whatsapp/messages/:id` | Obtener detalle de mensaje | ### Webhook | Metodo | Ruta | Descripcion | |--------|------|-------------| | GET | `/whatsapp/webhook` | Verificacion de webhook (Meta challenge) | | POST | `/whatsapp/webhook` | Recibir eventos de Meta (delivery status) | --- ## DTOs ### CreateConfigDto ```typescript export class CreateWhatsAppConfigDto { @IsString() phoneNumberId: string; @IsString() wabaId: string; @IsString() accessToken: string; @IsOptional() @IsNumber() @Min(1) @Max(100) rateLimitPerMinute?: number = 30; } ``` ### SendMessageDto ```typescript export class SendWhatsAppMessageDto { @IsString() @Matches(/^\+[1-9]\d{1,14}$/) to: string; // Formato E.164 @IsEnum(['text', 'template']) type: 'text' | 'template'; @IsOptional() @IsString() text?: string; @IsOptional() @IsString() templateName?: string; @IsOptional() @IsString() templateLanguage?: string = 'es_MX'; @IsOptional() @IsArray() templateParams?: string[]; } ``` --- ## Flujo de Envio ``` 1. Usuario llama POST /whatsapp/send │ ▼ 2. Validar credenciales del tenant │ ▼ 3. Verificar rate limit │ ▼ 4. Crear registro en whatsapp_messages (status: pending) │ ▼ 5. Llamar Meta Cloud API │ ▼ 6. Actualizar status a 'sent' con wamid │ ▼ 7. Meta envia webhook con delivery status │ ▼ 8. Actualizar status (delivered/read/failed) ``` --- ## Implementacion Backend ### Estructura de Archivos ``` apps/backend/src/modules/whatsapp/ ├── whatsapp.module.ts ├── whatsapp.service.ts ├── whatsapp.controller.ts ├── whatsapp-webhook.controller.ts ├── entities/ │ ├── whatsapp-config.entity.ts │ └── whatsapp-message.entity.ts ├── dto/ │ ├── create-config.dto.ts │ ├── update-config.dto.ts │ ├── send-message.dto.ts │ └── index.ts └── __tests__/ └── whatsapp.service.spec.ts ``` ### Configuracion Requerida Variables de entorno: ```env # WhatsApp no requiere variables globales # Cada tenant configura sus propias credenciales via API ``` --- ## Implementacion Frontend ### Archivos ``` apps/frontend/src/ ├── pages/admin/ │ └── WhatsAppSettings.tsx ├── hooks/ │ └── useWhatsApp.ts ├── services/ │ └── whatsapp.api.ts └── components/whatsapp/ └── WhatsAppTestMessage.tsx ``` ### Pagina de Configuracion `WhatsAppSettings.tsx` incluye: - Formulario de configuracion de credenciales - Switch para activar/desactivar - Boton para enviar mensaje de prueba - Tabla de historial de mensajes recientes - Indicador de estado de conexion --- ## Rate Limiting | Plan | Mensajes/Minuto | Mensajes/Dia | |------|-----------------|--------------| | Free | 10 | 100 | | Starter | 30 | 1,000 | | Pro | 60 | 5,000 | | Enterprise | Custom | Custom | El rate limiting se aplica por tenant usando el campo `rate_limit_per_minute` de la configuracion. --- ## Integracion con Notifications WhatsApp se integra como un canal adicional en el modulo de notificaciones: ```typescript // En notifications.service.ts async sendNotification(options: NotificationOptions) { // ... otros canales ... if (options.channels.includes('whatsapp') && options.phone) { await this.whatsappService.send({ to: options.phone, type: 'template', templateName: options.template, templateParams: options.params }); } } ``` --- ## Seguridad 1. **Tokens encriptados**: El access_token se almacena encriptado en la base de datos 2. **Webhook verification**: Se verifica el token de Meta antes de procesar eventos 3. **RLS**: Todas las tablas tienen Row-Level Security por tenant_id 4. **Rate limiting**: Previene abuso y costos excesivos --- ## Dependencias | Modulo | Tipo | Descripcion | |--------|------|-------------| | SAAS-002 (Tenants) | Requerido | tenant_id en configs y messages | | SAAS-007 (Notifications) | Opcional | Canal adicional de notificacion | | SAAS-005 (Plans) | Requerido | Limites por plan | --- ## Entregables - [x] Schema DDL `whatsapp` con 2 tablas - [x] 3 enums (message_status, message_type, message_direction) - [x] WhatsAppModule backend con service y controllers - [x] 2 entidades TypeORM - [x] DTOs de configuracion y envio - [x] Webhook handler para Meta - [x] Pagina WhatsAppSettings.tsx - [x] Hook useWhatsApp.ts - [x] API client whatsapp.api.ts - [x] 22 tests unitarios --- ## Criterios de Aceptacion - [x] Configuracion de credenciales por tenant funciona - [x] Envio de mensajes de texto exitoso - [x] Envio de templates exitoso - [x] Webhook recibe y procesa status correctamente - [x] Rate limiting previene exceso de mensajes - [x] Historial de mensajes accesible en UI - [x] Mensaje de prueba funciona desde configuracion --- ## Referencias - [Meta WhatsApp Business API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api) - [Sprint 5 Plan](../../orchestration/planes/PLAN-SPRINT-5-WHATSAPP.md) - [SAAS-007-notifications.md](./SAAS-007-notifications.md) --- **Ultima actualizacion:** 2026-01-10 **Autor:** Claude Code (Reestructuracion Documental)