Cambios recientes

Cambios de la API para quien integra, del más reciente al más antiguo. La versión es la misma que devuelve GET /health; lo que cambió para quien usa el panel está en las novedades del centro de ayuda.

2.144.02026-10-28

  • CRM con IA (función de plan crm_ia): nuevas rutas …/crm/ia — POST segmentos/desde-texto { texto } → { nombre, explicacion, filtro, total }; GET segmentos/sugeridos; GET clientes/:contactId (análisis de la IA e historial); POST clientes/:contactId/analizar; POST clientes/:contactId/copiloto; POST oportunidades/:id/sugerencia/aplicar y …/descartar; GET objeciones?dias=; GET pronostico.
  • CRM: GET/PUT …/crm/configuracion trae ia { disponible, activa, fuente, proveedor, modelo, autonomia, confianzaMinima, modelosDeMosend } y diasParaPerder; se guardan con iaActiva, iaFuente (MOSEND | PROPIA), iaProveedor, iaModelo, iaAutonomia (AUTO | SUGERIR), iaConfianzaMinima y diasParaPerder.
  • Contactos: filtros nuevos (listado y listas inteligentes) actividadEnDias, iaIntencion, iaInteres, iaObjecion, iaSentimiento e iaAnalizadoEnDias; los contactos traen iaIntencion, iaIntereses, iaObjecion, iaSentimiento, iaResumen, iaProximoPaso e iaAnalizadoAt; GET …/contacts acepta orden=puntaje.
  • CRM: GET …/crm/clientes/:contactId/puntaje → { guardado, total, temperatura (CALIENTE | TIBIO | FRIO), partes [{ etiqueta, puntos }] }. Las oportunidades pueden tener origen IA y sugerenciaIa; el contacto de una oportunidad trae puntaje.
  • Difusiones: el detalle trae resultadoEnVentas { recibieron, oportunidades, ganadas, montoGanado, compraron }.

2.143.02026-10-28

  • Difusiones: el máximo de filas de una audiencia por archivo (recipients) lo pone el plan; en Business y superiores, hasta 50.000 (antes 500 fijo). POST …/broadcasts acepta cuerpos de hasta 20 MB.
  • Difusiones: POST …/broadcasts/:id/send con más de 1.000 destinatarios no bloquea: la deja programada para ya, la envía el servidor y responde { enSegundoPlano: true, total }.
  • Difusiones a una lista: en templateVariables, {{contacto.nombre}} o {{contacto.nombre|respaldo}} dentro de un valor se reemplaza por el nombre de cada contacto (o por el respaldo si no tiene).

2.142.02026-10-28

  • Difusiones: freno por límite de Meta en todas, no solo en las creadas con porPartes. Al enviar, si la audiencia pasa del cupo de hoy, la difusión pasa a porPartes (sale lo que cabe y el resto en tandas); la respuesta de …/send trae porPartes: true. Si Meta rechaza por límite durante el envío (131048/130497, también los que llegan por webhook), se detiene: los rechazados vuelven a PENDING y sigue por partes 25 h después, o queda PAUSED con pausaMotivo LIMITE_DE_META si no llegó ninguno (respuesta con frenadaPorLimite: true).

2.141.02026-10-28

  • Difusiones: envío por partes. POST …/broadcasts acepta porPartes (bool) y tamanoDeTanda (1–100.000; vacío = el límite diario de Meta del número). La audiencia se fija al empezar y cada tanda manda lo que cabe en el cupo de ese momento; la siguiente sale 25 h después (24 h de Meta + 1 de margen). Los que esperan quedan PENDING (counts.pending y filtro pending en …/recipients) y el detalle trae partes { tandasEnviadas, tandasQueFaltan, tandasTotales, tamanoDeTanda, proximaTanda, pausaMotivo, cupo }.
  • Difusiones: estado nuevo PAUSED con pausaMotivo (MANUAL, CALIDAD, LIMITE_DE_META, CUPO_DEL_PLAN). Nuevos POST …/broadcasts/:id/pause y …/resume; …/send en una difusión por partes manda la siguiente tanda ya; …/cancel acepta PAUSED y deja omitidos a los que esperaban; …/retry-failed por partes devuelve los fallidos a la cola (respuesta con scheduledAt).
  • Difusiones: saltarYaRecibidos en POST …/broadcasts omite (SKIPPED) a quien recibió la misma plantilla en los últimos 30 días. Nuevo POST …/broadcasts/vista-previa { phoneNumberId, templateId, listId? | contactIds? | sourceBroadcastId + followUpAudience, tamanoDeTanda? } → { total, yaRecibieron, cupo, porPartes { tamanoDeTanda, primeraTanda, tandas, tandasSaltando } }. Por partes, la audiencia por archivo admite hasta 5.000 filas.

2.140.02026-10-27

  • Licencias: nuevo tipo de dato CORREO_PERSONAL en datoAdicionalTipo (productos y edición masiva). Solo acepta correos de proveedores gratuitos (Gmail, Outlook, Hotmail, Live, Yahoo, iCloud, Proton…); uno de empresa da 400. Se entrega por activación, como CORREO.
  • Licencias: en los tipos CORREO y CORREO_PERSONAL, un correo con pinta de error (gmial.com, hotmail.con, gmail.co) da 400 con la sugerencia («¿Quisiste decir …?»).
  • Licencias: forzarCorreo en …/sell, …/sell-cart, …/venta-manual, …/venta-manual-carrito y PATCH …/orders/:orderId/dato-adicional acepta un correo que no pasa esas reglas. Queda en datosPorLicencia[].aceptadosSinRegla [{ posicion, valor, motivo (EMPRESA | ERRATA), por, at }]. Las líneas de datosPorLicencia pueden traer tipo CORREO_PERSONAL.

2.139.02026-10-27

  • Licencias: el dato que pide un producto se separa en nombre corto (datoAdicionalLabel, por ejemplo «Correo»), tipo (datoAdicionalTipo: CORREO | TEXTO) e indicación para el cliente (datoAdicionalIndicacion, hasta 300 caracteres). Con tipo CORREO cada valor debe traer un correo (se acepta correo + contraseña) y el producto se entrega por activación salvo que tipoDeEntrega diga otra cosa. Las líneas de datosPorLicencia traen tipo. Los productos existentes se migraron solos: la indicación quedó con el texto que tenían.
  • Licencias: POST …/orders/:orderId/activaciones sin linea confirma todas las licencias listas del pedido y avisa al cliente en un solo mensaje, con un botón «Ver instrucciones» por producto en vez del enlace suelto.

2.138.02026-10-26

  • Licencias: entrega y reembolso por producto en pedidos de varios. POST …/orders/:orderId/items/:itemId/entregar { llaves?, mensaje?, notificar? } y POST …/orders/:orderId/items/:itemId/refund { reason?, destino? }. Un pedido DELIVERED con líneas sin deliveredAt está entregado parcialmente; POST …/orders/:orderId/completar-entrega en un carrito reparte las llaves entre las líneas pendientes. Las líneas traen refundedAt y refundCents y el pedido reembolsadoCents.
  • Webhooks: nuevos sale.item_delivered y sale.item_refunded (con itemId). sale.completed llega solo cuando no queda ningún producto por entregar. Los items traen id, deliveredAt, refundedAt, refundCents y refundTo, y pending indica si la línea sigue por entregar; nuevos deliveryComplete y refundedCents.
  • Reportes: las ventas cuentan el neto de lo reembolsado por productos sueltos.
  • Licencias: productos de activación. DigitalProduct.tipoDeEntrega (LLAVE | ACTIVACION; null = se deduce: si el dato que pide es un correo, ACTIVACION). POST …/orders/:orderId/activaciones { linea, posiciones?, nota?, notificar? } confirma la activación del correo de una o varias licencias: ese correo queda como su licencia (licenseKeys y customerData.licenseKey) y al cliente se le avisa con la fecha de vencimiento. datosPorLicencia trae entrega y activadas. Un dato ya activado no se puede editar.
  • Licencias: al completar una entrega con varias unidades, si no hay líneas en blanco cada renglón es una licencia. Un carrito donde todo lo entrega un asesor queda PAID (por entregar) hasta que sale el primer producto.

2.137.02026-10-26

  • Webhooks: nuevo formato SIMPLE por webhook (format: SIMPLE en POST/PATCH …/webhooks-outbound): solo el sobre (type, eventId, timestamp, organizationId, data) y, en las ventas, data con payment, customer e items[{ productId, sku, name, variant, quantity, unitPriceCents, pending, dataLabel, licenses[{ key, data }] }] y dataComplete. Mismas cabeceras y firma.
  • Webhooks de venta (formato completo): items llega siempre como lista, también con un solo producto, y cada ítem trae product.sku. contact.name ya no llega vacío (usa el nombre del perfil, como customer.name).
  • Fuera de horario, una venta pagada que entrega un asesor (o un comprobante en revisión) no silencia al bot: queda una tarea y a la hora de apertura la conversación pasa sola a los asesores.

2.136.02026-10-26

  • Saldo a favor de los clientes: nuevo módulo …/saldo. GET …/saldo/:contactId (total por moneda y bolsillos por marca), GET …/saldo/:contactId/movimientos (paginado con antes), POST …/saldo/:contactId/ajuste { montoCents (+ abona, − descuenta), currency, perfilDeCobroId?, motivo } y POST …/saldo/:contactId/devolucion { saldoId, montoCents, motivo? }. El saldo es del contacto: el mismo desde cualquier número o canal.
  • Licencias: POST …/orders/:orderId/refund acepta destino (DINERO por defecto, o SALDO para dejarlo a favor del cliente) y la respuesta trae refundDestino. Nuevo método SALDO en …/conversations/:conversationId/sell y …/sell-cart, POST …/orders/:orderId/pagar-con-saldo (pedido pendiente sin pasarela viva, o fiado), POST …/inbox/payments/:pagoId/abonar-a-saldo { contactId, perfilDeCobroId?, nota? } y POST …/saldo/recargas { contactId, montoCents, conversationId?, perfilDeCobroId? }.
  • Licencias: GET/PUT …/license-delivery/settings con saldoCompartidoEntreMarcas (por defecto false: lo que entra en una marca se gasta solo en esa marca). Los pagos recibidos tienen el estado ABONADO_A_SALDO y los pedidos pagados con saldo, provider saldo y paymentMethod SALDO (paymentChannel.type saldo en los webhooks).
  • Permiso y alcance nuevo saldo:gestionar: reembolsar y cancelar ventas, y abonar, ajustar y devolver saldo. Reembolsar y cancelar aceptan license-delivery:write o saldo:gestionar.
  • Webhooks: nuevo customer.balance_changed y refundTo en sale.refunded.
  • CRM: la ficha del cliente trae saldo (compartido, porMoneda, bolsillos), la línea de tiempo trae los movimientos (tipo saldo), la cuenta trae resumen.saldoAFavor, y la fusión de duplicados junta los bolsillos.
  • Corregido: el carrito por …/sell-cart rechazaba los métodos TARJETA y PAYPAL, y un carrito por PayPal quedaba con provider wompi.
  • Licencias: el dato que pide un producto va UNO POR LICENCIA. …/sell, …/sell-cart (por ítem), …/venta-manual y …/venta-manual-carrito aceptan datosAdicionales: string[] (manda sobre datoAdicional; con cantidad N, N valores; un correo repetido en la misma línea da 400). PATCH …/orders/:orderId/dato-adicional acepta cambios [{ linea, posicion, valor }] o un valor con varios correos que llena los que faltan. Los pedidos traen datosPorLicencia [{ itemId, productId, producto, etiqueta, valores }].
  • Webhooks: sale.completed, sale.paid y sale.refunded traen customerData [{ label, value, licenseKey }] (y por ítem en un carrito) y customerDataComplete. sale.paid trae trigger (PAYMENT o DATA_COMPLETED) y sale otra vez cuando se completan los datos de una venta pagada. Con incluirLlaves en false también se quita licenseKey.

2.135.02026-10-26

  • Webhooks: nuevo evento sale.refunded al registrar el reembolso de una venta (POST …/license-delivery/orders/:orderId/refund). Mismo payload que sale.completed con status REFUNDED, refundedAt, refundReason y las llaves revocadas en licenseKeys (se quitan si el webhook tiene incluirLlaves en false).

2.134.02026-10-26

  • Licencias: nuevo método PAYPAL (solo ventas en USD) en POST …/license-delivery/conversations/:conversationId/sell y …/sell-cart, y en …/orders/:orderId/cambiar-medio (medio: paypal). Cada pedido lleva su propio enlace de PayPal por el total y se confirma solo; el pedido trae paypalLinkId, paypalCaptureId, paypalFeeCents y paypalNetCents.
  • Licencias: GET y PUT …/license-delivery/paypal (conectar con clientId y secret; Mosend prueba las credenciales y registra el aviso de pagos) y POST …/license-delivery/orders/:orderId/paypal/verificar con { transaccion } (el ID de transacción de PayPal del cliente: confirma el pedido si el pago está completo, en USD, cubre el total y no se usó antes).
  • Marcas de cobro: aceptaPaypal y «paypal» en ordenDeMedios. El webhook sale.paid informa el canal como pasarela con bank «PayPal».
  • Webhooks: sale.paid llega en cada pago (pasarela, transferencia validada, confirmación manual o fiado pagado), una sola vez por pedido, y trae customer { name, email, phone } y product.sku.
  • Webhooks: todo evento trae eventId (también en el header X-Mosend-Event-Id), que no cambia entre reintentos. POST y PATCH …/webhooks-outbound aceptan incluirLlaves (por defecto true): en false los eventos de ventas llegan sin licenseKeys, oldKey ni newKey.

2.133.02026-10-26

  • Cuentas: …/crm/empresas son ahora todos los clientes a los que se les factura. Cada cuenta trae tipo (EMPRESA con NIT o PERSONA con cédula); POST y PATCH lo aceptan y nit guarda el documento (NIT sin dígito de verificación o la cédula). Cada cliente de facturación (…/sales/billing-profiles) queda solo en la cuenta de su documento al crearse o cambiarse.
  • Cuentas: GET …/crm/empresas acepta tipo y razonSocialId (solo las cuentas a las que se les vendió desde esa razón social) y cada fila trae razonesSociales [{ id, nombre }] y _count.perfilesDeFacturacion. GET …/crm/empresas/:id trae perfilesDeFacturacion, las facturas de esos clientes (no solo las de sus contactos), razonSocial en cada factura y cotización, y resumen.porRazonSocial [{ razonSocialId, nombre, moneda, facturas, facturadoCents, licencias, licenciasCents, cotizaciones }].
  • Razones sociales: nuevo GET …/crm/razones-sociales (id y nombre, la predeterminada primero; basta contacts:read). GET …/contacts, …/contacts/export y las listas inteligentes (smartFilter) aceptan vendidoDesde con el id de una razón social.

2.131.02026-10-25

  • CRM: nuevo módulo …/crm. Contactos con duenoUserId, empresaId, etapa (PROSPECTO, CLIENTE, RECURRENTE, INACTIVO), puntaje, comprasCount, gastoTotal y ultimaCompraAt. PATCH …/crm/clientes/:contactId cambia dueño, empresa, etapa y campos (se mezclan con los que ya tiene; null borra); POST …/crm/clientes/masivo los cambia a varios. GET …/crm/clientes/:id/ficha y …/linea-de-tiempo?antes&limite (todo lo que pasó con el cliente, paginado hacia atrás).
  • CRM: campos definidos con GET, POST, PATCH y DELETE …/crm/campos (tipo TEXTO, NUMERO, FECHA, LISTA, SI_NO, CORREO, TELEFONO o URL; el valor vive en attributes[clave]), GET …/crm/campos/sugeridos y POST …/crm/campos/unificar. Empresas con …/crm/empresas (consultar-nit trae los datos de la DIAN), duplicados con GET …/crm/duplicados y POST …/crm/duplicados/fusionar, y GET/PUT …/crm/configuracion.
  • Contactos: GET …/contacts y …/contacts/export aceptan duenoUserId (o ninguno), empresaId (o ninguna), etapa, campos (JSON {clave: valor}), compraEnDias, sinCompraDias, gastoMin y puntajeMin, y el listado trae dueno y empresa. Nuevo POST …/contacts/import/preview (columnas, muestra y mapeo sugerido) y POST …/contacts/import y …/contact-lists/:id/import aceptan mapeo (JSON columna → phone, name, email, empresa, empresa_nit, dueno, etapa, campo:<clave> o ignorar).
  • CRM avanzado (función de plan crm_avanzado): embudos y etapas (…/crm/embudos, …/crm/etapas), oportunidades (…/crm/oportunidades, tablero, mover, ganar, perder, reabrir), cadencias de seguimiento (…/crm/cadencias, inscribir, …/crm/inscripciones/:id/detener), automatizaciones (…/crm/automatizaciones) y GET …/crm/reportes/embudo. GET …/crm/reportes/clientes en todos los planes.
  • Listas: POST y PATCH …/contact-lists aceptan smartFilter (lista inteligente: los mismos filtros del listado de contactos); sus miembros se calculan al pedirlos y la difusión los resuelve al enviar. Una lista inteligente responde 400 si se le agregan o quitan miembros a mano.
  • Tareas: aceptan tipo (TAREA, LLAMADA, MENSAJE, REUNION, CORREO), oportunidadId, repetir (DIARIA, SEMANAL, MENSUAL) y repetirHasta; GET …/tasks filtra por desde, hasta, tipo y oportunidadId. Notas: aceptan menciones (ids de miembros) y adjuntos, que se suben con POST …/contacts/:id/notes/adjuntos.
  • Webhooks: nuevos contact.created, contact.updated, deal.created, deal.stage_changed, deal.won, deal.lost, task.created, task.completed y note.created.
  • Permisos y alcances nuevos: contacts:read_all (sin él, un rol ve solo los clientes y oportunidades de los que es dueño; no aplica a claves de API), deals:read, deals:write y crm:config.
  • Agenda: los servicios (…/agenda/types) aceptan y devuelven price, currency, color, modality (PRESENCIAL, VIRTUAL o DOMICILIO), location, meetingUrl, category, sortOrder, bufferBeforeMin (margen antes; bufferMin es el de después) y slotIntervalMin (cada cuánto se ofrecen horarios). staffUserIds fija quiénes atienden; con varios, cada horario sale con el primero que lo tiene libre. staffUserId sigue llegando como el primero de la lista. Configurar profesionales exige la función de plan agenda_avanzada.
  • Agenda: GET …/agenda/slots trae staffUserId en cada horario, y POST …/agenda/appointments sin staffUserId deja la cita con esa persona.
  • Agenda: POST …/agenda/exceptions acepta dateTo (rango de días) y startMinute / endMinute (bloquear unas horas). Responde la primera fila más creadas. PATCH …/agenda/settings acepta bloquearFestivos para bloquear solos los festivos de Colombia.
  • Agenda: nuevo POST …/agenda/preset con tipo salon, spa, consultorio, asesoria o clases: crea servicios de ejemplo, horario y festivos sin pisar lo que ya hay.
  • Webhooks: nuevos appointment.completed y appointment.no_show al marcar una cita como atendida o como no asistió.
  • Agenda: PATCH …/agenda/settings acepta paginaPublica, paginaSlug, paginaPhoneNumberId y paginaMensaje (página pública de reservas en app.mosend.dev/reservar/<paginaSlug>), reminder2HoursBefore / reminder2TemplateName / reminder2TemplateLang y los mismos con 3 (requieren agenda_avanzada), cancelarHastaHoras (plazo para que el cliente cancele o reprograme por su cuenta) y noShowAutoHoras (marcar solas las inasistencias, con su webhook appointment.no_show).
  • Agenda: nuevo GET …/agenda/contacts/:contactId/resumen con atendidas, inasistencias, canceladas, agendadas y la próxima cita. Las citas traen origen: PANEL, BOT, FLUJO, PAGINA o WHATSAPP_FLOW.
  • Agenda: los servicios aceptan capacity (cupos por horario: varias personas en la misma clase o mesa) y anticipoTipo / anticipoValor (PORCENTAJE del precio o valor FIJO; requieren agenda_avanzada). Las citas traen seats, anticipoCents y cobroId, y un estado nuevo: PENDING_PAYMENT (apartada esperando el anticipo; ocupa el horario y pasa a CONFIRMED al pagarse o a CANCELLED si el cobro vence). GET …/agenda/slots acepta seats y devuelve cuposLibres. POST …/agenda/appointments acepta seats y cobrarAnticipo.
  • Agenda: lista de espera con GET, POST y DELETE …/agenda/lista-de-espera. Cuando se cancela una cita, el horario se le ofrece al primero de la fila por WhatsApp. PATCH …/agenda/settings acepta anticipoMinutos, anticipoTrasInasistencias, esperaMinutos y esperaTemplateName / esperaTemplateLang.
  • Agenda: los servicios aceptan preguntas (formulario: [{ id, texto, tipo TEXTO | OPCION | SI_NO, opciones, obligatoria }]) y volverEnDias («agenda tu próxima»). POST …/agenda/appointments acepta respuestas por id de pregunta; reservas del bot exigen las obligatorias. Las citas traen respuestas [{ pregunta, respuesta }]. PATCH …/agenda/settings acepta encuestaTrasCita y volverTemplateName / volverTemplateLang.
  • Agenda: nuevo GET …/agenda/reporte?desde&hasta (por defecto 30 días) con totales, tasa de inasistencia y de cancelación, ingresos estimados, anticipos cobrados, clientes nuevos y recurrentes, y desglose por servicio, por profesional (con ocupación), por origen y por día.
  • Agenda: citas recurrentes con repetir { cadaDias: 7 | 14 | 21 | 28 | 30, veces: 2 a 12 } en POST …/agenda/appointments (responde serie { id, creadas, omitidas }); PATCH …/appointments/:id/cancel acepta serie: true. Las citas traen serieId, paqueteId y direccion (servicios a domicilio, obligatoria cuando reserva el bot).
  • Agenda: recursos compartidos (salas, equipos) con GET, POST, PATCH y DELETE …/agenda/recursos, y recursoId en los servicios. Paquetes de sesiones con GET, POST y DELETE …/agenda/paquetes: las citas del cliente usan el paquete vigente y cada atendida o no asistida gasta una sesión. PATCH …/agenda/google acepta crearMeet.

2.129.02026-10-22

  • Licencias: POST …/conversations/:id/sell, …/sell-cart, …/venta-manual y …/venta-manual-carrito aceptan datoAdicional (por línea en los carritos) y datoAdicionalDespues. Si el producto exige su dato adicional y no viene, responden 400, salvo con datoAdicionalDespues: true, que deja el pedido con el dato pendiente.
  • Licencias: nuevo PATCH …/license-delivery/orders/:orderId/dato-adicional con { valor } para completar el dato adicional pendiente de un pedido.

2.128.02026-10-22

  • Conversaciones: nuevo POST …/conversations/:id/tomar-hilo — cuando otra app (el agente de IA de Meta u otro proveedor) es dueña del hilo por el enrutamiento de conversaciones de Meta, lo toma para que Mosend pueda responder. Solo funciona si la empresa eligió a Mosend como socio de escalamiento. La conversación trae hiloDeOtraAppAt, hiloDeOtraAppRol y hiloResumen; un envío rechazado con 131070 marca hiloDeOtraAppAt.
  • Cotizaciones: el listado trae origen (PANEL o BOT). Las de origen BOT las emitió el agente de IA por WhatsApp o el chat web.

2.124.02026-10-16

  • Empresas: la emisora de facturación electrónica es ahora la empresa de la organización, para cotizar y facturar. PUT …/sales/einvoicing/config acepta razonSocial, direccion, telefono, correo, ciudad, sitioWeb, logoMediaId, cotFormasDePago, cotCondiciones, cotNotas, cotVigenciaDias y marcaIds (marcas que trabajan con la empresa), y nueva: true para crear una (sin configId se edita la predeterminada). Los datos de la empresa no exigen el módulo de facturación electrónica; la conexión DIAN sí. GET …/einvoicing/companies trae esos campos, marcas y facturaElectronicamente.
  • Facturación: nuevo GET …/sales/einvoicing/companies/sugerida?conversationId|customerOrderId|orderId (desde qué empresa se propone facturar). POST …/einvoicing/license-orders/invoice acepta configId. Sin configId se factura desde la empresa de la cotización del pedido, la de la marca o la predeterminada que facture electrónicamente. GET …/einvoicing/invoices filtra por configId.
  • Facturación: POST …/sales/einvoicing/validate acepta configId y, con solo el token, devuelve nit (del token), nitNoCoincide, creditNotePrefix y resolutions con dateTo, nextConsecutive y environment (SETP = habilitacion). Ya no hace falta idSoftware. Sin configId, GET …/einvoicing/config devuelve la empresa que factura electrónicamente (antes, la predeterminada a secas).
  • Cotizaciones: POST y PUT aceptan empresaId (manda sobre perfilDeCobroId). GET …/cotizaciones/empresas devuelve { empresas: [{ empresaId, nombre, razonSocial, nit, predeterminada, configurado, marcas }], sugerida }, y ?empresa= del listado filtra por empresa. Se retiran GET/PUT …/cotizaciones/emisor: esos datos son de cada empresa.

2.123.02026-10-15

  • Conversaciones: PATCH …/conversations/:id/status con {"status":"closed"} hecho por una persona (sesión de usuario) deja unreadCount en 0. Con una API key o un token OAuth el cierre no toca unreadCount.

2.122.02026-10-15

  • Cotizaciones: POST y PUT …/cotizaciones aceptan perfilDeCobroId, la empresa (marca) que emite: el id de una marca, null para los datos de la organización, o sin el campo para lo de antes (la marca del número de la conversación; al editar, la que ya tenía). Una marca de otra organización responde 400. El listado trae perfilDeCobroId y acepta ?empresa=<id de la marca>|ORGANIZACION.
  • Cotizaciones: nuevo GET …/cotizaciones/empresas?conversationId= — la organización y cada marca, con configurado (si ya tienen datos de emisor), y sugerida: la empresa que se propone para esa conversación.

2.121.02026-10-14

  • Conversaciones — ajustes de mensajería (GET/PATCH …/conversations/messaging-settings): nuevo markReadOn ("ABRIR" | "ATENDER", por defecto "ABRIR"). Decide cuándo el panel marca una conversación como vista: al abrirla o al empezar a responderla. Cualquier otro valor responde 400.

2.120.32026-10-14

  • Conversaciones: PATCH …/conversations/:id/status con {"status":"closed"} ya no responde 400 (PrismaError «Error creating UUID») cuando se llama con una API key o un token OAuth. Con OAuth el cierre queda a nombre de la persona que autorizó la aplicación (closedByUserId); con API key, closedByUserId queda en null. No hay que enviar ningún campo adicional.
  • Lo mismo al cambiar de plan por API (PATCH /plans/organizations/:orgId/plan y cancel-subscription) con una credencial de integración.

2.120.02026-10-14

  • Registro con código por WhatsApp: el límite (5 por teléfono, 10 por IP en una hora) cuenta solo los envíos que salieron, y el 400 dice en cuánto se puede volver a pedir el código.

2.119.02026-10-13

  • Licencias — venta manual (POST …/conversations/:conversationId/venta-manual y /venta-manual-carrito): nuevo medio ("llave" | "llave:<id>" | "cuenta:<id>") para la venta ya pagada. El pedido queda con ese medio y confirmedBy MANUAL; paymentChannel del webhook deja de decir «Manual».

2.118.02026-10-13

  • Webhooks: nuevo evento sale.paid cuando se paga una venta ya entregada (fiado), sola o en un cobro agrupado. Mismo payload que sale.completed más confirmedBy y groupedCharge. sale.completed agrega esos dos campos. El fiado vendido por transferencia ahora emite sale.completed al entregarse.
  • Cobros agrupados: POST …/cobros-agrupados acepta medio ("llave:<id>" | "cuenta:<id>"); POST …/cobros-agrupados/:id/marcar-pagado acepta orderIds (pago parcial), medio y avisar; nuevo POST …/cobros-agrupados/pago-registrado para registrar un pago hecho por fuera sin enviar el cobro.
  • Planes: al vencer la prueba de un plan de pago sin pagar el primer mes, la organización pasa a TRIAL_EXPIRED. POST /plans/organizations/:orgId/cancel-subscription funciona con la organización bloqueada, anula la factura del plan sin pagar y devuelve excedido cuando el uso supera los límites del gratuito.

2.117.02026-10-13

  • Plan y límites: GET /organizations/:orgId/plan-limits trae vigencia { hasta, esPrueba, porPagar }: hasta cuándo está PAGADO el plan. plan.nextPlanRenewalAt sigue siendo hasta dónde se facturó (con la renovación facturada por adelantado y sin pagar, no es lo mismo).

2.116.02026-10-12

  • Licencias — venta del asesor (POST …/conversations/:conversationId/sell y /sell-cart): nuevo enviarCobro (boolean, por defecto true). Con entregarYa: true y enviarCobro: false el fiado se entrega sin mandarle al cliente cómo pagar. /sell-cart ahora respeta transferAccountId (antes se ignoraba y se cobraba a la llave).
  • Licencias — POST /license-delivery/orders/:orderId/cambiar-medio acepta fiados (entregados y por cobrar), solo hacia "llave" | "transferencia" | "cuenta:<id>": mismo pedido y mismo monto. "tarjeta", "nequi_app" y "binance" devuelven 400 para un fiado.
  • Licencias — ajustes: receiptAiMaxCents (centavos, null = sin tope; de fábrica 20000000). En modo IA, por encima de ese monto el comprobante lo revisa una persona cuando el banco no puede confirmarlo.
  • Pagos recibidos: los comprobantes pueden traer veredicto ESPERA_BANCO (esperan el aviso del banco con su cifra; si no llega en 15 minutos pasan a REVISAR). La lectura de la IA incluye hora.

2.114.02026-10-10

  • Licencias — ajustes: receiptMode acepta "IA" (verificación de comprobantes con IA) y se agregan receiptAiSource ("MOSEND" | "PROPIA"), receiptAiProvider y receiptAiModel. Con "PROPIA" el proveedor tiene que estar configurado y encendido en /bot/ai-providers.
  • Pagos recibidos: los comprobantes traen veredicto (APROBADO_IA | REVISAR), motivoInterno y lectura (fecha, banco, destino y referencia que leyó la IA).
  • Licencias — pedidos: un pago por transferencia que llega después de vencido el pedido lo revive si ningún pedido vivo espera esa cifra. Los fiados ya no reservan su monto.

2.113.02026-10-09

  • Licencias — fiado: una venta con entregarYa de un producto sin llaves o de entrega asistida queda PENDING_PAYMENT con paymentPending true (fiado por entregar) hasta que se completa con POST /license-delivery/orders/:orderId/completar-entrega; ya no se marca DELIVERED al crearse. Los fiados abiertos no vencen.
  • Licencias — ventas manuales fiadas (pagado: false) llevan paymentAmountCents: su pago por transferencia se concilia solo, sin ventana de tiempo.
  • Cobros agrupados: cada pedido de GET …/cobros-agrupados trae fiado y montoCents. Si se paga por separado un pedido de un cobro abierto, el cobro pasa a ANULADO y se crea otro con lo que falta.

2.112.02026-10-09

  • Licencias — pedidos: POST /license-delivery/orders/:orderId/cambiar-medio sirve para cualquier pedido pendiente, no solo los que esperan transferencia. medio acepta "llave" | "transferencia" | "cuenta:<id>" | "tarjeta" | "nequi" | "nequi_app" | "daviplata" | "binance", y nequiPhone para "nequi_app". "nequi" usa primero la cuenta Nequi de transferencia de la marca y deja la solicitud a la app de respaldo.
  • Licencias — pedidos: a cuenta, llave o tarjeta el pedido es el mismo; a "nequi_app", "binance" o a tarjeta con menos de 30 minutos de enlace se cancela y se crea otro con el mismo precio. La respuesta trae pedidoNuevo y numeroAnterior; order es el pedido que queda esperando el pago.
  • Cotizaciones en PDF: /organizations/:orgId/cotizaciones (crear, editar, enviar por la conversación, duplicar, convertir en pedido, PDF y enlace firmado). Solo responden si el plan de la organización incluye Cotizaciones.

2.102.02026-10-03

  • Licencias — pago con tarjeta: method "TARJETA" en la venta (checkout, conversación y carrito) manda al cliente un botón con el enlace de pago de Wompi, válido 24 h. El pedido trae checkoutUrl. Se confirma buscando el pago por la referencia del pedido, sin depender del webhook. Requiere wompiTarjetaEnabled en los ajustes; nombreTarjetaPasarela le da nombre en reportes y webhooks.
  • Licencias — pedidos: POST /license-delivery/orders/:orderId/cambiar-medio acepta medio "tarjeta" para pasar a tarjeta un pedido que esperaba transferencia. selling-readiness incluye wompi:TARJETA en medios[].
  • Webhooks salientes: en los pagos con tarjeta, paymentChannel lleva type "pasarela", name «Tarjeta» (o el que definas) y bank «Wompi».
  • Informes: los endpoints con período (portada, ventas, actividad, bot, encuestas, licencias) aceptan desde y hasta (YYYY-MM-DD, días completos en la zona horaria de la organización) además de dias.

2.100.02026-10-03

  • Informes: GET /reports/ventas (solo propietario y administradores) — ingresos por día, semana o mes contra el período anterior, por medio de pago, por agente del bot y por asesor (vendió y cerró), productos, marcas, canales, tiempos, horas pico, clientes nuevos y recurrentes, cancelados y vencidos con motivo, y lo pendiente de hoy. Filtros: desde, hasta, agrupar, moneda, perfilId, phoneNumberId, agentId, userId, productId.
  • Licencias: cada pedido trae origenVenta (BOT | ASESOR | PANEL | API), vendidoPorAgentId y vendidoPorUserId, aparte de confirmadoPorUserId (quién confirmó el pago).

2.91.0 – 2.99.02026-10-02

  • Webhooks salientes: sale.completed trae paymentChannel {type, id, name, bank, account, confirmedBy} — por qué cuenta, llave, pasarela o Binance entró el dinero, con el nombre que la organización le dio. paymentMethod no cambia. Ver el payload completo en Webhooks salientes.
  • Contactos: GET /contacts/export devuelve todos los contactos que coinciden con los filtros del listado (q, channel, tagId, optInStatus, country, language, hasConversations, lastActivityDaysGt), sin paginar.
  • Licencias — medios de cobro: GET /license-delivery/selling-readiness incluye medios[] (llave, cada cuenta, wompi:NEQUI, wompi:DAVIPLATA, binance) en el orden de la marca; GET /license-delivery/orders trae medio en cada pedido y analytics trae porMedio.
  • Licencias — pedidos: POST /license-delivery/orders/:orderId/cambiar-medio { medio: "llave" | "cuenta:<id>", avisarCliente } cambia la cuenta o llave de un pedido que espera transferencia (mismo pedido y valor).
  • Licencias — confirmar a mano: confirm-transfer y marcar-pagada aceptan { medio, comprobanteMediaId }; POST /license-delivery/orders/:orderId/captura-de-pago sube la captura. El pedido guarda confirmadoComo (AVISO | COMPROBANTE | MANUAL) y quién lo confirmó; GET del pedido devuelve pruebaDelPago.
  • Licencias — marcas que cobran: /license-delivery/perfiles-de-cobro (CRUD + /resumen), correos de avisos por llave en /license-delivery/buzones (CRUD + /probar) y cobro libre sin producto en POST /license-delivery/cobros-libres.
  • Ajustes de licencias: nombreBinance, nombreNequiPasarela y nombreDaviplataPasarela (cómo se llaman esos medios en reportes y webhooks).
  • Facturas enviadas al cliente: el pie lleva cada producto con su valor, el IVA cobrado y el total; GET /messages/:messageId/media sirve el PDF de las facturas enviadas.

2.89.0 – 2.90.12026-10-01

  • Números: POST /phone-numbers/:id/prueba-de-conexion abre una prueba de ida y vuelta (texto y enlace para escribirle al número) y GET /phone-numbers/:id/prueba-de-conexion/:codigo devuelve su estado (esperando, recibido, respondido, fallo, vencida).

2.81.0 – 2.88.02026-09-30

  • Límite de mensajes de Meta: GET /messaging-limit devuelve por portafolio el nivel, los clientes contactados con plantilla en 24 h y los disponibles; se actualiza a diario y con los avisos de Meta.

2.78.0 – 2.80.22026-09-29

  • Licencias — llaves de cobro: /license-delivery/transfer-keys (CRUD, /activate y /qr). Varias llaves (Bre-B, Nequi, Bancolombia), una activa para las ventas nuevas.
  • Licencias — cobro agrupado: /license-delivery/cobros-agrupados (crear, /pendientes, /reenviar, /anular, /marcar-pagado) y POST /license-delivery/inbox/payments/:pagoId/match-cobro para saldar varios pedidos con un solo pago.
  • Agenda: PATCH /agenda/appointments/:id completa una cita (enlace, correo de la invitación, notas), POST /agenda/appointments/:id/pedir-correo pide el correo por WhatsApp y GET /agenda/counts da el contador de hoy.

2.64.0 – 2.72.22026-09-25

  • Encuesta de satisfacción: GET/PATCH /surveys/config y GET /surveys/results (nota media, tasa de respuesta, por opción y por asesor).
  • Memoria del bot: PATCH /bot/knowledge/:id/agentes define qué agentes leen cada documento (o todos). Cada agente lee solo sus documentos y los compartidos.

2.60.0 – 2.62.02026-09-23

  • Grupos de WhatsApp: /whatsapp-groups (crear, listar, detalle, eliminar), enlace de invitación, participantes y solicitudes de ingreso. El id y el enlace del grupo llegan por webhook de Meta.
  • Mensajes: POST /messages/:messageId/revelar muestra el contenido de un mensaje que el cliente eliminó.
  • Anuncios: GET /ad-campaigns lista los anuncios que trajeron conversaciones con lo que vendieron; PATCH /ad-campaigns/:id dice qué vende cada uno, quién atiende y qué etiqueta poner.

2.58.0 – 2.59.02026-09-22

  • Licencias — varias monedas: PUT /license-delivery/products/:productId/prices fija el precio del producto en otras monedas; POST /license-delivery/conversations/:conversationId/cart-preview dice a cuánto sale cada línea en la moneda del cobro antes de cobrar.

2.56.1 – 2.57.02026-09-21

  • Bot: GET /bot/resumen/dia — en qué se fue la IA un día concreto (por agente, por modelo y por motivo), cortado en la zona horaria de la organización.

2.53.1 – 2.54.02026-09-16

  • Webhooks salientes: los 27 eventos de entonces llegan con el mismo sobre { type, organizationId, timestamp, data }. Los campos que algunos mandaban sueltos en la raíz siguen ahí por compatibilidad; data es el lugar canónico.

2.49.0 – 2.53.02026-09-15

  • Números: GET /phone-numbers/service-usage (mensajes de servicio del mes contra los 1.000 gratis de Meta), GET /phone-numbers/:id/impacto-al-archivar y GET /phone-numbers/:id/historial-de-conexion (desconexiones y reconexiones con su motivo).
  • Plantillas: POST /templates/:id/copiar crea la misma plantilla en otra cuenta de WhatsApp.

2.43.1 – 2.48.02026-09-14

  • Plantillas: POST/DELETE /templates/:id/header-media guarda la cabecera predeterminada (imagen, video o PDF); los envíos que no traen archivo la usan solos.
  • Licencias: GET /license-delivery/inbox/payments/:pagoId/reassign-options y POST …/reassign mueven un pago ya conciliado a otro pedido.
  • Webhooks salientes: sale.completed de una entrega asistida sale con las llaves que registró el asesor.

2.40.0 – 2.43.02026-09-12

  • Licencias — pagos: GET /license-delivery/payments-inbox (avisos del banco y comprobantes en una lista) y POST …/discard; comprobantes en /license-delivery/receipts (aprobar, rechazar) y GET /license-delivery/orders/:orderId/receipts.
  • Licencias — cuentas de transferencia: /license-delivery/transfer-accounts (CRUD y /reorder).
  • Ventas: la factura le llega al cliente por WhatsApp al emitirse (documento dentro de la ventana de 24 h; fuera, con la plantilla configurada).

2.39.02026-09-11

  • Grupos de facturación: PATCH /billing-group/:targetOrgId/ai-limits fija el tope de gasto de IA de una organización del grupo (solo la matriz).

2.34.0 – 2.37.02026-09-09

  • Números: PATCH /phone-numbers/:id cambia el color con el que se distingue el canal en el inbox.
  • Licencias — en lote: POST /license-delivery/products/bulk, /products/bulk-price (porcentaje, monto o fijo, con vista previa), /products/bulk-delete y PUT /license-delivery/price-lists/:priceListId/items/bulk.
  • Reportes: GET /reports/portada (qué espera ahora y cómo va la atención por día) y GET /bot/resumen (quién atendió, acciones y cierres, contra el período anterior).

2026-09-07

  • Memoria del bot — fuentes nuevas: notas escritas a mano (POST /bot/knowledge/notes, PATCH /bot/knowledge/notes/:id) y páginas web públicas (POST /bot/knowledge/url). Con syncEveryHours la página se vuelve a leer cada N horas y solo se reprocesa si cambió el contenido. Los archivos aceptan además CSV.
  • Memoria del bot — búsqueda híbrida: la recuperación combina parecido semántico y palabras exactas en español (Reciprocal Rank Fusion). POST /bot/knowledge/search devuelve cada fragmento con similarity y porTexto; un acierto por palabra exacta se usa aunque no llegue a knowledgeMinSimilarity.
  • Memoria del bot — vacíos de conocimiento: GET /bot/knowledge/insights?dias= resume qué buscó el bot, las preguntas que quedaron sin respuesta agrupadas, el uso por agente y por documento. Una nota cierra un vacío con resolvesQuestionKey.
  • Agentes: documentos por agente con knowledgeDocIds en POST/PATCH /bot/agents (vacío = toda la biblioteca). knowledgeTags sigue funcionando, con menor precedencia.
  • Bot fuera de horario: cuando el cliente pide asesor y el equipo está cerrado, el bot ya no traspasa. Crea una tarea para el equipo (origin BOT), le dice al cliente cuándo lo contactan y sigue atendiendo. Por número en PUT /bot/config/:phoneId con outOfHoursTaskEnabled, outOfHoursTaskMessage ({apertura}) y outOfHoursTaskGraceMin; evento HANDOFF_DEFERRED. Guía en Handoff a humano.
  • Seguimiento por silencio: followUpEnabled, followUpAfterMin, followUpCloseAfterMin, followUpMode (AI | TEXT), followUpMessage y followUpCloseMessage en la misma configuración; eventos FOLLOWUP_SENT, FOLLOWUP_SKIPPED y FOLLOWUP_CLOSED.
  • Agentes: el traspaso entre agentes es invisible para el cliente (el destino responde en el mismo turno) y una etiqueta de ruteo ya no lo deshace.
  • Contrato OpenAPI: los cuerpos declarados en los controladores salen documentados en /openapi.json (varios POST/PATCH aparecían sin campos). Los SDKs y el portal se generan de ahí.

2026-09-06

  • Agentes multicanal: phoneNumberIds en POST/PATCH /bot/agents (vacío = todos los canales, incluidos web chat e Instagram); GET /bot/agents?phoneNumberId= filtra por canal. phoneNumberId (uno solo) queda como atajo legado.
  • Rendimiento por agente: GET /bot/agents/stats?dias= — conversaciones, respuestas, traspasos, escalamientos, ventas, citas, fallos, tokens y costo por agente y por canal. Lo anterior a la medición y lo del router sale como «sin atribuir».
  • Conversaciones: PATCH /conversations/:id/agent { agentId } fija a mano qué agente del bot atiende (null = que decida el enrutador). El detalle de la conversación incluye ahora sus etiquetas.
  • Enrutamiento: las routeTags son únicas (una etiqueta → un agente; 400 si choca) y el paso transfer_to_ai de los flujos acepta agentId para entregar a un agente concreto.
  • Passkeys: se acepta el origen Android de la app (huella de firma de Play) además del origen web; el login con passkey funciona desde la app móvil.

2026-09-05

  • Tiempo real: evento conversation.created para conversaciones nuevas en el canal del panel.
  • Mensajes: las plantillas se envían siempre al teléfono; el BSUID del contacto se usa solo para mensajes de sesión.

2026-09-04

  • Sesiones: GET /auth/me/sessions lista los dispositivos con sesión (una por sesión, marcando la actual); DELETE /auth/me/sessions cierra todas las demás y DELETE /auth/me/sessions/:id una en particular.
  • Miembros: PATCH /memberships/:id/suspension { suspended } suspende o reactiva el acceso de un miembro sin eliminarlo; /memberships/me devuelve suspended.
  • Ventas: POST /sales/einvoicing/license-orders/draft crea (o reutiliza) el pedido borrador de una venta de licencia sin emitir, para revisarlo y facturarlo después.
  • Licencias: POST /license-delivery/orders/:orderId/keys/:keyId/replace reemplaza una llave entregada que no funcionó (revoca la vieja, entrega una nueva) y dispara el webhook license.key_replaced. Mensaje y correo de reemplazo configurables.
  • Proveedores de IA: GET /bot/agents/modelos lista proveedores con sus modelos elegibles y si hay clave; las claves de Anthropic ligadas a identidad aceptan el Workspace ID (BYOK).

2026-09-03

  • Licencias: venta de carrito desde el asesor — POST /license-delivery/conversations/:conversationId/sell-cart (varios productos, una sola orden; method NEQUI o TRANSFERENCIA), con precio editable por línea.
  • Cobros: método TRANSFERENCIA (Bre-B a una llave, sin pasarela) junto a NEQUI y DAVIPLATA en el checkout y en la venta al chat.
  • Webhooks salientes: conversation.assignment_changed (asignar, reasignar o soltar una conversación). sale.completed incluye las llaves entregadas y phoneNumberId, para hooks con scope por número.

2026-09-02

  • Contactos: botExcluded en PATCH /contacts/:id — el bot no le responde nada a ese contacto (exclusión total).
  • Webhooks salientes: POST /webhooks-outbound/:id/test envía un evento webhook.test para comprobar el endpoint; evento nuevo sale.completed para ventas de licencias.

2026-08-30

  • Conversaciones: POST /conversations/:id/devolver-al-bot reactiva el bot tras un traspaso conservando el contexto.
  • Bot: ajuste de organización botMemoryResetHours (cada cuánto el bot olvida el historial de una conversación) y catálogo de modelos ampliado; los modelos que deprecaron temperature (Claude 5.x, gpt-5.x) ya no fallan.

2026-08-28

  • Conectores: módulo nuevo (/conectores) — WHMCS, Plesk, cPanel/WHM, WordPress/WooCommerce y HTTP genérico con catálogo cerrado de acciones, prueba de conexión y ejecución; identidad del cliente verificada por correo y acciones con confirmación del cliente o aprobación humana.
  • Licencias: cobro por transferencia a una llave (Bre-B) sin pasarela, bandeja de pagos conciliada con el correo del banco y QR de la llave; webhooks license.transfer_confirmed y license.payment_unmatched.

2026-08-23

  • Bot: GET /bot/salud (qué se está rompiendo y qué hacer), POST /bot/agents/:agentId/probador (conversar con un agente sin que salga nada al cliente), POST /bot/agents/:agentId/configurador (proponer cambios al prompt conversando) y catálogo de servicios /bot/servicios para sacar precios y enlaces del prompt.
  • Flujos: GET /bot/flows/plantillas con flujos de ejemplo; pasos nuevos: enviar imagen, enviar documento, botón de enlace y transfer_to_ai (entregar la conversación a la IA).

2026-08-19

  • Bot: librería de imágenes (/bot/images) que el agente IA, las auto-respuestas (acción «enviar imagen») y los flujos pueden enviar.
  • Licencias: vigencia por licencia y aviso de renovación automático (GET/POST /license-delivery/renewal-template); la respuesta del cliente al aviso tiene consecuencia.
  • Bot: activar una capacidad que el plan no incluye responde 400 con el nombre de la función.

2026-08-17

  • Listas de contactos: importar un CSV dentro de una lista (POST /contact-lists/:id/import), quitar contactos en bloque (DELETE /contact-lists/:id/members) y por filtro (POST /contact-lists/:id/remove-by-filter).
  • Versionado: GET /health devuelve la versión que está corriendo; todo el producto comparte un solo número desde la 2.1.0 (info.version de openapi.json va una versión por detrás del deploy).
  • Planes: catálogo de funciones contratables; Catálogo de WhatsApp y Flows pasan a ser funciones del plan.

2026-08-14

  • Jornada laboral — festivos y novedades: nueva API para el calendario de la organización. Alta masiva de festivos (POST /attendance/holidays, acepta varios de una vez), siembra del calendario oficial de un país y año (POST /attendance/holidays/seed) y novedades por persona —vacaciones, incapacidades, permisos— que tocan un rango de fechas (GET/POST/DELETE /attendance/leaves).
  • Jornada laboral — forma de trabajo: cada miembro puede estar en turno fijo o por horas (GET /attendance/work-modes, PATCH /attendance/work-modes/:agentId). Quien trabaja por horas no acumula ausencias por no cubrir un horario: se le cuenta lo trabajado. También se agregaron atajos de período —quincena, últimos 15/30 días, mes— resueltos en la zona horaria de la organización (GET /attendance/period-presets).
  • Bot: búsqueda semántica sobre la base de conocimiento (POST /bot/knowledge/search), que devuelve los fragmentos relevantes con su puntaje.
  • Difusiones: reintento en sitio de los destinatarios fallidos de un envío (POST /broadcasts/:id/retry-failed), sin crear una difusión nueva.

2026-08-06

  • Agentes de bot: la automatización pasa de un solo bot a agentes especializados (ventas, soporte…), cada uno con sus capacidades activables. CRUD completo en /bot/agents y catálogo de capacidades en /bot/agents/capabilities.

2026-08-05

  • Ventas y facturación electrónica: módulo nuevo con 31 endpoints. Productos, pedidos y perfiles de facturación por contacto (/sales/products, /sales/orders, /sales/billing-profiles), emisión de facturas y notas crédito, PDF por token firmado, y configuración del emisor con varias empresas emisoras (/sales/einvoicing/companies). Los permisos se separan: `sales:write` para operar y `sales:config` para tocar la configuración fiscal.

2026-08-04

  • Entrega de licencias digitales: módulo nuevo con 40 endpoints. Productos con variantes y pool de llaves, listas de precios, cupones, imágenes de producto, y el circuito completo de pedido → cobro → entrega automática por chat. Las llaves ya entregadas no se pueden borrar; al eliminar una variante sin ventas sus llaves libres vuelven al pool.
  • Cobros con Wompi: webhook de conciliación con validación de firma, general (POST /webhooks/wompi) y con URL propia por organización (POST /webhooks/wompi/:orgId).

2026-07-24

  • Agenda de citas: módulo nuevo con 20 endpoints. Reglas semanales de disponibilidad, días bloqueados por festivo o vacaciones, citas con filtros por rango/estado/contacto, y feed ICS público por token para suscribir la agenda desde cualquier calendario (GET /public/agenda/:token/calendar.ics).
  • Agenda — Google Calendar: conexión por OAuth (/agenda/google/connect y /callback), estado de la conexión, envío de citas al calendario y bloqueo automático de los huecos ocupados.
  • Agenda — reserva por WhatsApp Flow: se envía al contacto un Flow con selector de fecha nativo (POST /agenda/booking-flow/send) y su endpoint de datos para Meta.

2026-07-15

  • Cobros con Nequi: pago push a la app del celular (POST /billing/nequi/push), QR dinámico por monto (POST /billing/nequi/qr), consulta de estado en vivo y cancelación del pago pendiente.
  • Comprobantes de pago Bre-B/QR: la organización puede reportar un pago con su comprobante (POST /billing/payment-reports) y consultar la llave Bre-B de cobro para el modal.
  • Facturación: cambio de intervalo mensual/anual desde la API (PATCH /billing/interval).
  • Preferencias de interfaz por miembro (PATCH /memberships/me/preferences).
  • Números: sincronización de coexistencia con Meta —contactos e historial— (POST /phone-numbers/:id/coexistence/sync), y reintento de suscripción a los webhooks de una WABA (POST /waba/:id/webhooks/resubscribe).

2026-06-24

  • API v1.0.0: la referencia ahora cubre 68 módulos y ~400 endpoints. Se agregaron los módulos nuevos descritos abajo.
  • Recordatorios de jornada: API para configurar los avisos de turno de cada agente (inicio de turno, hora de almuerzo, regreso y fin de jornada), con anticipación configurable y canales por navegador, panel o correo (GET/PUT /organizations/:orgId/shift-reminders).
  • Equipo y turnos: endpoints de asistencia (entrada/salida, estado de trabajo) y de horarios de turno semanales por agente (franjas y almuerzo por día).
  • Tiendas (e-commerce): API para conectar WooCommerce/Shopify, mapear eventos de tienda (pedido, pago, envío, carrito abandonado) a plantillas de WhatsApp y revisar el log de eventos. Incluye el catálogo de plantillas de tienda listas para crear/sincronizar.
  • Avisos del sistema: endpoint para consultar los banners de estado activos que Mosend publica para todas las organizaciones.
  • Web Chat: el canal ahora soporta horario de atención por canal y acciones fuera de horario (ocultar, mostrar aviso, pedir correo o dejar mensaje con confirmación).
  • Mensajería: baja automática por palabra clave (opt-out) configurable por organización.

2026-06-06

  • Documentos: nueva API para gestionar los archivos de la organización — subir y organizar en carpetas, papelera con restaurar/purgar, uso de almacenamiento, enviar un documento a una conversación de WhatsApp (POST /documents/:docId/send), guardar un adjunto entrante como documento (POST /documents/from-message) y edición en vivo con OnlyOffice (editor-config + callback de guardado).
  • Páginas de enlaces (link-in-bio): API para crear páginas tipo Linktree — CRUD de páginas e ítems, subir avatar y portada, reordenar ítems, archivar y restaurar. El perfil público (GET /link-pages/p/:handle) y el redirect con seguimiento de clics (/go/:itemId) no requieren token.
  • Soluciones: catálogo de soluciones instalables (por ejemplo e-commerce). Listar el catálogo, ver el detalle por slug, instalar en una organización (con selección de WABA) y desinstalar.
  • Tareas: API de tareas tipo CRM — crear, listar con filtros, conteos para badges, tomar (claim), completar, editar y borrar. También se pueden listar por contacto.
  • Notas de contacto: notas internas por contacto (crear, listar con las fijadas primero, editar y borrar).
  • Créditos de IA (AI Power Pack): consultar el saldo con el desglose de uso de los últimos 30 días, ver el historial de transacciones y los paquetes de recarga disponibles.
  • Conversaciones: el listado (GET /conversations) ahora pagina por cursor (parámetros take + cursor) y acepta búsqueda por contacto (search, sobre nombre, nombre de perfil o número). Se agregó la galería de multimedia por conversación (/:id/media y /:id/media/counts) y los enlaces detectados en los mensajes (/:id/links).
  • Reportes de equipo: nuevos endpoints de desempeño — resumen semanal (reports/team/weekly), métricas por agente (reports/team/by-agent) y metas del equipo (reports/team/goals).
  • Verificación de email: endpoints para verificar el correo (POST /auth/verify-email) y reenviar el código (POST /auth/resend-verification). Las API keys no requieren verificación de email.

2026-05-20

  • API keys con scope por número (phoneNumberIds): puedes acotar una key a uno o más números de WhatsApp. Pensado para entregar una key a un bot externo o tercero y que solo opere su número — los envíos a números fuera de la lista devuelven 403 y los listados se filtran solos. Vacío = todos los números.
  • Webhooks salientes con scope por número (phoneNumberIds): un webhook puede restringirse a números específicos. Eventos con phoneNumberId se entregan solo si el número está permitido; template.status (con wabaId) si la WABA tiene algún número permitido; eventos globales de org (billing/uso) requieren un webhook sin scope.
  • Webhooks salientes: catálogo de eventos actualizado — conversation.handoff_requested (pedido de asesor humano), conversation.unanswered (mensaje sin respuesta humana tras N min, umbral configurable con unansweredThresholdMinutes 1–1440, default 2), conversation.updated, quality.changed. El bot IA, auto-respuestas y plantillas NO cuentan como respuesta humana para unanswered.
  • Broadcasts: nuevos conteos agregados en GET /broadcasts/:id (counts: total, sent, delivered, read, failed, replied) y endpoint GET /broadcasts/:id/recipients?filter= (replied · read · delivered · sent · failed) con paginación por cursor para listar destinatarios por estado. repliedAt marca a quienes contestaron dentro de los 30 días del envío.
  • Broadcasts: los broadcasts SCHEDULED ahora se ejecutan solos a la hora programada (job interno cada minuto). Ya no hace falta llamar /send manualmente.
  • Handoff a humano vía API: guía y endpoint para que un bot externo derive una conversación a un asesor humano.
  • Plantillas con botones dinámicos (URL con {{1}} o COPY_CODE): documentado el component button (sub_type url|copy_code) requerido en templateVariables para evitar el rechazo #131008 de Meta.

2026-05-15

  • Modelo de facturación clarificado: Mosend cobra solo la suscripción del plan (vía Mercado Pago). Los costos de las conversaciones de WhatsApp los cobra Meta directamente a la tarjeta vinculada a la WABA del cliente. Para activar plantillas, cada cliente debe configurar su método de pago en business.facebook.com → su WABA → Configuración de pago. UI del dashboard y /billing actualizado para reflejarlo (notice, labels honestos, step extra en el onboarding).
  • Traducción accionable de errores de Meta: cuando un mensaje falla (post-send, vía webhook de status), el motivo se persiste en Message.errorCode/errorTitle y se muestra en el inbox al hacer click sobre el icono ⚠ del estado. Cobertura inicial de ~30 códigos (#10, #100, #131042 billing, #131047 24h, #131049 capacity, #131056 opt-in, #132012-#132068 templates, etc.) con guías de cómo resolver cada uno.
  • Knowledge base (RAG) del bot: API CRUD para subir documentos (PDF, DOCX, TXT, MD), tagging y reproceso. Backend extrae texto, divide en chunks de ~700 tokens y embedea cada uno con text-embedding-3-small (1536 dim) vía OpenAI u OpenRouter. La búsqueda por similitud usa pgvector con índice IVFFLAT y operador `<=>` (distancia coseno).
  • Reactions: agregar/quitar emoji en mensajes propios o entrantes vía PUT/DELETE en /messages/:id/reactions.
  • Stickers: librería de stickers por organización con upload (cualquier imagen → WebP 512×512), guardado desde mensajes entrantes y envío a conversaciones.
  • WhatsApp Click-to-Chat Links: API para crear links cortos m.mosend.dev/<slug> con mensaje pre-cargado, QR code en PNG/SVG y analytics de clicks. Redirecciones públicas con tracking.
  • Passkeys (WebAuthn/FIDO2): registro y login passwordless completos. Endpoints públicos para opciones/verificación de login + JWT-protegidos para CRUD de passkeys del usuario.
  • Push notifications web: subscripciones VAPID, listado de dispositivos y endpoint de test.
  • Add-ons de billing: API GET y POST preview para extra seats, WABAs y storage como upgrades a la carta sobre el plan base.
  • Payment methods: tarjetas guardadas para auto-pay (CRUD + set-default + toggle de auto-pay).
  • Credit notes (admin staff): notas de crédito staff-only con generación de PDF y endpoint de regeneración.
  • Webhooks salientes: endpoint nuevo GET /webhooks-outbound/:id/deliveries para inspeccionar el log de entregas (status, attempt, body, response).

2026-05-03

  • Web Chat embebible: canal configurable con widget JS, sesiones anónimas, identificadas y verificación OTP.
  • Web Chat: historial de mensajes por visitante, vinculación de email post-sesión anónima.
  • Web Chat: gateway WebSocket dedicado en namespace /wc para comunicación en tiempo real con el widget.
  • Listas de contactos: CRUD completo con gestión de miembros (add/remove bulk).
  • Broadcasts: envío masivo a listas de contactos con estados de envío y cancelación.
  • Respuestas rápidas del inbox: atajos de teclado (/shortcut) con contador de uso.
  • Bot auto-respuestas: reglas por KEYWORD, OUT_OF_HOURS, WELCOME, FALLBACK con acciones de texto, template, flujo o transferencia.
  • Bot flujos secuenciales: diseñador de flujos conversacionales con pasos, variables y sandbox test-run.
  • Bot configuración: modos OFF / RULES_ONLY / RULES_PLUS_AI_FALLBACK / AI_AGENT por número, toggle rápido desde el panel.
  • Bot eventos: log de activaciones del bot por número para auditoría y debugging.
  • Agente IA: modelo configurable, prompt de sistema, temperatura, max_tokens, clasificador de intenciones.
  • Herramientas del agente IA: transfer_to_human y set_contact_attribute.
  • Transcripción de audio entrante vía Groq Whisper.
  • Planes: lista pública de planes, detalle por slug, cotización con cupón y cambio de plan self-service.
  • Límites de plan: endpoint de uso vs cuotas por organización (para barras de progreso en el dashboard).
  • Scope de WABA por usuario: visibilidad filtrada según asignaciones.
  • Fijar conversaciones en inbox.
  • Proveedores IA configurables por organización.

2026-05-01

  • Plantillas: soporte completo para header media (IMAGE/VIDEO/DOCUMENT) con upload resumable a Meta.
  • Plantillas: tipos nuevos de botones — FLOW, CATALOG, COPY_CODE.
  • Plantillas: modo carrusel con hasta 10 tarjetas (IMAGE o VIDEO + body + 2 botones por tarjeta).
  • Plantillas: componente LIMITED_TIME_OFFER (LTO).
  • Números: soft-delete (archivar) + restaurar + hard-delete con guardas anti-pérdida de cargos.
  • Embedded Signup: paso intermedio de selección manual de WABAs/números a importar.
  • Webhooks salientes: firma HMAC SHA-256 obligatoria en producción.
  • Auth: header X-Hub-Signature-256 validado en webhooks Meta antes de persistir.

2026-04-30

  • Lanzamiento de la API REST pública.
  • Integración Mercado Pago para suscripción de plan y recargas de saldo.