Meta Tech Provider

node | Enviar y recibir WhatsApp desde Node.js

Recibir es una ruta que responde al GET de verificación de Meta y acepta POSTs. Enviar es una llamada fetch a la Cloud API con el phone number id y el token del número. No existe un SDK nuestro y no hay nada que instalar.

2 handlers

Un GET para la verificación de Meta y un POST para los eventos.

24 hours

Ventana posterior al mensaje del cliente en la que se envía texto libre.

131047

El error que se devuelve cuando envías texto libre fuera de esa ventana.

¿Cómo se reciben mensajes en Node?

Una ruta con dos métodos, en Express, Fastify, en un route handler de Next o en un servidor plano.

El GET responde a la verificación de Meta: lee hub.mode, hub.verify_token y hub.challenge de la query, compara el token con el tuyo, y devuelve el challenge como texto plano. Devolverlo como JSON es el error de siempre y produce un endpoint que nunca recibe nada mientras aparenta estar correcto.

El POST recibe los eventos. Responde 200 de inmediato y procesa después. Meta reintenta cualquier cosa lenta, y un handler que hace su trabajo antes de responder verá el mismo mensaje más de una vez. En serverless en particular, responder primero y encolar el trabajo es lo que impide que un cold start se convierta en un duplicado.

¿Cómo se envía?

Un fetch al endpoint de mensajes de la Cloud API del phone number id, con el token en la cabecera bearer.

Nada de esto es específico nuestro, así que la petición coincide exactamente con la documentación de la propia Meta y no hay wrapper que aprender ni al que quedar atado. Los dos valores están en el panel, y get_api_credentials los devuelve por el conector MCP si es un asistente quien hace el cableado.

El cuerpo depende del tiempo. Dentro de las 24 horas del último mensaje entrante del cliente, envía un objeto de texto. Fuera de eso, envía un objeto de plantilla con un nombre de plantilla aprobada y su idioma. El código que solo envía texto pasa todas las pruebas y falla en el primer mensaje que llega de madrugada.

¿Qué cambia en serverless?

Dos cosas, y las dos tienen que ver con que la función termina antes que el trabajo.

Devolver 200 y luego seguir procesando no sobrevive a una función que se congela en el instante en que responde. Usa lo que tu plataforma ofrezca para mantener el trabajo vivo después de la respuesta, o empuja el payload a una cola y deja que otra función lo atienda. Meta solo necesita el acuse rápido; no necesita que el trabajo esté hecho.

Los cold starts además hacen más probables las respuestas lentas, lo que significa más reintentos y más duplicados. Deduplicar por el id de mensaje wamid no es opcional en esta forma, es justamente lo que la vuelve confiable.

Errores comunes

  • Devolver el challenge como JSON en lugar de como cuerpo crudo.
  • Hacer el trabajo antes de responder 200. En serverless la función puede congelarse en el instante en que responde.
  • Saltarse la deduplicación. Meta reintenta por diseño y los duplicados son normales, no un caso extremo.
Hacerlo con EasyCoexistence

Conecta el número en easycoexistence.com, define el destino del webhook como tu ruta, y lee el phone number id y el token desde el panel. Desde US$ 9 por número por mes, bajando a US$ 2 con volumen, con los primeros 7 días gratis.

Preguntas frecuentes

¿Necesito una librería?

No. Una ruta y fetch bastan, y la llamada coincide exactamente con la documentación de Meta.

¿Esto funciona en Vercel o en Lambda?

Sí, con la salvedad de siempre del serverless: acusa primero, luego procesa por una cola o por un mecanismo en segundo plano en lugar de ahí mismo.

¿Cómo verifico que la petición vino de Meta?

Revisa la cabecera de firma contra tu app secret. Vale hacerlo en cuanto el endpoint sea público.

¿Puedo usar TypeScript?

Sí. No hay nada nuestro contra lo que tipar, ya que el payload es de Meta y está documentado por Meta.

Sigue leyendo

¿Listo para empezar?

Configura WhatsApp Coexistence en minutos, no en meses. La app sigue funcionando en el teléfono.

Empezar prueba gratis

Verificado el

Enviar WhatsApp desde Node.js