Qué cambia en la API
Cambios de endpoint, de envelope de webhook y de comportamiento, en orden cronológico. Los campos nuevos son aditivos: nada de lo que ya recibes deja de llegar sin avisarse aquí.
Adición es compatible con lo que ya haces. Corrección cambia lo que recibes, hacia lo que ya estaba documentado. Requiere atención cambia el comportamiento de quien no haga nada.
- Requiere atenciónChatwootWhatsApp Oficial
Ventana de 24h: el mensaje libre fuera de ella ya no se envía
En la cuenta oficial, pasadas 24h del último mensaje del cliente, el texto libre ya no se intenta: o sale como plantilla aprobada, o se convierte en un aviso en la conversación.
Meta rechaza cualquier mensaje libre fuera de la ventana de 24 horas. Hasta ahora el intento salía de aquí, era rechazado allá y el error quedaba solo en el log: el agente veía el mensaje como enviado.
Qué cambia:
- Si el texto que escribió el agente corresponde a una plantilla aprobada, el envío sale como plantilla y la conversación se reabre. Las variables se extraen del propio texto, así que puede editar la plantilla antes de enviar.
- Si no corresponde, no se envía nada: una nota privada explica el motivo y el mensaje queda marcado como fallido.
POST /chatwoot/templates/syncpublica las plantillas aprobadas como respuestas rápidas (atajotpl_<nombre>), que es como el agente dispara una sin salir del panel.
Cuando no sabemos cuándo habló el cliente por última vez, el envío sigue normal — Meta sigue siendo quien decide.
- CorrecciónChatwoot
Chatwoot: la cuenta se descubre por la bandeja de entrada
Quien usa un único Token de Acceso para varias cuentas de Chatwoot tenía los mensajes enviados desde el celular escritos en la cuenta equivocada — o rechazados con 404.
El
account_idse descubría por el perfil del Token de Acceso, que devuelve la cuenta activa del usuario — sin relación con la cuenta dueña de la bandeja configurada. En un bot de automatización que atiende decenas de cuentas con un solo token, eso apuntaba a la cuenta equivocada.Ahora la cuenta se descubre buscando el
inbox_identifierconfigurado entre las bandejas de cada cuenta que el token alcanza. Cuando el barrido no la encuentra en ninguna, no se escribe nada: el log explica el motivo, en vez de que el mensaje acabe en la conversación de otro cliente.No necesitas hacer nada. Si tu integración funcionaba, sigue igual.
- CorrecciónChatwootWhatsAppWhatsApp Oficial
Chatwoot: cinco fallas en el espejo de las conversaciones
El mensaje cuyo archivo no se podía descargar desaparecía del panel; las marcas de entregado/leído nunca funcionaron en WhatsApp no oficial; los adjuntos más allá del primero se descartaban.
Una auditoría de la integración encontró cinco problemas, todos corregidos:
- El mensaje del cliente desaparecía cuando el archivo no podía descargarse (más de 40 MB, descarga rechazada). Chatwoot rechaza un mensaje sin contenido y sin adjunto, y la conversación quedaba sin rastro. Ahora llega un aviso en lugar del silencio.
- Las marcas de entregado y leído nunca funcionaron en WhatsApp no oficial: dependían de una configuración de tu webhook que nace apagada. El acuse ahora va directo a Chatwoot.
- Un contacto identificado solo por LID se convertía en un teléfono inventado, y la respuesta del agente no llegaba a nadie.
- Del segundo adjunto en adelante, no se enviaba nada cuando el agente adjuntaba varios archivos. Y todo documento llegaba como
file.pdfen vez de su nombre real. - Un envío rechazado por el proveedor parecía entregado en el panel; ahora aparece como fallido.
- CorrecciónAPIWhatsApp Oficial
Diagnóstico de webhook: la ruta de estadísticas pasa a hablar de tu instancia
GET /instance/webhook/statistics respondía 500 en cuenta oficial y, cuando respondía, devolvía los contadores de la cola del servidor — iguales para todas las instancias. Ahora devuelve el resultado real de cada POST de tu instancia.
La ruta tenía dos defectos que se sumaban.
En cuenta oficial (Cloud API) respondía 500: por dentro pasaba por la sesión del código QR, que la cuenta oficial no tiene. Era justamente la instancia cuyo webhook da más trabajo la que no se podía diagnosticar. En una instancia de código QR aún no cargada en el servidor, el "no encontrada" también salía como 500.
Y cuando respondía, los números eran los contadores de la cola del proceso — globales, compartidos por todas las instancias de ese servidor. Respondían "¿la cola está atascada?", nunca "¿el webhook de mi instancia salió, y qué respondió mi servidor?". La única respuesta a eso vivía en el log del servidor, fuera de tu alcance.
Ahora la respuesta es sobre tu instancia:
json{ "status": 200, "data": { "official": true, "webhook": { "allowNumber": "all", "webhookFormat": "meta", "configured": ["webhookMessage", "webhookMessageFromMe"], "anyUrl": true }, "delivery": { "queued": 118, "attempts": 118, "ok": 117, "clientError": 0, "failed": 1, "avgMs": 143, "last": { "ts": "2026-10-14T22:34:01.020Z", "status": 200, "ms": 131, "outcome": "ok" }, "recent": [] }, "queue": { "waiting": 0, "active": 0, "failed": 0, "scope": "worker-global" } } }Cómo leerlo:
anyUrl: false— ningún canal tiene URL. Sin URL no hay nada que entregar: el evento sale solo por el socket. Es la causa número uno de "no recibo nada", y era lo que obligaba a abrir el log para descubrir lo obvio.configureddice qué canales tienen URL de hecho.okalto y aun así "no llega nada" — el POST salió y tu servidor respondió 2xx. El evento se perdió en tu procesamiento, no en el transporte. Ese era el caso que no dejaba ningún rastro.clientError— tu servidor rechazó con 4xx. No reintentamos 4xx por diseño: un 404 o un 422 no mejora repitiendo.failed— timeout, 5xx o 429. Esos sí los reintentamos: 5 intentos con retroceso exponencial. Nuestro tiempo límite de entrega es de 8 segundos.queuedmuy por encima deattempts— la cola se trabó de nuestro lado. El problema no es tu servidor.queuesigue en la respuesta, ahora marcadascope: "worker-global": son números del proceso, compartidos con otras instancias. Para juzgar la tuya, usadelivery.
Letra pequeña: los contadores valen a partir de esta versión, no hay historial retroactivo. Se guardan 7 días, y
recenttrae las últimas 20 entregas con estado, duración y error. Vale para cuenta oficial (Cloud API) y código QR.En el mismo lote,
/instance/webhook/errorsalió de la documentación — aparecía allí y nunca existió en la API. - CorrecciónMessenger
Messenger: las reacciones funcionan, y el sticker deja de llegar como imagen
El endpoint de reacción enviaba un valor fijo en vez del emoji elegido, y Meta rechazaba todos los intentos. La reacción recibida y el sticker tampoco llegaban identificados.
- Enviar reacción (
/message/reactionconprovider: messenger) descartaba el emoji y mandaba un valor fijo: Meta respondía100/2018468en todos los intentos. Ahora va el emoji que envíes. El formato aceptado es el emoji en UTF-8 (👍,❤️); los nombres en texto (like) se rechazan de inmediato, con explicación. Quitar sigue siendotext: "". - Recibir reacción no se entregaba: el evento se descartaba antes de llegar a tu webhook. Ahora llega como mensaje
type: "reaction", conreaction.message_id,reaction.emojiyreaction.action(reactounreact; al quitar, el emoji viene vacío). - Sticker llegaba como imagen común. Messenger lo entrega como adjunto que se declara
imageconsticker_iden el payload; ahora llega comotype: "sticker"con ese id. Meta no expone el archivo animado en el webhook — la URL servida es la versión estática. - Foto del contacto: cuando la Graph rechaza el perfil, el motivo queda registrado en el log, en vez de que el contacto quede sin avatar sin explicación.
- Enviar reacción (
- AdiciónChatwoot
Chatwoot: cita nativa, nota de voz y hora real
Con el Token de Acceso configurado, la conversación en el panel gana burbuja de respuesta real, reproductor de voz y la hora en que el mensaje existió en el canal.
La API pública de la bandeja acepta solo texto y adjunto. Con Token de Acceso, el mensaje del cliente pasa a crearse por la Application API, lo que habilita tres cosas:
- Cita nativa: la respuesta aparece en la burbuja de Chatwoot, ya no como un fragmento citado dentro del texto.
- Nota de voz con reproductor propio, en vez de un adjunto de audio cualquiera.
- Hora real del mensaje: el backlog reentregado tras una caída de conexión ya no aparece amontonado en la hora de la entrega.
Sin Token de Acceso nada cambia. Las citas a mensajes anteriores a esta versión aparecen sin burbuja, porque no tienen el identificador del canal guardado.
- AdiciónChatwootWhatsAppWhatsApp Oficial
Chatwoot: “escribiendo…” en ambos sentidos y tilde azul al responder
El cliente ve cuando el agente escribe, el agente ve cuando el cliente escribe, y responder desde el panel marca la conversación como leída en WhatsApp.
Tres señales que existían en ambos extremos y nunca se encontraban:
- Agente escribiendo → el cliente lo ve. En WhatsApp no oficial es presencia; en la cuenta oficial el indicador va junto al marcar-como-leído, como exige la Cloud API. "Dejó de escribir" no existe en la cuenta oficial: allí el indicador desaparece solo tras unos 25 segundos.
- Cliente escribiendo → el agente lo ve en el panel. El indicador nunca abre una conversación nueva.
- Responder desde el panel marca como leído en el canal, así el cliente deja de ver dos tildes grises mientras ya está siendo atendido.
- AdiciónMessengerAPI
Webhook de Messenger: número de secuencia y marcas de tiempo
Cada evento lleva ahora un bloque wame con un número de secuencia por conversación y tres horarios, para reconstruir el orden y medir dónde se fue el tiempo.
La entrega de webhooks es paralela: el orden en que las solicitudes llegan a tu servidor es el orden en que cada una termina, no el orden en que entraron los eventos. Dos mensajes enviados en secuencia pueden llegar invertidos.
En vez de serializar la entrega, los eventos de Messenger pasan a llevar:
json"wame": { "seq": 42, "event_ms": 1760000000000, "received_at_ms": 1760000000420, "dispatched_at_ms": 1760000000437 }seqes un contador por conversación, asignado en el orden en que recibimos el evento de Meta. Ordenar por él reconstruye la secuencia, incluso con horarios iguales.event_mses la hora del evento según Meta, en milisegundos;received_at_ms, cuando entró aquí;dispatched_at_ms, cuando salió. Del primero al segundo es latencia de Meta; del segundo al tercero, nuestra.
El bloque es aditivo: ningún campo existente cambió. Por ahora solo en eventos de Messenger.
En el mismo lote,
GET /messenger/webhook-fieldsmuestra qué campos de webhook suscribe tu Página yPOSTen la misma ruta suscribe los que faltan — eso explica los acuses de entrega, de lectura o las reacciones que nunca llegan.