Webhook multicanal
Cada respuesta, en cada canal,
en un solo webhook.
WhatsApp desde tu número, email desde tu buzón, SMS desde tu móvil: un solo endpoint los recibe todos en el mismo sobre JSON firmado. Un handler alimenta tu bandeja, tu agente de IA o tu CRM.
¿Con prisa? Resume este artículo con una IA
La respuesta corta
¿Puede un solo webhook recibir WhatsApp, email y SMS?
Sí. Unlimited Messaging envía cada mensaje entrante de tu número de WhatsApp vinculado, tu buzón conectado y la SIM de tu móvil Android a una sola URL, como el mismo evento, message.received, firmado según Standard Webhooks. El sobre nunca cambia; data.channel.type indica WHATSAPP, EMAIL o SMS. Los webhooks están en los planes de pago Medium y Max.
Montada con proveedores separados, la misma bandeja exige tres integraciones. La Cloud API de Meta envía JSON anidado firmado con X-Hub-Signature-256 tras una verificación hub.challenge. Twilio envía SMS y WhatsApp como parámetros form-encoded firmados con HMAC-SHA1. SendGrid Inbound Parse envía multipart/form-data para un nombre de host cuyo MX has movido. Tres parsers, tres verificaciones de firma, tres ideas distintas de lo que es una conversación.
Aquí los canales son servicios junto a una sola API, y esa API anuncia cada mensaje igual: id, direction, content, sender, sentAt, la conversación (un chat o grupo de WhatsApp, la raíz de un hilo de email, un número SMS) y la cuenta por la que llegó. El email añade subject, html y attachments; WhatsApp añade archivos, grupos, reacciones y ediciones. Las reglas de entrega también son comunes: responder 2xx en menos de 10 segundos, 8 intentos en algo más de 3 días, deduplicar por eventId.
Las respuestas salen desde las mismas identidades. replyToMessageId responde en el mismo chat de WhatsApp o hilo de email; una respuesta SMS indica la SIM. Tus clientes ven tu número y tu dirección, nunca los de un proveedor.
Relacionado: enviar email y WhatsApp en una sola petición a la API y reunir las ventas por WhatsApp y email en una sola bandeja.

Los eventos
¿Cómo es el payload del webhook multicanal?
El mismo evento message.received en cada canal. Lo que cambia es data.channel.type y algunos campos propios del canal.
Común a todos los canales
type, eventId, occurredAt; data.message con id, externalId, direction, fromMe, content, sentAt, receivedAt, sender, senderId; data.channel con type, account (id, name) y conversation (id, isGroup, address).
WHATSAPP
Archivos (mediaUrl, mediaType, mimeType), ubicaciones, respuestas citadas (replyTo), grupos (participant, conversation.participants), más message.reaction, message.edited y message.deleted.
EMAIL
subject, html (no fiable, hay que sanearlo), attachments (hasta 20 por email), conversation.id igual a la raíz del hilo y replyTo al mensaje respondido.
SMS
Solo texto. conversation.id es null, así que agrupa por sender. Mensajes recibidos después de iniciar sesión en la app Android.
Alrededor de los mensajes
message.sent y message.status siguen lo que envías en los tres canales; account.status_changed avisa de un número, buzón o SIM que se cae.
// WhatsApp
{ "type": "message.received", "eventId": "whd_6f1c...", "occurredAt": "2026-11-09T10:00:01.000Z",
"data": {
"message": { "id": "msg_0e55...", "direction": "IN", "content": "Is my order ready?",
"sender": "+447700900123", "senderName": "Lea", "sentAt": "2026-11-09T10:00:00.000Z" },
"channel": { "type": "WHATSAPP", "account": { "id": "acc_373b...", "name": "Support" },
"conversation": { "id": "[email protected]", "isGroup": false,
"address": "+447700900123" } } } }
// Email: same envelope, plus subject, html and attachments
{ "type": "message.received", "eventId": "whd_9a4f...", "occurredAt": "2026-11-09T14:05:12.000Z",
"data": {
"message": { "id": "msg_3f8a...", "direction": "IN", "content": "Signed quote attached.",
"sender": "[email protected]", "subject": "Re: Quote #1042",
"html": "<p>Signed quote attached.</p>", "attachments": [ { "filename": "quote.pdf" } ] },
"channel": { "type": "EMAIL", "account": { "id": "acc_8b2e...", "name": "[email protected]" },
"conversation": { "id": "[email protected]", "isGroup": false,
"address": "[email protected]" } } } }
// SMS: text only, no conversation id
{ "type": "message.received", "eventId": "whd_2b9e...", "occurredAt": "2026-11-09T08:42:06.000Z",
"data": {
"message": { "id": "msg_7d2c...", "direction": "IN", "content": "Running 10 min late, sorry!",
"sender": "+447700900456", "sentAt": "2026-11-09T08:42:03.000Z" },
"channel": { "type": "SMS", "account": { "id": "acc_5e8d...", "name": "Front desk SIM" },
"conversation": { "id": null, "isGroup": false, "address": "+447700900456" } } } }Puesta en marcha
¿Cómo escribir un solo handler para todos los canales?
Vincula los tres canales una vez, registra un endpoint y diferencia solo donde un canal cambia de verdad.
- 01
Vincula tus canales
Escanea un código QR para WhatsApp, conecta tu buzón por IMAP/SMTP, instala la app Android para el SMS. Cada uno se convierte en una cuenta.
- 02
Registra un solo endpoint
POST /webhooks con tu URL y tus eventTypes, o añádelo en la página Webhooks del panel. Sin accountIds cubre todas las cuentas, incluso las futuras.
- 03
Verifica una vez, diferencia al final
Una verificación de firma, un upsert por eventId, una fila en la bandeja. Solo cambia la llamada de respuesta: replyToMessageId para WhatsApp y email, la SIM para el SMS.
curl https://api.unlimitedmessaging.app/webhooks \
-H "Authorization: Bearer $UM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/um",
"eventTypes": ["message.received", "message.status", "account.status_changed"],
"description": "Every reply, every channel"
}'
# No accountIds: the endpoint covers every WhatsApp number, mailbox and SIM you have,
# including ones linked later. The response carries "secret": "whsec_..." once.// app/api/webhooks/um/route.ts (Next.js App Router)
import crypto from 'node:crypto';
import { UnlimitedMessagingApiClient } from '@unlimited-messaging/sdk';
const um = new UnlimitedMessagingApiClient({ token: process.env.UM_API_KEY! });
const key = Buffer.from(process.env.UM_WEBHOOK_SECRET!.replace(/^whsec_/, ''), 'base64');
// Standard Webhooks: HMAC-SHA256 of "id.timestamp.rawBody", base64.
function verify(raw: string, id: string, ts: string, header: string) {
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = crypto.createHmac('sha256', key).update(`${id}.${ts}.${raw}`).digest('base64');
return header.split(' ').some((entry) => {
const sig = entry.startsWith('v1,') ? entry.slice(3) : '';
return sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
});
}
export async function POST(req: Request) {
const raw = await req.text();
const h = req.headers;
if (!verify(raw, h.get('webhook-id') ?? '', h.get('webhook-timestamp') ?? '',
h.get('webhook-signature') ?? '')) {
return new Response('bad signature', { status: 401 });
}
const event = JSON.parse(raw);
if (event.type !== 'message.received') return new Response(null, { status: 200 });
const { message: m, channel } = event.data;
// One inbox row, whatever the channel (upsert on eventId: delivery is at least once).
await inbox.upsert({
eventId: event.eventId,
channel: channel.type, // WHATSAPP | EMAIL | SMS
from: m.sender ?? m.senderId, // +E164 or email address
thread: channel.conversation.id ?? m.sender, // SMS has no conversation id
subject: m.subject ?? null,
text: m.content,
at: m.sentAt, // order on this, not on arrival
});
const answer = await draftReply(m.content); // your LLM call, or null for a human
if (answer) {
if (channel.type === 'SMS') {
await um.messages.messageSend({
to: { phone: m.sender },
channels: [{ channel: 'SMS', accountId: channel.account.id }],
text: answer,
});
} else {
// WhatsApp and email: same chat or same thread, same number or mailbox.
await um.messages.messageSend({ replyToMessageId: m.id, text: answer });
}
}
return new Response(null, { status: 200 }); // within 10 s; queue slow work
}Vibe coding
¿Programas con Cursor, Claude Code, Lovable o Bolt? Pega esto
Contexto suficiente para que tu editor con IA construya toda la ruta de la bandeja unificada de una vez.
Add a unified inbox to this app with Unlimited Messaging: WhatsApp (my number), email (my mailbox) and SMS (my Android phone) all arrive on ONE webhook.
1. Create a POST route at /api/webhooks/um that reads the RAW body.
2. Verify the Standard Webhooks signature: key = base64-decode(UM_WEBHOOK_SECRET without "whsec_"); expected = base64(HMAC-SHA256(key, `${webhook-id}.${webhook-timestamp}.${rawBody}`)); accept if any space-separated entry of the webhook-signature header equals `v1,${expected}` (constant-time compare); reject timestamps more than 5 minutes off; return 401 otherwise.
3. On type "message.received", upsert one row keyed on body.eventId: channel = data.channel.type (WHATSAPP | EMAIL | SMS), from = data.message.sender ?? data.message.senderId, thread = data.channel.conversation.id ?? data.message.sender, subject = data.message.subject, text = data.message.content, at = data.message.sentAt (order on this, never on arrival).
4. Build an inbox page listing threads across channels with a channel badge.
5. Replies: install @unlimited-messaging/sdk, read UM_API_KEY from env. WhatsApp and email: `client.messages.messageSend({ replyToMessageId: data.message.id, text })`. SMS: `client.messages.messageSend({ to: { phone: sender }, channels: [{ channel: 'SMS', accountId: data.channel.account.id }], text })`.
6. Return 200 within 10 seconds; queue slow work. Put UM_API_KEY and UM_WEBHOOK_SECRET in .env and .env.example.
Docs: https://docs.unlimitedmessaging.app (Webhooks). Register with POST https://api.unlimitedmessaging.app/webhooks and eventTypes ["message.received", "message.status", "account.status_changed"].Lo que se construye
¿Qué puedes construir con un solo webhook para todos los canales?
Tres proyectos que en otros sitios son tres integraciones y aquí un solo handler.
Una bandeja de soporte multicanal
Una lista de conversaciones, una etiqueta por canal, respuestas enviadas desde tu número o tu dirección en el mismo hilo. Añade message.status para mostrar entregado y leído cuando el canal lo informa.
Un contestador con IA
Pasa content a Claude o GPT con el historial de la conversación, devuelve la respuesta por el canal de origen y pasa a una persona ante palabras clave o dudas.
Sincronización con el CRM
Asocia cada mensaje al contacto por teléfono o dirección de email, sea cual sea el canal, con sentAt para la cronología.
Cambio de canal
¿Sin respuesta en WhatsApp tras un día? Insiste por email o SMS; el mismo POST /message puede enviar por tres canales a la vez.
Supervisión
account.status_changed en los tres canales te avisa cuando un número, un buzón o un móvil deja de reenviar.
Flujos sin código
Apunta el webhook a n8n, Make o Zapier y ramifica por data.channel.type.
La tabla
Una bandeja, tres caminos: Twilio, una pila propia o Unlimited Messaging
Lo que hace falta para recibir respuestas de WhatsApp, email y SMS en el mismo código.
| Twilio + SendGridUn proveedor, varios productos | Meta + servicio de parsing + proveedor SMSHecho a mano | Unlimited MessagingUn webhook, planes de pago | |
|---|---|---|---|
| Formatos de payload | Form-encoded para SMS y WhatsApp, multipart para email | JSON de Meta, formato del proveedor, multipart o JSON para email | Un solo sobre JSON |
| Verificaciones de firma | X-Twilio-Signature (HMAC-SHA1), más la protección propia del endpoint de parsing | X-Hub-Signature-256 para Meta, una por cada otro proveedor | Una sola verificación Standard Webhooks |
| Identidades que ven tus clientes | Números alquilados a Twilio, un remitente de WhatsApp registrado | Un número trasladado a la Cloud API, un número SMS alquilado | Tu propio número, buzón y SIM |
| Configuración antes del primer mensaje | Compra de número, registro del remitente de WhatsApp, MX | App de Meta y portfolio comercial, MX, alquiler de número | Escanear un QR, contraseña del buzón, app Android |
| Coste por mensaje | 0,0083 $ por segmento SMS recibido en EE. UU., 0,005 $ por mensaje de WhatsApp más tarifas de Meta | Tarifas de Meta a partir de 1.000 respuestas de servicio por número al mes, coste por SMS | Ninguno; webhooks con Medium o Max |
| Estatus oficial | WhatsApp Business Platform oficial | WhatsApp Business Platform oficial | WhatsApp mediante el protocolo no oficial de dispositivos vinculados |
Comprobado el 9 de noviembre de 2026 en las páginas de Twilio (webhooks, precios de SMS y WhatsApp), la documentación de Meta (webhooks, precios) y la guía de Inbound Parse de SendGrid (enlaces en las fuentes).
La letra pequeña
¿Qué límites tiene un webhook unificado sobre tus propios canales?
Un solo formato elimina el código de pegamento. Cada canal conserva su naturaleza.
Los webhooks son de pago
Enviar por los tres canales es gratis en todos los planes, y los mensajes recibidos aparecen en la bandeja de la aplicación web. Enviarlos a tu servidor requiere Medium (19 € al mes, o 17 € al mes con pago anual) o Max.
WhatsApp es un dispositivo vinculado
El número se vincula como WhatsApp Web, con un protocolo no oficial: el spam hace que lo restrinjan, y WhatsApp cierra la sesión de los dispositivos vinculados si el móvil principal pasa 14 días sin conexión.
El SMS necesita un móvil Android
La SIM reenvía a través de la app Android gratis (8.0 o posterior), que debe seguir encendida y conectada. Solo texto, y solo los SMS recibidos después de iniciar sesión.
El email lee la bandeja de entrada
Por ahora solo buzones IMAP (Gmail con contraseña de aplicación, tu dominio, la mayoría de proveedores); todavía sin Outlook ni Microsoft 365. El correo que va a spam o a otras carpetas no se ve.
No todos los campos existen en todos los canales
El SMS no tiene identificador de conversación ni acuse de lectura, el email no tiene reacciones, WhatsApp no tiene asunto. Programa sobre los campos comunes y trata el resto como opcional.
FAQ
Preguntas sobre el webhook multicanal
Fuentes
Fuentes y referencias
Para verificar por ti mismo la información de este artículo:
- Especificación Standard Webhooksstandardwebhooks.com
- Getting started with webhooks (hub.challenge, X-Hub-Signature-256)Meta for Developers
- Precios de la WhatsApp Business PlatformMeta for Developers
- Incoming message webhook request (form-encoded)Twilio Docs
- Webhooks security (X-Twilio-Signature, HMAC-SHA1)Twilio Docs
- Precios de SMS en Estados UnidosTwilio
- Precios de WhatsApp (0,005 $ por mensaje, entrante o saliente)Twilio
- Setting up the Inbound Parse webhook (MX, multipart/form-data)Twilio SendGrid Docs
- Acerca de los dispositivos vinculados (cierre de sesión tras 14 días sin el móvil principal)Servicio de ayuda de WhatsApp
- Referencia de la API de Unlimited Messaging - WebhooksUnlimited Messaging

Escrito por
Ilian · Ingeniero de software senior
Ingeniero de software senior, funda y dirige varias empresas tecnológicas. Diseña productos en torno a las API de mensajería, la automatización y la integración de la IA, y comparte aquí lo que aprende construyendo.
Tres canales, un solo handler.
Crea una cuenta, vincula tu WhatsApp, tu buzón y tu móvil Android, y activa los webhooks con Medium o Max. Enviar sigue siendo gratis en todos los planes.