← Blog

·

Cómo conectar ChatGPT a la API oficial de WhatsApp (tutorial con código)

Actualizado el 28/10/2026

Para conectar ChatGPT a la API oficial de WhatsApp, recibes el mensaje del cliente por el webhook, envías el historial de esa conversación a la Responses API de OpenAI (POST https://api.openai.com/v1/responses) y devuelves el texto generado con una llamada de envío de la Cloud API. La respuesta libre solo puede salir dentro de la ventana de 24 horas que abre el cliente, y la política de Meta exige una vía clara hacia un agente humano. Usar la IA como apoyo a la atención de tu propia empresa está permitido; ofrecer un «ChatGPT de uso general» como producto en WhatsApp tiene reglas propias en los términos de Meta.

Este tutorial es la parte práctica: código Node.js completo, historial por contacto, control de la ventana, traspaso a humano y costos. La arquitectura general está en WhatsApp Cloud API: qué es, cómo funciona y cuánto cuesta y en los tutoriales de bot enlazados más abajo.

Qué necesitas antes de empezar

  • Un número conectado a la API oficial, con el webhook configurado. Si aún no lo tienes, empieza por la guía de la Cloud API enlazada arriba.
  • Una clave de la API de OpenAI (OPENAI_API_KEY), creada en el panel de OpenAI.
  • Node.js 18 o superior (el ejemplo usa fetch nativo y el SDK oficial openai).
  • Una base de datos para guardar historial y estado de la conversación. En el ejemplo usamos memoria para simplificar.

En WhatsApp no cambia nada por usar ChatGPT: la Cloud API no sabe qué modelo genera el texto. Lo que regula el caso de uso son los términos de Meta, que vemos más adelante.

El flujo en 5 pasos

PasoQué pasaDónde
1El cliente escribe y Meta dispara el webhookMeta → tu servidor (directo o vía proveedor)
2Tu servidor responde 200 al instante y encola el eventoWebhook
3El worker carga el historial de ese wa_id y decide si responde el botBase de datos + enrutador
4El worker llama a la Responses API con instrucciones e historialOpenAI
5El texto vuelve al cliente por POST /messagesCloud API

El paso 2 es donde fallan las integraciones hechas con prisa. El modelo puede tardar varios segundos en responder, y el webhook no puede esperar. En Vectalk, por ejemplo, el endpoint debe devolver HTTP 200 en un máximo de 20 segundos o el evento se reenvía, según la documentación de webhooks. Reenvíos sin deduplicación se convierten en respuestas duplicadas y costo doble.

¿Quieres probar mientras lees? Crea tu cuenta en Vectalk y envía el primer mensaje por la API oficial. Crear cuenta gratis →

¿Responses API o Chat Completions?

OpenAI tiene dos APIs para generar texto. La guía de generación de texto recomienda la Responses API para aplicaciones nuevas, y es la que usamos aquí. La llamada mínima es:

curl https://api.openai.com/v1/responses \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "TU_MODELO",
    "instructions": "Eres el asistente de Tienda Ejemplo. Responde en hasta 3 frases.",
    "input": "¿Cuánto tarda el envío a Guadalajara?"
  }'

Tres parámetros importan para un bot de WhatsApp:

  • instructions: el comportamiento del bot (tono, alcance, lo que no hace). Vale solo para la solicitud actual, así que envíalo siempre.
  • input: la pregunta, o una lista de mensajes user y assistant con el historial.
  • model: elígelo en la página de modelos de OpenAI. Déjalo en una variable de entorno para cambiarlo sin tocar el código.

En los SDKs oficiales, el texto final está en response.output_text. No leas output[0] directamente: la salida puede traer otros elementos antes del texto, como llamadas a herramientas.

Historial por contacto: tres formas

ChatGPT no recuerda la conversación por sí solo. En cada mensaje tienes que darle el contexto. La guía de estado de la conversación de OpenAI describe tres opciones:

OpciónCómo funcionaDónde queda el historialCuándo usarla
Historial manualEnvías los últimos mensajes en inputEn tu base de datosOpción recomendada para atención: controlas tamaño, retención y auditoría
previous_response_idEnvías solo el mensaje nuevo y el ID de la respuesta anteriorEn OpenAI (los objetos de respuesta se guardan 30 días por defecto)Prototipos; los tokens de respuestas anteriores se siguen cobrando como entrada
Conversations APICreas una conversación y pasas su ID en conversationEn OpenAI, sin el límite de 30 díasCuando quieres un estado duradero del lado de OpenAI

Para atención al cliente, el historial manual suele ser la opción más fácil de justificar: los datos quedan en tu base, decides cuánto tiempo guardarlos y puedes usar store: false para que OpenAI no guarde la respuesta. La clave del historial es el wa_id del cliente (el campo from del mensaje recibido).

Si la conversación incluye datos personales, la ley de protección de datos de tu país se aplica a lo que envías al proveedor de IA. En Brasil es la LGPD (Ley General de Protección de Datos); consulta LGPD y WhatsApp. Este artículo no sustituye asesoría legal.

Código completo en Node.js

El ejemplo usa Express, el SDK openai y el envío por Vectalk, que acepta el mismo payload de la Cloud API. Con token de instancia, el número de origen se resuelve automáticamente; con token de organización, incluye phone_number_id en el cuerpo, según la referencia de envío. Si integras directo con Meta, cambia la URL por https://graph.facebook.com/<versión>/<PHONE_NUMBER_ID>/messages y usa tu token de Meta.

npm install express openai
import express from 'express';
import OpenAI from 'openai';

const openai = new OpenAI(); // lee OPENAI_API_KEY del entorno
const MODELO = process.env.OPENAI_MODEL;
const URL_ENVIO = 'https://apis.vectalk.com.br/api/messages';
const TOKEN = process.env.VECTALK_TOKEN; // token de instancia
const VENTANA_MS = 24 * 60 * 60 * 1000;
const MAX_TURNOS = 20;

const INSTRUCCIONES = `Eres el asistente virtual de Tienda Ejemplo en WhatsApp.
- Responde en español, en un máximo de 3 frases cortas.
- Habla solo de pedidos, envíos, cambios y productos de la tienda.
- No inventes precios, plazos ni políticas: usa solo los datos proporcionados.
- Si no sabes, si el cliente pide una persona o el tema es un reclamo,
  una cancelación o un cobro en disputa, responde exactamente: HANDOFF`;

const app = express();
app.use(express.json());

const cola = [];
const procesados = new Set();  // wamid ya tratados (usa Redis/base de datos en producción)
const chats = new Map();       // wa_id -> { estado, historial, ultimaEntrada }

// 1. Webhook: encola y responde 200 de inmediato
app.post('/webhook', (req, res) => {
  for (const entry of req.body.entry ?? []) {
    for (const change of entry.changes ?? []) {
      for (const msg of change.value?.messages ?? []) cola.push(msg);
    }
  }
  res.sendStatus(200);
});

// 2. Envío a WhatsApp
async function enviar(cuerpo) {
  const r = await fetch(URL_ENVIO, {
    method: 'POST',
    headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ messaging_product: 'whatsapp', ...cuerpo }),
  });
  if (!r.ok) throw new Error(`Falló el envío: ${r.status} ${await r.text()}`);
  return r.json();
}

// 3. Llamada a OpenAI (Responses API)
async function preguntarAlModelo(historial) {
  const respuesta = await openai.responses.create(
    {
      model: MODELO,
      instructions: INSTRUCCIONES,
      input: historial,         // [{ role: 'user' | 'assistant', content: '...' }]
      max_output_tokens: 300,   // respuestas cortas cuestan menos
      store: false,             // no guardar la respuesta en OpenAI
    },
    { timeout: 15000 },
  );
  return respuesta.output_text.trim();
}

// 4. Worker
async function procesar(msg) {
  if (procesados.has(msg.id)) return;
  procesados.add(msg.id);

  const c = chats.get(msg.from) ?? { estado: 'bot', historial: [], ultimaEntrada: 0 };
  c.ultimaEntrada = Number(msg.timestamp) * 1000;
  chats.set(msg.from, c);

  if (c.estado !== 'bot') return; // un humano tomó la conversación: el bot calla

  if (msg.type !== 'text') {
    await enviar({ to: msg.from, type: 'text', text: { body: 'Por aquí solo entiendo texto. ¿Puedes escribir tu pregunta?' } });
    return;
  }

  await enviar({ status: 'read', message_id: msg.id }); // marcar como leído

  c.historial.push({ role: 'user', content: msg.text.body });
  c.historial = c.historial.slice(-MAX_TURNOS);

  let texto;
  try {
    texto = await preguntarAlModelo(c.historial);
  } catch (e) {
    console.error('Falló OpenAI', e);
    texto = 'HANDOFF'; // ante la duda, pasa a una persona
  }

  if (texto === 'HANDOFF') return transferir(msg.from, c);
  if (Date.now() - c.ultimaEntrada > VENTANA_MS) return; // ventana cerrada: solo plantilla

  await enviar({ to: msg.from, type: 'text', text: { body: texto } });
  c.historial.push({ role: 'assistant', content: texto });
}

async function transferir(waId, c) {
  c.estado = 'humano';
  await enviar({ to: waId, type: 'text', text: { body: 'Voy a llamar a una persona de nuestro equipo. En un momento sigue la conversación por aquí.' } });
  // Avisa a tu herramienta de atención (cola de tickets, CRM, Slack).
}

setInterval(async () => {
  const msg = cola.shift();
  if (!msg) return;
  try { await procesar(msg); } catch (e) { console.error(e); }
}, 50);

app.listen(3000, () => console.log('Bot activo en el puerto 3000'));

Para ejecutarlo:

export OPENAI_API_KEY="sk-..."
export OPENAI_MODEL="modelo-elegido-en-la-pagina-de-modelos"
export VECTALK_TOKEN="tu-token-de-instancia"
node bot.mjs

Para probar en local, expón el puerto 3000 con un túnel y registra la URL como webhook; el paso a paso está en cómo probar el webhook de WhatsApp en local. Si tu webhook recibe directo de Meta, valida la firma de cada solicitud antes de procesarla: consulta cómo validar X-Hub-Signature-256.

Mientras el modelo piensa, la Cloud API permite mostrar «escribiendo…» en la misma llamada que marca el mensaje como leído, agregando "typing_indicator": { "type": "text" }. Según la documentación de indicadores de escritura, desaparece cuando respondes o a los 25 segundos, lo que ocurra primero, y Meta recomienda usarlo solo si realmente vas a responder.

Qué resuelve el ejemplo y qué falta

  • Resuelve: respuesta inmediata al webhook, deduplicación por wamid, historial por contacto con límite de tamaño, timeout en OpenAI, verificación de la ventana y estado de traspaso.
  • Falta para producción: cola persistente con reintentos, base de datos para historial y estado, control del ritmo de envío (throughput), registro de costo por conversación y un panel para que el agente devuelva la conversación al bot.

Bots completos sin la parte de IA están en bot de WhatsApp con Node.js y bot de WhatsApp con Python.

Ventana de 24 horas: ChatGPT no inicia conversaciones

La respuesta del modelo es un mensaje libre. La Política de Mensajería de WhatsApp Business permite responder sin plantilla solo dentro de la ventana de atención de 24 horas, que se abre y se renueva con cada mensaje del cliente. Fuera de ella, solo plantillas aprobadas.

En la práctica:

  • El bot es reactivo. No puede enviar «Hola, ¿sigues interesado?» dos días después con texto generado por ChatGPT. Para eso existen las plantillas.
  • Verifica la ventana justo antes de enviar, no solo cuando llega el mensaje. Si el modelo se trabó, la cola se atrasó o el worker se cayó, la ventana puede cerrarse en el camino.
  • No uses el modelo para «rellenar» una plantilla. Las plantillas tienen texto aprobado y variables; el contenido de las variables debe venir de los datos de tu sistema.

Traspaso a un humano

La política de Meta permite automatizar dentro de la ventana, pero exige vías de escalamiento claras, como el traspaso a un agente humano en la conversación, teléfono, correo, soporte web o formulario. En el código de arriba, tres situaciones llevan al traspaso:

  1. El modelo responde HANDOFF porque no sabe, el cliente pidió una persona o el tema es sensible (así lo dicen las instrucciones).
  2. La llamada a OpenAI falla o excede el tiempo.
  3. Puedes sumar disparadores propios, como palabras clave o un botón «Hablar con un agente».

Tras el traspaso, el estado pasa a humano y el bot calla hasta que el agente devuelva la conversación. Si el número usa coexistencia, el agente puede responder desde la app WhatsApp Business, y los mensajes enviados desde la app llegan a tu sistema como eventos de eco; puedes usarlos para marcar la conversación como humano automáticamente.

Cuánto cuesta: Meta + OpenAI

Son dos cuentas separadas.

WhatsApp (Meta). Las respuestas del bot dentro de la ventana son mensajes de servicio. Desde el 1 de octubre de 2026, cada número tiene 1.000 mensajes de servicio gratis al mes, y el cobro empieza en el 1.001. Para destinatarios en Brasil, la tarifa de servicio es de R$ 0,0350 (reales) por mensaje entregado, según la página de precios de Meta; los demás países tienen sus tarifas en la misma página. Las plantillas se cobran según la tarifa de su categoría, dentro o fuera de la ventana (en Brasil, marketing R$ 0,3217; utilidad y autenticación R$ 0,0350); desde el 1 de octubre de 2026, eso incluye las plantillas de utilidad enviadas dentro de la ventana.

OpenAI. Se cobra por tokens de entrada y de salida, con un precio que depende del modelo. Consulta la página de precios de OpenAI antes de estimar.

Tres ajustes bajan las dos cuentas a la vez:

  • Una respuesta por pregunta. Tres mensajes cortos cuentan como tres mensajes de servicio después de la franquicia. Pide al modelo una sola respuesta.
  • Historial corto. Cada mensaje antiguo enviado en input se cobra otra vez como token de entrada. Mantén los últimos turnos y, si hace falta, un resumen.
  • max_output_tokens. Limita el largo de la respuesta y evita textos largos que nadie lee en el celular.

Qué permite Meta: un «ChatGPT de uso general» es otro caso

Los Términos de Meta para la Plataforma de WhatsApp Business, actualizados el 23/09/2026, tratan de los «Proveedores de IA» en la sección 4.7: proveedores y desarrolladores de tecnologías de IA o aprendizaje automático, como grandes modelos de lenguaje, plataformas de IA generativa y asistentes de IA de uso general. Tienen prohibido usar la plataforma para ofrecer esas tecnologías cuando son la funcionalidad principal, y no incidental o auxiliar, a criterio de Meta. Los términos prevén excepciones para determinados países.

EscenarioLectura de los términos
Una tienda usa un modelo de OpenAI para responder dudas sobre pedidosIA como apoyo a la atención de la empresa; no es el caso al que apunta la cláusula
Una clínica usa IA para agendar y confirmar citasIgual: la IA es herramienta del servicio, no el producto
Una empresa ofrece «conversa con una IA sobre cualquier tema» en WhatsAppEs el caso de Proveedor de IA; depende de las reglas por país

Brasil es uno de esos países. La página de precios para Proveedores de IA, actualizada el 15/10/2026, indica que desde el 11/03/2026 los Proveedores de IA pueden enviar mensajes de servicio a usuarios con número +55, con tarifa propia, siempre en respuesta al usuario (la ventana de atención sigue vigente). En esos mensajes, el webhook de estado trae la categoría general_purpose_ai. La misma página lista otros mercados y fechas. La regla aplica solo a Proveedores de IA; el precio para las demás empresas no cambia.

Los términos también prohíben usar datos de la plataforma para crear, entrenar o mejorar modelos de IA, con una excepción para ajustar un modelo de uso exclusivo de la empresa que no sirva para otros modelos. En la práctica: revisa cómo tu proveedor de IA trata la retención y el entrenamiento, y no reutilices conversaciones de WhatsApp para entrenar modelos de terceros.

Cómo hacerlo con Vectalk

Vectalk es un proxy de la Cloud API oficial: tu bot recibe los mismos webhooks de Meta y envía con los mismos payloads, cambiando solo la URL base y el token. En el código de arriba, eso es la constante URL_ENVIO y el VECTALK_TOKEN. Registras la URL del bot con POST /api/webhooks y puedes dar de alta más de una URL por instancia, por ejemplo una para el bot y otra para tu sistema de atención. No registras tarjeta en Meta: cada mensaje entregado se descuenta del saldo prepago de tu cuenta Vectalk, y la coexistencia deja que tu equipo responda desde la app cuando el bot traspasa la conversación. Empieza en apps.vectalk.com.br/register y consulta la guía rápida.

Preguntas frecuentes

¿Necesito autorización de Meta para usar ChatGPT en WhatsApp?

Para un bot de atención de tu propia empresa, la documentación consultada no describe un registro adicional: usas la API oficial normalmente. Si tu producto es un asistente de IA de uso general, lee la sección 4.7 de los términos y la página de Proveedores de IA antes de lanzar.

¿Puedo usar la app de ChatGPT o un «ChatGPT para WhatsApp» listo?

Este tutorial usa la API de OpenAI en tu servidor, conectada a la API oficial de WhatsApp. Las herramientas que conectan WhatsApp escaneando un código QR usan canales no oficiales, con riesgo de bloqueo; consulta API oficial vs. API no oficial de WhatsApp.

¿El bot puede enviar el primer mensaje?

No con texto generado por el modelo. Para iniciar o retomar el contacto fuera de la ventana de 24 horas, necesitas una plantilla aprobada.

¿Cómo hago que ChatGPT responda audios?

El webhook entrega el ID del archivo multimedia. Lo descargas con la API de medios, lo transcribes con el servicio que prefieras y envías el texto al modelo. La descarga está en cómo descargar los archivos que envía el cliente.

¿Responses API o Chat Completions?

Las dos funcionan con WhatsApp, porque la integración es solo HTTP. OpenAI recomienda la Responses API para aplicaciones nuevas, y es la que usa el ejemplo.


Fuentes oficiales consultadas el 28/10/2026: OpenAI: generación de texto, OpenAI: estado de la conversación, Términos de Meta para la Plataforma de WhatsApp Business (actualizados el 23/09/2026), Política de Mensajería de WhatsApp Business (actualizada el 23/09/2026), Precios para Proveedores de IA (actualizada el 15/10/2026), Precios de la plataforma de WhatsApp Business, Indicadores de escritura, Vectalk: webhooks, Vectalk: envío de mensajes.

Prueba hoy la API oficial de WhatsApp

Crea tu cuenta, genera el token y envía el primer mensaje con la guía de la documentación. Los mismos payloads y webhooks de la Cloud API de Meta.