Lelemon API
  • Guías
  • Referencia de la API
Crear un agenteConversar con un agenteConocimiento del agenteAcciones HTTPEscalamiento a un humanoMandar un mensaje a una conversaciónQue el agente escriba primeroAgendar en tu propia pantallaInventariar tus agentes para una auditoriaCatalogos y respuestas rapidas de un embudoDisponibilidad de una persona del equipoMetricas de las conversaciones
powered by Zudoku
Guías

Darle acciones a un agente de Lelemon desde otra aplicación

Documento para el equipo que va a escribir la integración. Describe cómo registrar una acción HTTP —una llamada a un sistema de ustedes que el agente puede hacer en medio de una conversación— y cómo concedérsela o quitársela a un agente. Alcanza para implementar el lado de ustedes sin preguntarnos nada.

Base de la API de Lelemon: https://api.lelemon.cl

Qué resuelve esto

Un agente contesta con lo que sabe. Con una acción, además hace: abre un ticket en el sistema de ustedes, consulta el estado de un pedido, agenda algo en su calendario. La acción es una URL de ustedes, un método, y un esquema de los parámetros que el agente va a completar con lo que entendió de la conversación.

Son dos recursos distintos, y conviene tenerlos separados desde el principio:

  • La acción es de la organización. Se registra una vez, con su URL y su credencial.
  • La concesión es por agente. Una acción registrada no la usa nadie hasta que se le concede a un agente concreto, de a una.

Todo va con la credencial de organización en la cabecera Authorization:

Code
Authorization: Bearer lel_a1b2c3d4e5f6_<...>

Alcances: actions:read para ver, actions:write para registrar, dar de baja, conceder y quitar. actions:write es el permiso más delicado de la API —una acción HTTP manda datos de contactos de ustedes al sistema que la acción apunte— así que se lo dan sólo a integraciones que ya administran.

Una credencial con actions:write sólo registra acciones hacia los sitios que tiene permitidos. La lista la escribe una persona con rol de administrador en Integraciones, API, al emitir la credencial o después, y la credencial no la puede cambiar. Un sitio es esquema, host y puerto: https://n8n.ejemplo.cl no permite http://n8n.ejemplo.cl ni https://otro.n8n.ejemplo.cl. Así, si la credencial se filtra, quien la tenga no puede crear una acción que mande los datos a un servidor suyo.


1. Si van a dejar registrada la autorización: el texto

Code
GET https://api.lelemon.cl/v1/external/actions/authorization

No pide alcance: alcanza con una credencial viva.

Una acción manda datos de las conversaciones —nombre, RUT, teléfono, lo que la persona cuente— al sistema que ustedes indiquen. La Ley 21.719 (art. 15 bis) pide que el responsable de esos datos nos haya autorizado a entregarlos: quién, para qué, hacia dónde. Esa autorización puede constar en el contrato marco que tienen con nosotros, y por eso registrar la acción no la exige. Si prefieren dejarla registrada acción por acción —con versión del texto, país de destino y finalidad, consultable después—, la mandan en el mismo cuerpo, y para eso está este endpoint: lo que aceptan tiene versión, y la versión viaja en el cuerpo. Si no van a mandarla, salten al paso 2.

La respuesta

Code
{ "version": "2026-08-1", "vigente": { "version": "2026-08-1", "texto": "Autorizo a Lelemon a enviar a este destino los datos que el agente saque de las conversaciones: ...", "detalle": "Cuando el agente decide usar esta acción, arma los parámetros con lo que entendió ..." }, "fueraDeChile": { "version": "2026-08-1", "texto": "Este sistema está fuera de Chile, así que los datos salen del país. ...", "detalle": "La ley permite sacar datos de Chile cuando ..." }, "paises": ["chile", "fuera_de_chile", "desconocido"] }

version es lo que va en autorizacionVersion si registran la autorización. Guárdenla en la configuración de su integración, no en el código: cuando el texto cambie, el registro empieza a contestar 400 nombrando la versión que mandaron y la vigente, y la corrección es volver a leer este endpoint y actualizar ese valor.

fueraDeChile es un segundo texto, aparte. Si el sistema al que apunta la acción está alojado fuera de Chile —o no saben dónde—, los datos salen del país y eso es una transferencia internacional (art. 27): hay que confirmarla por separado, y queda registrada por separado.


2. Registrar una acción

Code
POST https://api.lelemon.cl/v1/external/actions

Alcance: actions:write.

El cuerpo

CampoTipoLímiteObligatorioQué hace
slugtexto64síIdentificador de la acción. Es con lo que se le concede a un agente, y es la llave para reintentar sin duplicar: mandar el mismo slug dos veces actualiza la misma acción con lo que manden, y conserva lo que no manden (las cabeceras, si no vienen, siguen).
nametexto100síCómo se llama.
descriptiontexto2000síLo que lee el agente para decidir cuándo usarla. Sin esto no la usa nunca. Escríbanla para el agente, no para una persona: "Consulta el estado de un pedido por su número. Usar cuando el cliente pregunte dónde está su compra."
urltexto2000síA dónde llama. http o https, pública y alcanzable: una dirección privada o que no resuelve da 400. No vuelve en ninguna respuesta: de la dirección sólo devolvemos el origen.
methodtexto—síGET, POST, PUT, PATCH o DELETE.
headersobjeto—noNombre de cabecera a valor. Acá viaja la credencial del sistema de ustedes. Se cifra antes de guardarse y no vuelve nunca, ni siquiera enmascarada.
parametersobjeto—noJSON Schema de los parámetros que el agente completa. Los nombres de estos parámetros son lo que queda registrado como "qué datos salen".
timeoutenteromsnoCuánto esperamos la respuesta de ustedes.
paraClientesbooleano—noA qué agentes se les puede conceder. Sin mandarlo, a cualquiera: a quién se la dan se decide al concederla (paso 4). true: sólo a los que atienden desconocidos por WhatsApp. false: sólo al asistente interno de ustedes. Tiene que ser un booleano de verdad: "false" entre comillas da 400, no lo convertimos.
purposetexto500no*Para qué es. Parte de la autorización: la ley pide que el encargo declare su finalidad.
destinationCountrytexto—no*Dónde está alojado el sistema: chile, fuera_de_chile o desconocido. Lo declaran ustedes; no lo detectamos, porque con un CDN adelante el DNS miente. desconocido cuenta como fuera.
autorizacionVersiontexto—no*La version que devolvió el paso 1.
confirmaSalidaDelPaisbooleano—con la autorización, si el destino no es chileLa segunda confirmación. Sin ella, una autorización con destino fuera de Chile da 400.

* La autorización es un bloque: o no mandan nada de purpose, destinationCountry y autorizacionVersion —y la acción se registra igual, sin autorización registrada— o mandan los tres. Dos de tres es 400 que dice cuál falta: una autorización a medias, con la finalidad en blanco o el país sin decir, sería peor que ninguna.

La respuesta

201 con la acción, sin la URL:

Code
{ "slug": "crear_ticket", "name": "Crear un ticket", "description": "Abre un ticket en el sistema de soporte con lo que cuenta el cliente.", "method": "POST", "origin": "https://api.suempresa.cl", "headerNames": ["Authorization"], "parameters": { "type": "object", "properties": { "resumen": { "type": "string" } } }, "audience": null, "status": "active" }

audience es a quién se le puede conceder: null es cualquiera (lo que queda sin paraClientes), external sólo los que atienden clientes, internal sólo el asistente interno.

origin y no url, y headerNames y no headers, a propósito: en un webhook de n8n el path es el token, y actions:read es el alcance que se le da a un auditor.

Ejemplo con curl

Con la autorización registrada. Sin ella, saquen las tres últimas líneas del cuerpo y el VERSION.

TerminalCode
VERSION=$(curl -s https://api.lelemon.cl/v1/external/actions/authorization \ -H "Authorization: Bearer $LELEMON_API_KEY" | jq -r .version) curl -X POST https://api.lelemon.cl/v1/external/actions \ -H "Authorization: Bearer $LELEMON_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"slug\": \"crear_ticket\", \"name\": \"Crear un ticket\", \"description\": \"Abre un ticket en soporte con lo que cuenta el cliente. Usar cuando reporte un problema.\", \"url\": \"https://api.suempresa.cl/tickets\", \"method\": \"POST\", \"headers\": { \"Authorization\": \"Bearer $TOKEN_DE_USTEDES\" }, \"parameters\": { \"type\": \"object\", \"properties\": { \"resumen\": { \"type\": \"string\" } }, \"required\": [\"resumen\"] }, \"purpose\": \"Abrir tickets de soporte con lo que reporta el cliente.\", \"destinationCountry\": \"chile\", \"autorizacionVersion\": \"$VERSION\" }"

Códigos de estado

CódigoCuándo
201Registrada (o actualizada, si el slug ya existía).
400Falta un campo de la acción, la autorización vino a medias, la autorizacionVersion no es la vigente, el destino sale de Chile sin confirmaSalidaDelPais, paraClientes no es un booleano, o la URL no se puede usar (privada, no resuelve, no es http/https). El mensaje dice cuál.
401Credencial ausente, revocada o inválida.
403A la credencial le falta actions:write, o la URL apunta a un sitio que la credencial no tiene permitido. Reescribir por slug una acción que apunta a un sitio no permitido también da 403, aunque no cambien la URL. El mensaje dice qué sitio falta.
429Pasaron un techo por minuto: 3.000 pedidos por credencial o 200 por dirección IP. Esperen lo que diga Retry-After.

Por qué reintentar no duplica

Mandar el mismo slug es la misma acción, esté activa o dada de baja. Si está activa, se actualiza con lo que venga en el cuerpo y se conserva lo que no venga; si cambian el sistema al que apunta (otro origen), la autorización anterior queda revocada —era para lo que había antes— y la nueva se registra si vino. Si está dada de baja, revive: dar de baja no borra, porque el registro de qué acción se ejecutó contra qué sistema tiene que seguir siendo legible después, así que el slug queda ocupado por una fila que el listado no muestra. Un guion de aprovisionamiento que corre dos veces deja una sola acción, con lo último que mandó.


3. Ver las acciones

Code
GET https://api.lelemon.cl/v1/external/actions

Alcance: actions:read. Devuelve { "data": [ ... ] } con las acciones HTTP que registraron ustedes, con la misma forma que la respuesta del registro. No incluye las acciones nuestras ni las de un servidor MCP: para saber qué puede tener un agente concreto está el paso siguiente.

Code
GET https://api.lelemon.cl/v1/external/agents/{agentId}/actions

Alcance: actions:read. El catálogo completo que ese agente puede tener, con enabled diciendo cuáles tiene concedidas hoy:

Code
{ "data": [ { "slug": "crear_ticket", "name": "Crear un ticket", "description": "...", "source": "Tus sistemas", "enabled": true }, { "slug": "search_knowledge", "name": "Buscar en el conocimiento", "description": "...", "source": "Lelemon", "enabled": true } ] }

source es una etiqueta para mostrar, no un código: Tus sistemas para lo que registraron ustedes, Lelemon para las acciones que traemos nosotros, y el nombre del servidor MCP o del conector cuando viene de ahí. No programen contra ese texto.

Sale el catálogo entero y no sólo lo concedido, porque para prender una hay que saber su slug, y un cliente que sólo viera lo suyo concluiría que el resto no se puede conceder. Sin la dirección ni cabeceras. Con actions:read, cada entrada trae destinationOrigin: el origen al que sale la acción, sea HTTP, de un servidor MCP o de un conector, y null si es una herramienta nativa de Lelemon. Está explicado en la guía para inventariar agentes.


4. Conceder y quitar

Code
PUT https://api.lelemon.cl/v1/external/agents/{agentId}/actions/{slug} DELETE https://api.lelemon.cl/v1/external/agents/{agentId}/actions/{slug}

Alcance: actions:write. Los dos devuelven 204 sin cuerpo. Los dos son idempotentes: conceder lo que ya estaba, o quitar lo que no estaba, no es un error.

Se concede de a una, nunca mandando la lista entera. Si tuvieran que mandar el conjunto completo, para agregar una tendrían que leer las que hay, sumar la suya y mandar todo — y entre el leer y el mandar, lo que alguien concedió desde el panel desaparece sin error y sin rastro. Dos concesiones simultáneas por dos procesos distintos quedan las dos.

Códigos de estado

CódigoCuándo
204Concedida / quitada.
400Sólo en PUT: esa acción no existe para su organización, o no alcanza a este agente. Quitar no valida: si una acción dejó de existir hay que poder sacársela igual.
404El agente no existe, no es de su organización, o es el asistente interno.

Por qué el asistente interno da 404

El asistente interno de ustedes trae herramientas que leen contactos con su teléfono, tratos y líneas de cartola. Con actions:write se podría registrar una acción a una URL propia y concedérsela: no haría falta ni hablarle, el dueño le escribe mañana y los datos salen solos. Por eso la API no lo toca: ni le concede, ni le quita, ni lista lo que tiene. Y el 404 es el mismo que el de un agente que no existe, para no confirmar cuál de los identificadores probados es el interno.


5. Dar de baja una acción

Code
DELETE https://api.lelemon.cl/v1/external/actions/{slug}

Alcance: actions:write. 204. Deja de estar disponible y se retira de todos los agentes que la tenían concedida, en el momento. El slug queda ocupado: volver a registrarlo revive esta misma acción (ver el punto 2). 404 si no tienen una acción con ese slug.


6. El cuerpo de los errores

Igual que en el resto de la API: statusCode, code, message y, cuando es un 400 de validación, errors con el campo que falló y la forma de lo que llegó, nunca su valor.

Códigos de error

Decidan por code, no por el texto del message: el texto puede cambiar y el code no. Los que importan al registrar una acción:

codeStatusCuándo pasaQué hacer
validation_failed400El cuerpo no cumple lo que pide la ruta.Corregir el pedido.
action_destination_blocked400La dirección no es una URL pública http o https.Usar una URL pública.
action_origin_not_allowed403La credencial no puede crear acciones hacia ese sitio.Que un administrador agregue el sitio a la credencial en Integraciones, API.
api_key_invalid401Falta la credencial, está mal escrita, fue revocada o venció.Revisar la clave o pedir una nueva.
scope_missing403La credencial no tiene el permiso que pide la ruta.Pedir que le agreguen ese permiso.
rate_limited429Pasaron el límite de pedidos.Esperar lo que diga Retry-After.

Si el error no tiene un código propio, code toma uno según el statusCode (not_found para 404, conflict para 409, internal_error para 500, y así). La tabla completa está en la guía de agentes, sección 7.

El 400 por versión vieja del texto es el único que conviene manejar por programa, porque va a pasar el día que el texto cambie y le va a pasar a todas las integraciones a la vez:

Code
{ "statusCode": 400, "message": "El texto de autorización cambió: mandaste la versión 2026-08-1 y la vigente es 2026-11-1. Lee el texto nuevo en GET /v1/external/actions/authorization y vuelve a enviarlo con esa versión." }

Lo razonable es que su integración, ante ese mensaje, avise a una persona: aceptar un texto legal nuevo automáticamente es justamente lo que el texto pide que no pase.


7. Lo que todavía no hacemos

  • Probarla. El botón de "probar" del panel no tiene equivalente por API.
Conocimiento del agenteEscalamiento a un humano
On this page
  • Qué resuelve esto
  • 1. Si van a dejar registrada la autorización: el texto
    • La respuesta
  • 2. Registrar una acción
    • El cuerpo
    • La respuesta
    • Ejemplo con curl
    • Códigos de estado
    • Por qué reintentar no duplica
  • 3. Ver las acciones
  • 4. Conceder y quitar
    • Códigos de estado
    • Por qué el asistente interno da 404
  • 5. Dar de baja una acción
  • 6. El cuerpo de los errores
    • Códigos de error
  • 7. Lo que todavía no hacemos
JSON
JSON
JSON
JSON