Changelog · página 4 de 14

Novedades de la API

Cada cambio de la superficie pública queda registrado aquí, del más nuevo al más viejo. Esta página cubre del 9 sep 2026 – 24 sep 2026. También puedes suscribirte al feed.

v3.4.1 Corrección

Reintenta un mensaje de contacto sin enviarlo dos veces

POST /contacts/{id}/messages acepta ahora el campo opcional client_message_id, un UUID v4 generado por tu aplicación antes del primer intento.

Si la conexión se corta y no sabes si Meteor alcanzó a recibir el mensaje, repite la misma solicitud con el mismo UUID. Meteor devuelve el mensaje ya registrado y no vuelve a entregarlo al contacto. La respuesta indica este caso con deduplicated: true.

El UUID queda disponible como client_message_id en el mensaje devuelto y al consultar la conversación. No reutilices una misma llave con otro texto, adjuntos o contacto: Meteor responde 409 para evitar cruzar conversaciones.

El campo es opcional y aditivo; las integraciones existentes conservan su comportamiento.

v3.4.0 Corrección

La referencia te trata de tú en todas sus descripciones

Trece descripciones de la referencia, la mayoría de Contactos, te hablaban con voseo. Ahora usan el mismo español neutro que el resto de la documentación.

Esta corrección documenta el mismo contrato 3.4.0: no es una nueva versión de la API. Se conservan las rutas, los parámetros, los esquemas y los permisos, así que no necesitas cambiar tus llamadas. Si generas un cliente desde el contrato, solo cambian sus comentarios.

v3.4.0 Cambio

Borrar un campo de contacto ahora borra también su valor

DELETE /variables/field-definitions/{id} ya no se limita a quitar la definición del campo: además borra el valor de ese campo en todos los contactos del espacio de trabajo.

Antes el dato se quedaba guardado en cada contacto. Si luego creabas otro campo con el mismo identificador —lo normal cuando te equivocaste de tipo y lo creas de nuevo—, los valores viejos reaparecían con el tipo anterior.

Vaciar el valor cuenta como un cambio del contacto, así que recibirás un contact.updated por cada contacto que tenía el dato. El valor llega en null.

Nuevo 409

Si una automatización activa observa el campo, la llamada responde 409 y no borra nada: vaciar el valor dispararía su condición en todos los contactos a la vez. El mensaje nombra las automatizaciones; desactívalas o cambia su condición y vuelve a intentar.

v3.3.0 Cambio

Ahora sabes desde dónde salió cada respuesta, y solo te llegan mensajes reales

Si tu integración sigue las conversaciones de WhatsApp, ahora puedes saber quién respondió y desde dónde sin cruzar datos por tu cuenta. El evento contact.message.sent trae el campo sent_from:

ValorLa respuesta salió…
metdel Met.
phonedel WhatsApp Business del celular del dueño.
flowde un flujo o una automatización.
meteorde cualquier otra parte de Met: la bandeja, una difusión, una plantilla o la API.

Tus métricas quedan limpias. Antes, las notas internas de la conversación —«Chat asignado a…», «Estado cambiado…», «Etiqueta agregada…»— también llegaban como mensajes enviados, aunque el contacto nunca las veía. Eran cerca de una de cada cinco entregas de este evento. Ya no te llegan: si cuentas respuestas o tiempos de atención, ahora cuentas solo lo que el contacto recibió.

No te pierdes las respuestas al conectar. Al crear un endpoint con contact.message.received, la consola te ofrece sumar contact.message.sent con un clic. Con solo el primero ves lo que escribe el contacto, pero no lo que se le responde.

v3.2.0 Nuevo

Cuatro campos nuevos para leer los topes de un plan

Si tu integración pinta el estado de la cuenta o decide cuándo ofrecer una mejora de plan, ahora tienes cuatro datos que antes no estaban en el contrato. Todos son opcionales y aditivos: nada de lo que ya leías cambió.

Cuántas redes sociales admite el plan

Plan.social_accounts_max dice cuántas cuentas de red social —líneas de WhatsApp, cuentas de Facebook e Instagram, sumadas— puede tener conectadas el espacio de trabajo.

{ "slug": "oficina", "social_accounts_max": null }

null significa sin tope, y es lo que devuelven los planes de pago. Un plan que traiga 1 admite una sola cuenta entre las tres redes, no una por red.

Es un techo distinto de los que ya conocías: wa_numbers_included cuenta números de WhatsApp y meta_accounts_included cuenta cuentas de Meta, cada uno contra su propia red. Este mira el total. Cuando lo alcanzas, conectar otra cuenta responde 403 con error: "social_accounts_quota" y un usage que trae el desglose por red.

Cuándo el tope de contactos no bloquea

Plan.contacts_limit_soft distingue dos formas de aplicar max_contacts:

ValorQué pasa al llegar al tope
false (lo habitual)La suscripción pasa a contacts_limit y el espacio de trabajo queda bloqueado.
trueSolo se frena el alta de contactos. El espacio de trabajo sigue operando.

Con el tope blando, un contacto entrante que llega por encima del límite no se pierde: se guarda en espera y se incorpora cuando el cupo vuelve a alcanzar.

Dónde aterriza una prueba que vence

WorkspaceSubscription.fallback_plan_id es el plan al que pasa la suscripción cuando se le acaba la prueba, en vez de quedar inactiva. null —el valor de casi todas— es el comportamiento de siempre: la prueba vence y la cuenta se bloquea hasta que se elija un plan.

Y en GET /billing/access, landed_on_fallback te avisa de la ventana en la que la prueba ya venció y la cuenta ya opera con el plan de destino, aunque la suscripción todavía diga trial:

{
  "subscription_status": "trial",
  "landed_on_fallback": true,
  "plan_slug": "<el plan de destino>",
  "limits": { "contacts_max": 100 }
}

Cuando landed_on_fallback es true, manda el plan que viene en la respuesta, no el subscription_status. plan_id, plan_slug y limits ya son los del plan de destino; el estado de la fila se pone al día en el corte siguiente. Si tu integración decide por subscription_status, vas a ver una prueba vencida donde hay una cuenta que funciona.

v2.53.0 Nuevo

Crea plantillas de WhatsApp y edita tus atajos por API

Lo que hasta hoy solo se podía hacer desde el panel ya se puede hacer por API.

Plantillas de WhatsApp

curl -X POST https://api.met.meteor.com.co/api/v1/channels/42/templates \
  -H "Authorization: Bearer $MET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "recordatorio_cita",
    "language": "es",
    "category": "UTILITY",
    "components": [
      { "type": "BODY", "text": "Hola {{1}}, te recordamos tu cita del {{2}}." }
    ]
  }'

Y DELETE sobre la misma ruta, con el name en el cuerpo, para borrarla. Las dos piden el permiso nuevo channels:manage.

Una plantilla pertenece a la cuenta de WhatsApp, no al número. Si tienes varias cuentas conectadas, la plantilla queda disponible para todos los números de aquella en la que la creaste. Omitir waba_id la crea en tu cuenta primaria, que puede no ser la del número desde el que piensas enviar; los waba_id conectados te los devuelve GET /channels/{id}/templates.

Una clave de prueba no alcanza. Crear una plantilla manda una solicitud real a revisión de Meta sobre la cuenta de tu cliente, así que channels:manage está entre los permisos restringidos en modo de prueba.

Hay un tope: 25 creaciones por cuenta y por hora. No es un número decorativo: una plantilla rechazada le baja la calificación de calidad a la cuenta de WhatsApp, y esa calificación es de tu cliente, no tuya. El 429 sale con rate_limited.

Ahora te enteras cuando Meta resuelve

La creación vuelve de inmediato con template_status: "PENDING". Meta decide después, y lo normal es que tarde. Hay tres eventos nuevos para no tener que estar preguntando:

EventoCuándo
channel.template.approvedMeta aprobó la plantilla.
channel.template.rejectedMeta la rechazó — trae el motivo.
channel.template.status_updatedCambió de estado por otra razón: pausada, deshabilitada, marcada, en apelación, archivada…

El tercero es el que conviene no ignorar. Ahí caen las plantillas que venían funcionando y dejaron de hacerlo, que operativamente es peor que un rechazo: un rechazo lo descubres cuando vas a mirar, una pausa te corta envíos en curso.

Los tres piden channels:read.

Atajos

Los atajos —las respuestas guardadas del chat— también salen a la API, con CRUD completo en /quick-replies. Leer pide conversations:read; crear, editar y borrar piden el permiso nuevo conversations:write.

curl https://api.met.meteor.com.co/api/v1/quick-replies \
  -H "Authorization: Bearer $MET_API_KEY"
v3.1.1 Cambio

Un teléfono tiene una sola ficha por espacio de trabajo

line_id ya no divide la identidad de un contacto. Un mismo teléfono tiene una sola ficha dentro del espacio de trabajo, sin importar por cuál línea de WhatsApp haya entrado o se le haya escrito.

Esto corrige lo que anunciamos el 14 de septiembre. Allí decíamos que POST /contacts/import usaba teléfono + línea como identidad y que el mismo número podía existir en dos líneas por separado. Ya no es así.

line_id sigue aceptándose y sigue validándose contra las líneas del espacio de trabajo —una línea inexistente o de otro espacio se rechaza igual que antes—, pero ahora se conserva como metadato de origen y emisión.

Qué cambia en la práctica: si importas el mismo teléfono por dos líneas distintas, antes obtenías dos contactos y ahora actualizas uno solo, según on_existing. Si tu integración contaba con dos fichas separadas para el mismo número, ese supuesto ya no se cumple.

Ninguna operación cambió de nombre, de ruta ni de forma: la corrección es de comportamiento y de la documentación que lo describía.

v3.1.0 Cambio

Duplicar un flujo acepta el nombre de la copia

POST /workspaces/{workspaceId}/flows/{id}/duplicate acepta ahora un cuerpo opcional con name, el nombre que llevará la copia.

Sin name el comportamiento no cambia: la copia se llama como el original más «(copia)». Las integraciones que ya llamaban al endpoint sin cuerpo siguen funcionando igual.

La copia sigue naciendo como draft, sin slug y sin disparadores: no ejecuta nada hasta que se publique. Copia el lienzo borrador (draft_definition), no la versión publicada.

v3.0.0 Nuevo

Los contactos importados pueden conservar su línea de WhatsApp

POST /contacts/import acepta ahora line_id en cada contacto. El valor es el phone_number_id de una línea de WhatsApp conectada al mismo espacio de trabajo.

Cuando se envía, Meteor guarda el contacto en esa línea y usa teléfono + línea como identidad. Así, un mismo teléfono puede existir en dos líneas sin mezclar las conversaciones; si vuelve a importarse en la misma línea, se actualiza el contacto existente según on_existing.

Una línea inexistente o perteneciente a otro espacio de trabajo se rechaza para evitar que una importación asocie contactos al canal equivocado.

v2.52.0 Nuevo

Un tope de gasto por conversación, consultable y reiniciable

Cada espacio de trabajo puede fijar un monto máximo de consumo por conversación. Al superarlo, el Met deja de responder en ese chat: el contacto no recibe ningún mensaje, la conversación queda marcada para atención humana y en el hilo aparece un aviso visible sólo para el equipo, con lo gastado y el tope que se alcanzó. El tope viene desactivado y se enciende desde Ajustes → Conversaciones.

El tope se revisa antes de cada turno, no durante, así que una conversación cierra un poco por encima del monto fijado. Es deliberado: cortar a mitad de una respuesta dejaría al contacto con media frase.

Dos operaciones nuevas acompañan el cambio. GET /contacts/{contactId}/budget devuelve el estado del tope para esa conversación: si está activo, el monto configurado, lo consumido hasta ahora, cuántas respuestas lo componen, desde cuándo se cuenta y si el Met ya se detuvo. POST /contacts/{contactId}/budget/reset vuelve el contador a cero y permite que el Met retome la conversación; es la única forma de reanudarla antes de que el contador se reinicie solo.

Ese reinicio automático ocurre al cerrar la conversación y también tras veinticuatro horas sin mensajes. Sin él, un contacto que escribe con regularidad alcanzaría el tope una vez y quedaría sin respuesta indefinidamente.

Ambas operaciones requieren los mismos permisos que gobiernan el piloto automático de un contacto, de modo que quien atiende el chat pueda reanudarlo sin depender de un administrador.

v2.30.2 Nuevo

Actualización controlada de campos de contacto desde webhooks

Los mapeos de un webhook ahora aceptan on_existing: "overwrite" para actualizar un campo de contacto que ya contiene información. Si omites esta opción, el comportamiento no cambia: Meteor conserva el valor existente y solo completa campos vacíos. Las claves de identidad y enrutamiento del contacto no se pueden sobrescribir mediante esta opción.

v2.51.0 Nuevo

Las colecciones pueden reemplazarse sin mezclar versiones anteriores

La importación de elementos de cualquier colección de usuario admite ahora el modo opcional replace_active. Las colecciones globales, internas y protegidas quedan excluidas para evitar cambios accidentales en datos del sistema. Este modo valida primero el archivo completo y, en una sola transacción, conserva como vigentes únicamente los registros incluidos en la nueva versión.

Antes de aplicar el reemplazo se puede ejecutar una vista previa con dryRun. La respuesta informa cuántos registros se crearán, actualizarán, reactivarán o archivarán, además del total vigente esperado. Cada ejecución exige una revisión identificable, una clave de identidad elegida por el usuario y una confirmación explícita con el nombre de la colección. La ejecución queda disponible para consulta posterior.

El comportamiento anterior de actualización por clave sigue disponible como modo predeterminado, por lo que las integraciones existentes no cambian.

La lectura de elementos también admite ahora el parámetro explícito status=active. Así una interfaz o integración puede mostrar únicamente la versión vigente después del reemplazo, mientras los registros archivados se conservan para consulta histórica sin quedar mezclados en el listado operativo.