Changelog · página 9 de 12

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 25 jul 2026 – 30 jul 2026. También puedes suscribirte al feed.

v2.14.0

El CLI ya opera datos y CRM, y sabe decirte por qué tu key no funciona

met ya opera las colecciones, los ítems y los contactos desde la terminal, además de runs, tareas y eventos.

met collections show 12        # el esquema de campos
met items create --collection 12 --set titulo="Casa en el norte" --set precio=250000
met contacts send 42 "Ya quedó agendada la visita"

--set es repetible y se escribe sin escapar nada. Se parte en el primer =, así que una URL con query pasa entera.

Los tipos son la parte fina. Del shell todo llega como texto, y mandar "true" donde el campo espera un booleano lo guarda como texto sin que nada se queje. Así que --set convierte solo lo que no tiene ambigüedad: true, false, null y los números pasan; 007, 1.50, 1e3 y 0x10 quedan como texto, porque no sobreviven el viaje de ida y vuelta. Lo que no puede distinguir es un teléfono 3001234567 de una cantidad — para esos, el tipo lo pones tú:

met items create --collection 12 --data '{"telefono":"3001234567"}'

met contacts send manda como operador humano, no como Met: es el equivalente de escribir desde la bandeja, y queda atribuido a una persona en el historial. Si quieres que responda un Met, eso es met run.

met whoami responde *"¿por qué mi key no funciona?"* distinguiendo los tres casos que desde afuera se ven idénticos:

  • 401 — la key está mal, vencida o revocada.
  • 403 — la key es válida y le falta el scope de la operación. Es el que más tiempo hace perder: autentica sin problema y aun así falla, y la primera sospecha siempre cae en la key.
  • 2xx — key, workspace y host correctos.

También imprime contra qué host y qué workspace estás pegando, que es el otro error silencioso. Reemplaza a met keys: las API keys se crean y revocan desde el panel.

Está en @meteor.ia/cli 0.3.0. La guía completa: CLI.

v2.13.0

El servidor MCP ya escribe, y sabe qué hay en tu workspace

El catálogo MCP pasó de 16 tools en 6 dominios a 22 en 9. Hasta ahora un agente conectado a Meteor podía leer bastante y escribir muy poco: creaba contactos y tareas, instalaba plantillas, y ahí terminaba.

Cerrar el ciclo de una tarea. met_set_task_status era el eslabón que faltaba: se podían crear tareas y ejecutarlas, pero no marcarlas como terminadas. Un asistente que abre trabajo y nunca lo cierra deja el tablero peor de como lo encontró.

Escribir datos. met_create_item y met_update_item sobre las colecciones no-code. data lleva las claves del esquema de la colección — las ves con met_list_collections — y en met_update_item es un merge parcial: lo que no mandas queda como estaba. El título del ítem es el primer campo del esquema, no una clave name aparte.

Contexto del workspace. met_list_variables y met_list_skills. Las variables son los tokens que se interpolan en prompts, plantillas y mensajes: un asistente que no las ve redacta a ciegas para ese workspace. Las habilidades responden "qué sabe hacer esto" antes de pedirle algo a un Met.

Hablarle a un contacto. met_send_message envía por el canal activo del contacto, como operador humano. No hay que elegir canal: lo resuelve el contacto. Y si no tiene un canal conversacional activo, falla — antes que descartar el mensaje en silencio.

Cada tool declara el mismo scope que su endpoint REST, así que ninguna abre una puerta nueva: met_send_message pide channels:send, igual que POST /contacts/{id}/messages. Una key sin ese scope no ve la tool en el catálogo.

Los descriptores de /.well-known/mcp.json y /.well-known/server.json se regeneran del catálogo real, así que ya anuncian las 22.

v2.12.0

Python en las guías, y el CLI ya puede ejecutar tareas

El SDK de Python tiene paridad completa con el de TypeScript desde hace tiempo, y en el portal no había un solo ejemplo de Python. La mitad del SDK era invisible.

Pestañas TypeScript · Python · curl. En Autenticación, Ejecutar Mets, Contactos, Tareas y Errores. Funcionan sin JavaScript y se navegan con el teclado.

pip install meteor-ia

Ojo con una diferencia real: en Python las respuestas son diccionarios (run["output"], no run.output) y los métodos van en snake_case (send_message, create_note). Los ejemplos del portal salen de las firmas reales, no de traducir el de TypeScript.

El CLI ya ejecuta tareas. Antes cubría runs y eventos; ahora también tareas:

met tasks list
met tasks run tsk_123 --wait

--wait importa más de lo que parece. POST /tasks/:id/execute arranca la ejecución y devuelve enseguida, así que sin esperar el comando sale con código 0 por haber podido disparar, no por haber funcionado — en un cron, eso es un fallo que nunca te enteras. Con --wait el código de salida refleja el estado final.

Y si eres partner, el CLI ya te sirve. Una key de partner no tiene workspace, así que no tenía ningún camino en la terminal:

met partner leads --status won
met partner commissions --json

Son de solo lectura a propósito. Instala o actualiza con npm i -g @meteor.ia/cli y mira la guía del CLI.

El servidor MCP también creció: ahora son 16 tools, con met_execute_task y met_get_task_execution — antes un agente podía crear tareas y no ejecutar ninguna. Y el servidor es descubrible: https://developers.meteor.com.co/.well-known/mcp.json trae el endpoint, cómo autenticar y la lista de tools, generada del catálogo real.

v2.11.0

Los parámetros y los cuerpos del contrato dejan de estar mudos

El spec describía 383 parámetros sin una sola descripción. La referencia mostraba taskId y nada más, y saber si un {id} es un UUID o un entero era algo que se averiguaba llamando a producción a ver qué contestaba. Eso se cierra, y también mejora bastante lo que se documenta de los cuerpos que envías.

Los 383 parámetros están descritos. Los de ruta y los de query, en las dos superficies (41 más en la Partners API). No se escribieron uno por uno: esos 383 son 64 nombres distintos, así que el contrato los toma de un diccionario compartido y salen iguales en todas las operaciones. Un parámetro nuevo se describe una vez y aparece descrito en todos lados; si alguien agrega uno que no está en el diccionario, el generador lo reporta por nombre en vez de publicarlo mudo.

Cuando un endpoint quiere decir algo más específico, su propia descripción gana: el diccionario es el piso, no el techo.

Los cuerpos de las peticiones dicen mucho más. El contrato ahora se genera introspeccionando los tipos y los comentarios del código, no solo los nombres de los campos:

  • required pasó de 50 a 167 schemas. Antes, en la mayoría de los cuerpos no había forma de saber qué campo era obligatorio salvo mandarlo incompleto y leer el 400.
  • Las propiedades documentadas pasaron de 361 a 863, con 221 descripciones, más límites de longitud y ejemplos donde el código los declaraba.

Y una cosa que decidimos NO publicar. Al generar desde los tipos, 158 operaciones quedaron con un schema de respuesta que decía, literalmente, "esto devuelve un objeto". En la referencia eso se ve *igual que documentado* y no informa nada: quien lo lea no sabe ni un campo más que antes, pero cree que sí. Se podan; la respuesta 2xx sigue declarada, sin un cuerpo que finja.

Documentar de verdad lo que devuelve cada endpoint es el trabajo que sigue, y va de a uno —priorizado por el tráfico real de cada endpoint, no por intuición—. Preferimos que la referencia diga "todavía no está" antes que insinuar que sí.

v2.10.1

owner_kind admite METEOR, y se limpian dos schemas del contrato

Lo único que puede afectarte: owner_kind tiene un valor más.

En la Partners API, las tareas y los ítems de checklist de un proyecto declaran de quién es la responsabilidad del trabajo. Hasta hoy eran dos valores, PARTNER y CLIENT; ahora son tres:

owner_kind: "PARTNER" | "CLIENT" | "METEOR"

METEOR significa que el trabajo lo hace el equipo de Meteor. La situación existía y no existía la forma de decirla, así que se registraba como si fuera del partner.

Es un cambio aditivo: ninguna respuesta cambió de forma y los dos valores de siempre siguen significando lo mismo. Pero si tu código compara owner_kind contra una lista cerrada —un enum, un match exhaustivo, un switch sin rama por defecto— un valor nuevo puede hacerlo fallar. Conviene revisarlo antes de que te llegue el primer proyecto con tareas de Meteor. Si usas el SDK, actualízalo y el tipo ya lo trae.

Los enum cerrados son justamente la razón por la que esto se anuncia aunque del lado del servidor nada se haya roto: agregar un valor es compatible para quien lo emite y no siempre para quien lo lee.

Y dos schemas que salen de components, sin efecto para nadie:

  • SowItemDto — era el cuerpo de un endpoint interno de alcance de proyecto, que dejó de existir cuando el alcance y los hitos se unificaron en una sola lista. Nunca formó parte de una operación pública.
  • WhatsappWabaTargetDto — estaba declarado sin una sola propiedad y sin ninguna operación que lo usara. Era un artefacto de generación, no un contrato.

El conteo de operaciones —333 entre las dos superficies— no se movió.

v2.10.0

Los errores quedan documentados en el contrato, y el portal se puede usar

Hasta hoy el spec público describía 297 operaciones sin decir qué pasa cuando alguna falla: ni una sola respuesta de error documentada. Un dev tenía dos salidas, y las dos malas: llamar a ciegas contra producción, o leer los tipos del SDK en GitHub. Eso se cierra.

El catálogo de errores está en el contrato. Cada operación pública declara ahora sus respuestas 400, 401, 429 y 500, con el schema del cuerpo y un ejemplo real. La taxonomía es la de siempre —cinco type en lista cerrada, code en inglés, message en español— pero ahora la referencia interactiva la muestra en cada endpoint, en vez de esconderla en una guía.

  • error.type — authentication_error, invalid_request_error, rate_limit_error, agent_error, api_error. El SDK los mapea 1:1 a clases de excepción.
  • error.code — específico y creciente: invalid_api_key, missing_scope, quota_exceeded, test_mode_restricted…
  • request_id — guárdalo. Es buscable en tu Workbench y es lo primero que pide soporte.

Vale igual para la Partners API: el catálogo vive en un solo lugar, así que las dos superficies no pueden divergir.

La referencia ya puede ejecutar requests. Con el botón *Test Request* pegas tu key y pruebas cualquier endpoint sin salir del portal. Usa una key met_test_ mientras exploras.

Buscador. ⌘K (o /) en cualquier página del portal: busca en las guías, en sus secciones, en las 333 operaciones de los dos specs y en el changelog.

Dos guías nuevas:

  • Skills — 20 operaciones que no tenían ni una línea de narrativa. Activar del catálogo, guardar credenciales, probar antes de vincular, y por qué activar una skill no se la da a todos tus Mets.
  • CLI (met) — el CLI existía, estaba publicado en npm y no tenía página. Incluye met listen --forward, que reenvía los eventos de tu workspace a tu servidor local para desarrollar webhooks sin túneles.

El servidor MCP deja de prometer lo que no tiene. La tabla de capacidades de MCP se genera del catálogo real: son 14 tools sobre 6 dominios. La tabla anterior estaba escrita a mano y listaba ocho dominios, cuatro de ellos sin una sola tool — y como el catálogo se filtra por los scopes de tu key, una tool que no existe se veía igual que un permiso faltante.

Y varias cosas que estaban rotas a la vista: las guías mostraban el título dos veces, el menú lateral no tenía índice de secciones, en el teléfono había que scrollear toda la navegación antes de llegar al texto, y compartir un link del portal no generaba preview. El changelog ahora tiene feed Atom.

v1.5.0

Exporta e importa flujos como JSON ("Flows as Code")

Un flujo de automatización ahora es un artefacto de texto portable: expórtalo a JSON, versiónalo en git, compártelo entre workspaces o genéralo por código. La definición del canvas viaja con sus referencias cruzadas (Mets, skills, MCPs, colecciones, canales, sub-flujos) reescritas como marcadores estables y descritas en un bloque dependencies — nunca datos vivos ni credenciales.

# Exporta un flujo
met api GET /workspaces/$WS/flows/$FLOW_ID/export > bienvenida.flow.json

# Previsualiza el import en otro workspace (no crea nada)
met api POST /workspaces/$WS2/flows/import/preview -d @<(jq '{doc: .}' bienvenida.flow.json)
  • GET /workspaces/:workspaceId/flows/:id/export (automations:read) — devuelve el documento portable { schema_version, kind, flow, dependencies, content_hash }. Se exporta lo publicado (o el borrador si nunca se publicó). Las referencias a datos vivos (contactos, ejecuciones) se anulan con aviso; se detectan posibles secretos pegados en texto libre.
  • POST /workspaces/:workspaceId/flows/import/preview (automations:read) — dry-run que no muta: valida el JSON, chequea tipos de nodo y resuelve cada dependencia contra el workspace destino (auto por nombre / código de sistema), reportando lo que quedó sin resolver.
  • POST /workspaces/:workspaceId/flows/import (flows:write) — crea el flujo como borrador desactivado. bindings permite mapear a mano las dependencias que no matchearon (o omitirlas); las que quedan sin resolver dejan la referencia vacía con aviso, sin romper la importación.
  • Importación idempotente — import acepta target_flow_id: en vez de crear un duplicado, reescribe el borrador de ese flujo. Habilita el ciclo git-native (exportar → editar el JSON → reimportar sobre el mismo flujo). El preview informa existing_flow_id cuando ya hay un flujo con el mismo identificador, para elegir entre crear o actualizar.
  • Round-trip en el editor — "Copiar JSON" copia el subgrafo seleccionado (o todo el lienzo) al portapapeles; "Pegar JSON" lo fusiona en otro flujo del mismo workspace regenerando ids. Para cruzar workspaces se usa Exportar/Importar (que traduce las referencias a marcadores).

El formato reutiliza el motor de referencias de los Snapshots, así que un flujo exportado es honesto sobre lo que necesita para correr en otro lado.

v2.9.2

Un enlace nuevo para un adjunto, cuando lo necesites

Ahora que los adjuntos del hilo son privados, su enlace caduca a los 7 días. Eso está bien para leer el hilo —cada lectura trae enlaces recién emitidos— pero deja colgada a una integración que guarde referencias a documentos en su propio sistema: al octavo día, el enlace guardado no abre nada.

  • GET /partner/leads/:id/attachments/signed-url?storage_path=…
  • GET /partner/projects/:id/attachments/signed-url?storage_path=…
  • En el SDK: met.partner.leads.comments.signedUrl(leadId, storagePath) y su gemelo en proyectos, en TypeScript y en Python.

Devuelve el adjunto con un enlace recién firmado, más expires_in en segundos para que sepas cuánto te dura sin adivinarlo.

La regla, en una línea: guarda storage_path, no la URL. El storage_path no caduca nunca; la URL es de usar y tirar. Si ya guardaste URLs, no hace falta que migres nada — vuelve a pedirlas con el storage_path que viene en el mismo objeto.

Sin scope nuevo: monta el de lectura del objeto al que pertenece el hilo (partner:leads:read o partner:projects:read). Y el adjunto tiene que estar en ese hilo — un storage_path que no le pertenece devuelve 404, igual que uno que no existe.

v2.9.1

Los adjuntos del hilo dejan de ser públicos

Ayer, al anunciar el hilo de la relación, escribimos que los adjuntos quedaban en un bucket público y que no subieras por ahí nada que no pudieras compartir por link. Ya no es así: los archivos del hilo viven en un bucket privado y solo se entregan por URL firmada. Un GET sin credencial ya no abre nada.

Qué cambia para ti:

  • POST …/comments/upload ahora devuelve también bucket: es dónde quedó el objeto, y el servidor lo necesita para volver a firmar la URL cada vez que lees el hilo. Mándalo de vuelta en attachments, junto con el resto de la metadata, tal como lo recibiste.
  • La url que te devuelve el upload caduca. No la guardes como si fuera permanente: cada lectura del hilo trae una URL fresca. Lo que sí es estable es storage_path.
  • El campo type (siempre "file") ahora se acepta explícitamente. Si reenviabas la respuesta del upload completa, ya no te la rechaza.

Si hasta hoy armabas el objeto a mano con solo url y storage_path, sigue funcionando: bucket y type son opcionales, y los adjuntos que subiste antes se siguen leyendo.

v2.9.1

Paridad completa en los SDKs, y Tareas estrena guía

Auditamos las 297 operaciones públicas contra lo que realmente ofrecen los SDKs. Dos huecos, los dos cerrados:

  • met.variables.retrieve(id) — la única asimetría CRUD que quedaba: se podía listar, crear, actualizar y borrar una variable, pero no leer una sola por su id.
  • met.snapshots.submit(id) — enviar un snapshot propio a revisión editorial. El scope snapshots:publish existía en el contrato y no tenía superficie en ningún SDK: aparecía en la lista de scopes de tu key y no había forma de usarlo.

Con esto, TypeScript y Python cubren 297 de 297 operaciones, y ninguna ruta de los SDKs apunta a algo que no exista en el spec.

También estrena guía Tareas — 35 operaciones que hasta hoy solo existían en la referencia generada. Cubre el modelo (la tarea es la receta, la ejecución es el plato), los pasos, los disparadores, comentarios con adjuntos, vistas guardadas, y sobre todo las pausas para una persona: la diferencia entre aprobar un paso que el Met ya hizo y completar un paso que hiciste tú, y por qué las tres operaciones van contra el id de la ejecución y no el de la tarea.

Sabemos lo que falta y no lo escondemos: Skills (20 operaciones) sigue sin guía, y el CLI met cubre hoy run, runs, chat y listen — los dominios grandes (tareas, colecciones, contactos) todavía no tienen comando.

v2.9.0

Partners API — el hilo de la relación, con adjuntos

La conversación sobre una oportunidad y la de su proyecto son la misma. No es una decisión de la API: para Meteor, oportunidad, cliente y proyecto no son tres cosas sino la misma relación en tres momentos, y ahora la superficie pública lo refleja. Lo que escribiste mientras vendías sigue ahí cuando estás implementando — sin copiar nada, porque nada estaba en el lugar equivocado.

  • GET /partner/leads/:id/comments · GET /partner/projects/:id/comments — el hilo, del mensaje más viejo al más nuevo.
  • POST /partner/leads/:id/comments · POST /partner/projects/:id/comments — escribe un mensaje, con o sin adjuntos.
  • POST …/comments/upload — sube un archivo (multipart file) y devuelve su metadata para mandarla en attachments.
  • DELETE /partner/lead-comments/:id · DELETE /partner/project-comments/:id — borra un mensaje propio.
  • En el SDK: met.partner.leads.comments.* y met.partner.projects.comments.* (list · create · upload · delete), en TypeScript y en Python.

No hay scope nuevo. El hilo monta el de su dominio: leerlo pide partner:leads:read o partner:projects:read, escribirlo el :write correspondiente. Quien puede ver la oportunidad ve su conversación, y no antes — un scope aparte de "comentarios" habría dejado leer conversaciones de objetos que la key no puede ver.

Tres límites, dichos sin eufemismos:

  • Los adjuntos quedan en un bucket público: cualquiera con la URL abre el archivo, sin autenticación. No subas por ahí nada que no puedas compartir por link.
  • El tope por archivo es 25 MB (la superficie interna acepta más, pero ahí hay una sesión de por medio).
  • Las menciones no se pueden mandar por API: dependen de ids internos del equipo, y un id equivocado le notificaría a la persona equivocada. Salen en la lectura, como nombres.

También en esta versión: el SDK de Python alcanzó la paridad completa con el de TypeScript en met.partner — antes cubría seis rutas de solo lectura, ahora las 34 operaciones, incluidas escritura de oportunidades y proyectos, tareas, hitos, tickets y el hilo.

Todavía no: el hilo del cliente —el que no cuelga de una oportunidad ni de un proyecto— y los comandos de partner en el CLI met, que hoy opera sobre un workspace.

v2.8.0

Partners API — tickets de soporte

Soporte estrena superficie pública, y arranca por la API de partners: ya puedes abrir, responder y cerrar tickets desde tu propio portal.

  • GET /partner/tickets · GET /partner/tickets/:id (con el hilo de mensajes) · GET /partner/tickets/reasons, con el scope partner:support:read.
  • POST /partner/tickets · POST /partner/tickets/:id/messages · PATCH /partner/tickets/:id/status, con el scope partner:support:write.
  • En el SDK: met.partner.support.list/get/reasons/create/reply/updateStatus.

Con workspace_id el ticket se abre a nombre de un cliente de tu cartera y ese cliente lo ve en su Met; sin él es un ticket tuyo hacia Meteor. Es la pieza que te deja poner una mesa de ayuda de primer nivel en tu portal sin sacar al cliente de tu experiencia.

Estados: new · in_progress · waiting_client · resolved · closed.

Dos límites que la API respeta igual que el portal: las notas internas del equipo de Meteor nunca salen por esta superficie, y los tickets de prioridad crítica los gestiona solo Meteor.

Próximo: adjuntos y comentarios en oportunidades, proyectos y tickets.