Cómo crear un chatbot de IA con la API de OpenAI para responder en WhatsApp
Un webhook, una llamada a la API de OpenAI y una respuesta por la API de WhatsApp: el código completo de un chatbot que atiende en WhatsApp, Instagram y Messenger. Con memoria por contacto, control de costo y salida al humano.
Un chatbot de IA en WhatsApp son tres piezas: recibir el mensaje, preguntarle al modelo, devolver la respuesta. Ninguna es difícil — lo que suele costar es el medio de campo: el formato del webhook, la memoria de la conversación y saber cuándo la IA no debe responder.
Este artículo muestra el código completo, en Node.js, y resuelve las tres cosas.
Lo que necesitas
- Una instancia en la API — la no oficial conecta por código QR en segundos y sirve para probar.
- Una clave de la API de OpenAI.
- Una URL pública para el webhook. En desarrollo,
ngroko similar.
Pieza 1: recibir el mensaje
Apunta el webhook de tu instancia (formato meta) a tu URL. Todo evento llega en el sobre estándar de la Cloud API, y el campo provider dice el canal:
{
"object": "wame",
"provider": "whatsapp",
"entry": [{
"id": "<instance-id>",
"changes": [{
"field": "messages",
"value": {
"messages": [{
"from": "525512345678",
"id": "wamid.XXXX",
"type": "text",
"text": { "body": "¿hacen envíos a Guadalajara?" }
}]
}
}]
}]
}
Esto importa más de lo que parece: como los tres canales llegan en el mismo sobre, el bot que escribas para WhatsApp ya atiende Instagram y Messenger. Es el estándar único de webhook de la plataforma.
El extractor, con las guardas que evitan el 90% de los bugs:
function extraer(body) {
const msg = body?.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
// Los estados de entrega ("delivered", "read") también llegan acá.
// Sin esta guarda, el bot se responde a sí mismo en bucle.
if (!msg || msg.type !== 'text') return null;
return {
de: msg.from,
texto: msg.text.body,
canal: body.provider,
messageId: msg.id,
};
}
Pieza 2: preguntarle al modelo
La API de OpenAI no guarda estado. Cada llamada es independiente, así que la memoria es tuya:
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// En producción usa Redis o base de datos. En memoria se pierde al reiniciar.
const historial = new Map();
const SYSTEM = `Eres el agente de atención de Tienda Ejemplo, en WhatsApp.
Reglas:
- Responde en español neutro, en máximo 3 frases cortas.
- Nunca inventes plazos, precios ni disponibilidad.
- Si la pregunta exige un dato que no tienes, responde exactamente
con el texto [HUMANO] y nada más.`;
async function responder(de, texto) {
const anterior = historial.get(de) ?? [];
// Últimos 10 mensajes: suficiente para el contexto y
// bastante para que el costo no crezca sin límite.
const mensajes = [
{ role: 'system', content: SYSTEM },
...anterior.slice(-10),
{ role: 'user', content: texto },
];
const r = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: mensajes,
max_tokens: 300,
temperature: 0.3,
});
const respuesta = r.choices[0].message.content.trim();
historial.set(de, [
...anterior.slice(-10),
{ role: 'user', content: texto },
{ role: 'assistant', content: respuesta },
]);
return respuesta;
}
Tres decisiones de ese código merecen explicación:
temperature: 0.3 — la atención al cliente no quiere creatividad. Temperatura baja hace la respuesta más previsible y reduce la invención.
max_tokens: 300 — WhatsApp no es lugar para párrafos largos. Además de mejorar la lectura, limita el costo por respuesta.
slice(-10) — el costo de OpenAI es por token, y el historial entero viaja en cada llamada. Sin recorte, una conversación larga se vuelve progresivamente más cara.
Pieza 3: devolver por WhatsApp
async function enviar(para, texto, canal) {
await fetch(`https://us.api-wa.me/${process.env.WAME_KEY}/message/text`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: para, text: texto, channel: canal }),
});
}
Todo junto
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhook/wame', async (req, res) => {
// Responde 200 DE INMEDIATO. OpenAI tarda segundos, y un webhook
// que demora se reenvía — el cliente recibiría la misma respuesta
// dos o tres veces.
res.sendStatus(200);
const msg = extraer(req.body);
if (!msg) return;
try {
const respuesta = await responder(msg.de, msg.texto);
if (respuesta.includes('[HUMANO]')) {
await enviar(msg.de, 'Un momento, te comunico con alguien del equipo.', msg.canal);
await avisarAgente(msg); // tu cola, tu CRM
return;
}
await enviar(msg.de, respuesta, msg.canal);
} catch (e) {
console.error('falló la respuesta a', msg.de, e);
await enviar(msg.de, 'Tuve un problema. Ya te paso con una persona.', msg.canal);
await avisarAgente(msg);
}
});
app.listen(3000);
Listo — unas 60 líneas para un bot de IA que atiende en los tres canales.
El detalle que separa demo de producción
Responder 200 antes de procesar. Es la línea más importante del archivo. La llamada a OpenAI tarda de 1 a 5 segundos; si tu handler la espera antes de contestar al webhook, la entrega se considera fallida y se reenvía. El resultado es el cliente recibiendo la misma respuesta tres veces — y tú pagándola tres veces.
Tener una salida al humano. El [HUMANO] del system prompt existe para eso. Un bot que responde "no sé" es malo; uno que inventa el plazo de entrega es peor, porque se convierte en reclamo. Cómo funciona el otro lado —cola, asignación y el bot saliendo de escena— está en varios agentes en el mismo número.
Tratar el error como camino normal. OpenAI va a fallar en algún momento: timeout, límite, indisponibilidad. El catch no deja al cliente en el vacío.
No responderse a sí mismo. La guarda en extraer se encarga: los estados de entrega y lectura también llegan al webhook.
¿Y si el webhook no llega?
Pasa, y casi siempre es una de las mismas causas. Antes de tocar el código, apunta el webhook a una URL de webhook.site y envía un mensaje: si el evento aparece ahí, el problema es tu servidor; si no aparece, es la configuración de la instancia. Esa prueba de 30 segundos separa los dos mundos. La guía completa está en el webhook no llega: las 7 causas.
Conclusión
El chatbot en sí es la parte fácil. Lo que decide si se queda en producción es el entorno: responder el webhook al instante, recortar el historial, tener salida al humano y tratar el error como camino esperado.
Empieza con una instancia no oficial y un número de prueba. Cuando el comportamiento esté bien, pasa a la API oficial — el webhook y el SDK son los mismos, así que el código del bot no cambia.
¿Listo para automatizar tu WhatsApp?
Crea tu cuenta gratis y empieza a enviar mensajes por la API en minutos.
Empezar gratisPreguntas frecuentes
¿Cómo conecto la API de OpenAI con WhatsApp?+
Son tres piezas: un webhook que recibe el mensaje de WhatsApp, una llamada a la API de OpenAI con el historial de la conversación, y un POST a /{key}/message/text devolviendo la respuesta. El webhook recibe todos los canales en el mismo formato, así que el mismo código atiende WhatsApp, Instagram y Messenger.
¿Necesito n8n para hacer un bot de IA en WhatsApp?+
No. n8n es cómodo si quieres armar el flujo visualmente o ya usas la herramienta. En código son unas 60 líneas, y ganas control total sobre la memoria, el costo y las reglas de cuándo no responder.
¿Cuánto cuesta tener un chatbot de IA en WhatsApp?+
Dos costos separados: el de OpenAI, cobrado por token consumido, y el del mensaje. En la API no oficial el mensaje tiene precio fijo por instancia; en la oficial, Meta cobra por conversación. El costo de la IA es el que más varía y depende del tamaño del historial que envías en cada llamada.
¿Cómo hago que el bot recuerde la conversación?+
La API de OpenAI no guarda estado: cada llamada es independiente. Guardas los últimos mensajes por contacto en un almacenamiento tuyo (Redis, base de datos o memoria) y los envías como historial en cada petición. Con los últimos diez suele alcanzar, y mantiene el costo previsible.
¿Qué hago cuando la IA no sabe responder?+
Instruye al modelo en el system prompt para que devuelva un marcador acordado cuando no tenga certeza, y maneja ese marcador en tu código derivando a una persona. Un bot que inventa el plazo de entrega sale más caro que uno que pasa la pelota.
Sigue leyendo
API de Instagram y Messenger en la misma API de WhatsApp: una instancia, un estándar
Tres canales oficiales de Meta casi siempre significan tres integraciones. Con una sola instancia, el mismo envío y el mismo sobre de webhook, solo cambia un campo: provider. Cómo funciona y qué te ahorra.
API no oficial de WhatsApp: qué es, si es segura y cómo usarla (2026)
Entiende qué es una API no oficial de WhatsApp, cómo funciona la conexión por código QR, si es segura y legal, cuál es el riesgo real de bloqueo y cuándo conviene usarla en lugar de la API oficial.
API oficial vs no oficial de WhatsApp: ¿cuál elegir? (comparativa 2026)
Comparativa completa entre la API oficial de WhatsApp (Cloud API de Meta) y la API no oficial: costo, aprobación, límites de envío, plantillas, soporte y riesgo de bloqueo. Descubre cuál tiene sentido para tu caso.