El WhatsApp, el SMS y el correo que tu producto manda, con registro de qué llegó.
Un motor de avisos para meter en lo tuyo: plantillas con variables, libreta de contactos con su consentimiento, credenciales de Meta y Twilio guardadas cifradas, y un registro por envío que dice encolado, enviado, entregado o leído. Con tus colores y en tu dominio.
Recordatorio de cita
Para Laura Medina
cita.recordatorio · v3
Hola Laura, te recordamos tu cita en Clínica Norte el jueves 26 a las 11:30. Responde SÍ para confirmar o llámanos para moverla.
09:00
- Encolado09:00:02
- Enviado09:00:04
- Entregado09:00:05
- Leído09:14:31
Mandar un mensaje es fácil. Poder demostrarlo después, no.
Llamar a Meta desde tu backend toma una tarde. Lo que toma meses es el consentimiento, el registro de qué llegó, los reintentos que no duplican y las llaves guardadas como se debe. Eso es lo que este módulo trae resuelto.
Lo que se mandó es lo que se aprobó
El cuerpo se arma al encolar y se guarda en el envío con la versión de la plantilla. Si alguien la edita mañana, el registro de hoy sigue diciendo exactamente qué le dijimos a ese cliente.
A quien dijo que no, no se le manda
La baja se guarda por canal, con fecha y motivo, y la comprueba la base de datos al encolar — no un `if` que una ruta nueva pueda olvidar. Si el cliente manda STOP, la baja se anota sola.
Tus llaves de Meta y Twilio no las lee nadie
Se cifran al guardarse y la tabla no tiene ni una política de lectura para usuarios: sólo el servidor las abre al despachar. El tablero muestra si están puestas y desde cuándo, nunca el secreto.
Tres pasos, y ninguno toca la API de Meta
Redactas la plantilla
Una por canal, porque un SMS de 160 caracteres y un correo con HTML no son el mismo texto. Con {{variables}} y una vista previa con datos reales antes de activarla.
Tu producto la encola
Desde el widget o con una llamada a la API: contacto, plantilla y variables. El módulo resuelve el canal, comprueba el consentimiento, renderiza y encola. Repetir la llamada no repite el mensaje.
El registro cuenta qué pasó
Enviado, entregado, leído o fallido con el error del proveedor traducido a español. Lo que se puede reintentar se reintenta solo; lo que necesita a una persona, se marca y se explica.
Tres canales y todo lo que hay alrededor
Cada canal con sus propias credenciales, guardadas por espacio de trabajo. Un envío es un canal: el texto aprobado en WhatsApp no es el correo, y reintentar por otro lado es un envío nuevo que alguien decide.
Meta Cloud API
SMS
Twilio
Correo
Resend
Libreta de contactos con consentimiento
Nombre, correo, teléfono y WhatsApp, más los atributos que quieras. El consentimiento vive aparte, por canal: el mismo cliente puede querer la factura por correo y no querer WhatsApp.
Nunca dos veces el mismo aviso
Cada envío lleva una clave de deduplicación única por espacio. Un reintento de tu job o un doble clic devuelven el mismo envío, sin segunda fila ni segundo WhatsApp a las tres de la mañana.
Reintentos que saben cuándo parar
Un 5xx o la red caída reintentan solos con espera creciente. Un número inválido o una plantilla sin aprobar no: se marcan fallidos con el motivo, porque eso sólo lo arregla una persona.
Redactar, enviar y ver datos son tres permisos
El redactor escribe plantillas pero no dispara campañas a diez mil personas. Atención manda un mensaje suelto sin ver la libreta entera. El lector ve el registro y ningún dato personal.
Campañas a un segmento
Eliges la plantilla, filtras la libreta y el módulo encola un envío por contacto, saltando a quien se dio de baja. Cada uno con su estado y su error, no un «se mandó» global.
Una etiqueta, un archivo
El tablero entero —plantillas, libreta, envíos y ajustes— se embebe con una etiqueta HTML. Sin build, sin framework, aislado en Shadow DOM, con tus colores heredados por variables CSS.
El tablero, con una etiqueta. Los envíos, con una llamada.
El token lo emite tu backend con tu llave secreta y dura quince minutos. La llave nunca llega al navegador, y las credenciales de Meta y Twilio nunca salen del servidor.
El tablero embebido
<script src="https://nexusnorth.dev/embed/v1/nexus-notificaciones.js" defer></script>
<nexus-notificaciones
tenant-id="tu-tenant"
workspace-id="tu-espacio"
auth-token="token-efimero-de-tu-backend"
style="--nexus-primary: #4f46e5; --nexus-radius: 0.75rem"
></nexus-notificaciones>Un envío desde tu backend
POST /api/v1/notificaciones/messages
Authorization: Bearer <token>
{
"contact_id": "c_8f3a…",
"template_key": "cita.recordatorio",
"vars": { "nombre": "Laura", "fecha": "jueves 26", "hora": "11:30" },
"dedupe_key": "cita:4412:recordatorio-24h"
}- Tu módulo no aprende a hablar con Meta ni con Twilio: manda contacto, plantilla y variables, y ya.
- El canal se elige al encolar: el que pidas, si no el de la plantilla, y sólo si el contacto tiene dirección, hay credencial y no se dio de baja.
- La misma clave de deduplicación devuelve el mismo envío. Puedes reintentar tu llamada sin miedo.
- Sin cookies de terceros: el token viaja en memoria, no en el navegador.
- Aislado en Shadow DOM: tus estilos no lo tocan y los suyos no te tocan.
- Un solo archivo, sin dependencias que choquen con las tuyas.
Lo que suelen preguntar antes de integrarlo
¿Manda desde mi número de WhatsApp o desde el de ustedes?
Desde el tuyo. Cada espacio de trabajo guarda sus propias credenciales de Meta, Twilio y correo, cifradas. Tus clientes ven tu nombre y tu número, no una marca ajena. Si todavía no tienes cuenta de Meta Business, te decimos cómo darla de alta.
¿Qué pasa si edito una plantilla que ya se usó?
Nada con lo ya mandado. Cada envío guarda el cuerpo tal como salió y la versión de la plantilla con la que se armó. La edición sube la versión y aplica a los envíos que vengan. Así «qué le dijimos a este cliente» siempre tiene respuesta.
¿Cómo evitan mandar a alguien que se dio de baja?
La baja se guarda por contacto y canal con fecha y motivo, y la comprueba la base de datos dentro de la función que encola: ninguna ruta puede saltársela. Si el destinatario contesta STOP por SMS, el proveedor lo avisa y la baja se anota sola. Volver a dar de alta sí pide una acción explícita.
¿Si falla WhatsApp, lo reintenta por correo?
No automáticamente, y es a propósito. El texto aprobado para WhatsApp no es el HTML del correo, y el consentimiento también es por canal. Reintentar por otro lado es un envío nuevo con otra plantilla, y alguien lo decide desde el registro con un clic.
¿Cómo sé si de verdad llegó?
Con los webhooks de Meta y Twilio: pasan el envío de «enviado» a «entregado» y a «leído». Sin webhook configurado, el envío se queda honestamente en «enviado», que es lo único que se sabe. El correo reporta entregado y rebotado.
¿Puede mi equipo redactar sin poder mandar campañas?
Sí. Redactar plantillas, ver contactos, mandar un mensaje suelto y disparar una campaña son permisos separados. El redactor escribe y mantiene la libreta; atención contesta a un cliente concreto sin ver la lista completa; sólo el dueño y el administrador lanzan campañas.
¿Dónde viven los datos de mis contactos?
En nuestra instancia por omisión, con aislamiento por espacio impuesto en la base. Si lo prefieres, pueden vivir en la tuya: el módulo apunta a donde le digas. Son datos personales de terceros y los tratamos como tales.
¿Tu producto necesita avisar a sus clientes?
Cuéntanos qué mandas hoy y por dónde, y te decimos si este módulo encaja — o si lo tuyo necesita otra cosa.
Hablemos