Typebot en WhatsApp por la API oficial, con ZapClaw
En resumen: ZapClaw entrega cada mensaje de WhatsApp a un pequeño script intermediario (el relay), que ejecuta tu Typebot publicado por la Chat API de Typebot, y las respuestas del bot vuelven por ZapClaw. Los mensajes pasan por la Cloud API oficial de Meta, y el número sigue funcionando en la app de WhatsApp Business de tu celular. Mantienes el bot que ya construiste y no necesitas una app de Meta propia.
Conecta tu número en minutos y pon en él el bot que ya construiste, alojado por Typebot o self-hosted.
Plan Business: US$ 29 al mes, con números ilimitados
Empieza gratis Ver el relayLo que necesitas para conectar
- La app de WhatsApp Business en el número, en la versión 2.24.17 o posterior, con uso habitual.
- Autenticación en dos pasos activada en la cuenta personal de Facebook que autoriza la conexión.
- El número fuera de cualquier otro proveedor. Si está conectado a otra plataforma, desconéctalo allí primero.
- Una computadora para hacer la conexión, con tu celular a la mano para confirmarla en la app.
No necesitas una empresa registrada ni un negocio verificado para conectar. La lista completa.
Por qué ZapClaw para un Typebot en WhatsApp
- El número sigue en la app de WhatsApp Business. Con la Coexistencia, tu equipo sigue respondiendo en la app mientras el bot trabaja con el mismo número. La integración de WhatsApp del propio Typebot te pide traer tu propia app de Meta, y su documentación (en inglés) dice que un número que ya se usa en la app de WhatsApp Business no se puede usar con ella.
- Sin una app de Meta propia. Conectas el número en la ventana de Embedded Signup de Meta, desde el panel de ZapClaw, y ZapClaw se encarga del lado de la Cloud API.
- El bot que ya construiste. El relay ejecuta tu bot publicado por la Chat API de Typebot, así que sigues construyendo y publicando en Typebot como siempre.
- Ninguna librería no oficial detrás de tu bot. Las integraciones que imitan WhatsApp Web van contra las condiciones de WhatsApp y ponen el número en riesgo. ZapClaw usa la Cloud API de Meta, y las políticas de Meta se aplican como a cualquier empresa en ella.
- Entregas que puedes comprobar. Cada evento va firmado con HMAC-SHA256 y tiene hasta 3 intentos de entrega si el relay no responde, y un evento fallido se puede reenviar desde el panel.
Por qué hay un relay en medio
Typebot no puede recibir el webhook de ZapClaw tal como llega. Su bloque Webhook solo reanuda una conversación que ya está en pausa en él, y su Chat API espera una llamada por mensaje, con una sesión guardada para cada persona.
Así que el relay se encarga de eso como lo describe la guía de Typebot para apps de mensajería (en inglés): abre una sesión con el primer mensaje del cliente, la continúa con los siguientes y devuelve las burbujas de texto del bot por ZapClaw. Son menos de 100 líneas de Node.js, sin nada que instalar.
Configúralo en cuatro pasos
- En Typebot, publica tu bot y copia su ID público (dónde encontrarlo). Mantén el flujo centrado en texto: burbujas de texto, campos de texto y botones.
- En ZapClaw, conecta tu número, crea una clave de API y copia la Clave de firma en la página Webhook.
- Ejecuta el relay de abajo con esos tres valores en un servidor con una dirección HTTPS pública, y pega esa dirección en Webhook en ZapClaw. ZapClaw solo entrega en una dirección HTTPS pública.
- Haz clic en Enviar evento de prueba en ZapClaw: el relay responde
200y no inicia nada. Luego envía un mensaje de WhatsApp a tu número desde otro celular: el bot responde.
El relay, listo para ejecutar
Guárdalo como relay.mjs e inícialo con node relay.mjs en Node.js 18 o posterior. Lee su configuración del entorno: ZAPCLAW_API_KEY, ZAPCLAW_SECRET (la clave de firma), TYPEBOT_PUBLIC_ID, TYPEBOT_API para un Typebot self-hosted, y PORT, el puerto en el que escucha el relay (8787 por defecto), al que tu proxy HTTPS reenvía.
// relay.mjs: ZapClaw webhook in, Typebot Chat API, replies out through ZapClaw.
// Node.js 18 or newer, nothing to install. Start it with: node relay.mjs
import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';
const ZAPCLAW_API_KEY = process.env.ZAPCLAW_API_KEY; // zc_live_...
const ZAPCLAW_SECRET = process.env.ZAPCLAW_SECRET; // the webhook signing secret
const TYPEBOT_PUBLIC_ID = process.env.TYPEBOT_PUBLIC_ID; // your published bot
const TYPEBOT_API = process.env.TYPEBOT_API || 'https://typebot.co/api';
const sessions = new Map(); // customer: { id, choices }. Use your database in production.
const queues = new Map(); // one message at a time per customer, in order
const isSigned = (raw, header = '') => {
const hmac = createHmac('sha256', ZAPCLAW_SECRET).update(raw).digest('hex');
const expected = Buffer.from(`sha256=${hmac}`);
const given = Buffer.from(String(header));
return given.length === expected.length && timingSafeEqual(given, expected);
};
const typebot = async (path, body) => {
const res = await fetch(`${TYPEBOT_API}/v1/${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...body, textBubbleContentFormat: 'markdown' }),
});
return res.ok ? res.json() : null;
};
const sendText = (from, to, text) =>
fetch('https://api.zapclaw.app/api/v1/send/text', {
method: 'POST',
headers: { 'X-API-Key': ZAPCLAW_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ from, to, text }),
});
const answer = async ({ data, account }) => {
const customer = data.user_id || data.from;
const from = account.display_phone_number || account.phone_number_id;
const to = data.from || data.user_id;
const session = sessions.get(customer);
let reply = null;
if (session) {
// Typebot takes a button by its exact label, so accept its number or any letter case.
const typed = data.text.body.trim();
const choice = session.choices.find(
(label, i) => typed === String(i + 1) || typed.toLowerCase() === label.toLowerCase()
);
reply = await typebot(`sessions/${session.id}/continueChat`, {
message: { type: 'text', text: choice || typed },
});
}
if (!reply) {
// First message, or a session that expired (continueChat answers 404): start the bot.
reply = await typebot(`typebots/${TYPEBOT_PUBLIC_ID}/startChat`, {
prefilledVariables: { name: data.contact_name, phone: to },
});
if (!reply) return;
}
const choices =
reply.input?.type === 'choice input'
? reply.input.items.map((item) => item.content).filter(Boolean)
: [];
if (reply.input) sessions.set(customer, { id: reply.sessionId || session.id, choices });
else sessions.delete(customer); // the flow ended: the next message starts it again
const texts = (reply.messages || [])
.filter((m) => m.type === 'text')
// Typebot writes standard Markdown; WhatsApp reads *bold*, ~strike~ and bare links.
.map((m) => m.content.markdown
.replace(/\*\*(.+?)\*\*/g, (_, t) => `*${t}*`)
.replace(/~~(.+?)~~/g, (_, t) => `~${t}~`)
.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (_, label, url) => `${label} (${url})`));
if (choices.length) texts.push(choices.map((label, i) => `${i + 1}. ${label}`).join('\n'));
for (const text of texts) if (text) await sendText(from, to, text);
};
createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => chunks.push(chunk));
req.on('end', () => {
const raw = Buffer.concat(chunks);
if (!isSigned(raw, req.headers['x-zapclaw-signature'])) return res.writeHead(401).end();
res.writeHead(200).end(); // answer ZapClaw now: it waits 10 seconds, a bot can take longer
let event;
try {
event = JSON.parse(raw.toString('utf8'));
} catch {
return;
}
if (event.event !== 'message.received' || event.data?.type !== 'text') return;
const key = event.data.user_id || event.data.from;
const next = (queues.get(key) || Promise.resolve())
.then(() => answer(event))
.catch((err) => console.error(err));
queues.set(key, next);
});
}).listen(process.env.PORT || 8787);
En un Typebot self-hosted, apunta TYPEBOT_API a la dirección de tu viewer, la app donde las personas responden a tus bots, seguida de /api.
Lo que hace: comprueba el encabezado X-ZapClaw-Signature, responde a ZapClaw de inmediato (ZapClaw espera 10 segundos, y un bot que llama a una IA puede tardar más) y atiende los mensajes de cada cliente de uno en uno, en orden. Las opciones de un bloque Buttons salen como una lista numerada, y el cliente responde con el número o con el texto de la opción, en mayúsculas o minúsculas. Cuando el flujo termina, el siguiente mensaje lo vuelve a empezar.
Crea variables llamadas name y phone en tu bot y el relay las llena con el primer mensaje, con el nombre del contacto en WhatsApp y su número. Las sesiones viven en la memoria del relay, así que reiniciarlo vuelve a empezar todas las conversaciones: en producción, guárdalas en tu base de datos, como recomienda la guía de Typebot.
El relay envía las burbujas de texto. Una burbuja de imagen trae su dirección en content.url, que puedes enviar con POST /api/v1/send/media.
Llamar a ZapClaw desde dentro del bot
El bloque HTTP Request de Typebot también puede llamar a la API de ZapClaw, con un encabezado X-API-Key y un cuerpo personalizado armado con tus variables: por ejemplo, para avisar a un vendedor por WhatsApp cuando un lead llega al final del bot. La misma llamada como comando curl:
curl -X POST https://api.zapclaw.app/api/v1/send/text \
-H "X-API-Key: zc_live_..." \
-H "Content-Type: application/json" \
-d '{ "from": "15551617409", "to": "15555550100", "text": "New lead from the bot" }'
from es tu número conectado, que el webhook trae en account.display_phone_number, y to es la persona a quien escribes. Un mensaje enviado responde 201. El texto libre funciona dentro de las 24 horas siguientes al último mensaje de esa persona a tu número; fuera de esa ventana, Meta solo acepta una plantilla aprobada, con POST /api/v1/send/template.
Lo que llega al relay
Cada mensaje llega como un evento message.received: el texto en data.text.body, el remitente en data.from (o data.user_id para un contacto que solo muestra su nombre de usuario), el nombre del contacto en data.contact_name y tu número en account.display_phone_number.
{
"event": "message.received",
"sequence": 1042,
"timestamp": "2026-10-15T14:00:00.000Z",
"data": {
"from": "15555550100",
"user_id": "US.1A2B3C4D5E6F7G8H9I0J",
"contact_name": "Maria Silva",
"message_id": "wamid.HBg...",
"type": "text",
"timestamp": "1792072800",
"text": { "body": "Hi" }
},
"account": {
"phone_number_id": "964283400112599",
"display_name": "My Business",
"display_phone_number": "+1 555 161-7409"
}
}
El relay solo pasa los mensajes de texto entrantes: el evento de prueba del panel y cualquier otro evento reciben un 200 y nada más. Todos los eventos y campos están en la documentación (en inglés).
Cuánto cuesta
- Gratis: 500 mensajes al mes y 1 número, sin tarjeta y sin fecha de vencimiento. Al llegar al límite, el envío se pausa y los mensajes nuevos quedan retenidos hasta que te suscribas.
- Business: US$ 29 al mes, con 20,000 mensajes incluidos y números ilimitados.
- Agency: US$ 49 al mes para agencias, con 3 clientes y 60,000 mensajes incluidos y números ilimitados.
Meta te cobra directamente las tarifas de mensajes de WhatsApp, sin margen de ZapClaw. Todos los planes y precios.
Para quién es
Equipos que construyeron en Typebot flujos de captación de leads, calificación, preguntas frecuentes o reservas y quieren llevarlos al número de WhatsApp que sus clientes ya usan. Las agencias conectan los números de sus clientes en el plan Agency, cada cliente aislado de los demás. No sirve para envíos masivos.
Para ir más allá
- Flowise en WhatsApp, cuando las respuestas deben venir de un agente de IA y no de un flujo guionizado.
- WhatsApp en n8n, con un flujo que importas en lugar de un script.
- La API oficial de WhatsApp con ZapClaw: lo que recibes, el precio y los requisitos.
- La referencia del webhook (en inglés), con cada evento y campo.
Fuentes
Documentación de Typebot, en inglés, consultada el 15 de octubre de 2026. Las funciones cambian, así que revisa cada fuente antes de construir.
- Typebot, integración con apps de mensajería externas por la API HTTP: el patrón del relay, una sesión por persona y el 404 de una sesión vencida.
- Referencia de la API de Typebot, Start chat y Continue chat: los campos de la solicitud y de la respuesta.
- Typebot, bloque Webhook y bloque HTTP Request.
- Typebot, WhatsApp: su propia integración, la app de Meta que pide y el número de la app de WhatsApp Business.
- Typebot, variables (variables precargadas) y configuración self-hosted (la dirección del viewer).
- Código fuente de Typebot en GitHub: cómo se reconoce la respuesta a un bloque Buttons.
- ZapClaw: webhooks y verificación de la firma en la documentación, y lo que necesitas para conectar.
Pon tu Typebot en WhatsApp hoy
Empieza en el plan gratuito: un número, sin tarjeta. Pasa al plan Business cuando necesites más números o más mensajes.
Empieza gratis Ver la documentación del webhook (en inglés)