# Quickstart https://dev.bentho.org/quickstart/ QUICKSTART · ≈ 5 MIN # Tu primera respuesta en tres pasosNecesitas un espacio de Bentho con el módulo Bentho API y algún documento cargado. No hay nada que instalar: la API es HTTP y JSON. ## 1 · Crea tu claveEn la consola, abre el módulo API de tu espacio y crea una clave: ponle un nombre (por ejemplo, erp-produccion), elige a qué espacios llega y si solo lee o también escribe. La clave completa se ve una sola vez. Bentho solo guarda su huella: si la pierdes, crea otra y revoca la vieja. Tiene esta forma: bth_, 16 caracteres hexadecimales, un punto y el secreto. Guárdala en una variable de entorno de tu servidor, nunca en el código: BASHCOPIAR ``` export BENTHO_KEY="bth_7f3a1c9e04b2d8a1.xQ2…" ``` ¿Cuál es el id de tu espacio? Pregúntale a la API: devuelve los espacios a los que llega la clave. BASHCOPIAR ``` curl https://bentho.org/api/companies \ -H "Authorization: Bearer $BENTHO_KEY" # {"companies": [{"id": "mi-espacio", "name": "Mi espacio", "modules": ["api", …], …}]} ``` ## 2 · PreguntaUna petición a POST /api/rag/{espacio}/conversations con la pregunta y un session_id tuyo. El session_id es obligatorio: agrupa los turnos, así que reúsalo para las preguntas de seguimiento. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/rag/mi-espacio/conversations \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "question": "¿Cuántos días tengo para devolver un producto?", "session_id": "primera-prueba" }' ``` Tarda entre 2 y 20 segundos. Dale a tu cliente un timeout de al menos 60. ## 3 · Lee la respuesta200 OK · EJEMPLOCOPIAR ``` { "status_code": "1000", "response": "Según la política de devoluciones, tienes 30 días desde la entrega…\n\nReferencia: politica_devoluciones.pdf", "sources": ["politica_devoluciones.pdf"], "confidence": 0.7556, "warning": false, … } ``` - status_code "1000": contestó con apoyo en tus documentos. - status_code "1001": no había información suficiente y prefirió no inventar. response trae el mensaje de rechazo del espacio y sources llega vacío. - warning: true: contestó, pero solo parte de la respuesta está respaldada. Muéstralo como tal. - confidence: de 0 a 1. Desde 0,75 responde sin reparos. ## Y después - Mostrar la respuesta mientras se escribe: conversations/stream. - Subir documentos desde tu sistema: load_documents. - Que tu cliente aguante los errores y los límites: Errores, límites y créditos. --- # API https://dev.bentho.org/api/ API V1 # La API de BenthoPregúntale a los documentos de un espacio, sube y quita documentos, ajusta cómo responde y consulta tus créditos. Todo por HTTP, con JSON y una clave. Los módulos de tu espacio suman sus propias rutas. ## Lo básico | BASE | https://bentho.org/api | CLAVE | Authorization: Bearer bth_. · Claves y permisos | FORMATO | JSON (Content-Type: application/json), salvo la subida de documentos (multipart) y el stream (SSE). | DESDE DÓNDE | Desde tu servidor. La API no admite llamadas desde el navegador de tus usuarios (CORS), y la clave nunca debe llegar ahí. | VERSIÓN | v1: se agregan campos, nunca se quitan ni se renombran. ## Las rutas | | MÉTODO | RUTA | PARA QUÉ | PERMISO | POST | /rag/{espacio}/conversations | Haz una pregunta a tu espacio | lee | SSE | /rag/{espacio}/conversations/stream | La misma pregunta, en vivo | lee | GET | /rag/{espacio}/documents | Los documentos del espacio | lee | POST | /rag/{espacio}/load_documents | Sube documentos | escribe | DEL | /rag/{espacio}/documents/{archivo} | Quita un documento | escribe | GET | /rag/{espacio}/indexing_status | ¿Ya está listo lo que subí? | lee | PATCH | /rag/{espacio}/config | Ajusta cómo responde el Cerebro | escribe | PATCH | /companies/{espacio}/api-config | Límites, cuota diaria e IPs del espacio | escribe | GET | /cuentas/{cuenta}/bolsa | Tus créditos | lee ## MódulosLas rutas de un módulo cuelgan de /api/mod/{modulo}/{espacio}/, con la misma clave y los mismos límites. Solo responden en los espacios que tienen ese módulo (los ves en GET /api/companies); en los demás, 403. ### Fuentes · /api/mod/fuentes/{espacio} | | MÉTODO | RUTA | PARA QUÉ | PERMISO | POST | /fichas | Arma una ficha | escribe | GET | /fichas/{ficha} | El estado de una ficha | lee | GET | /fichas/{ficha}/markdown | La ficha armada y cómo se armó | lee | GET | /fichas | Las fichas del espacio | lee | POST | /fuentes | Crea una fuente | escribe | POST | /fuentes/{fuente}/lanzar | Lanza una fuente | escribe | GET | /fuentes/{fuente} | Una fuente y su última corrida | lee | GET | /fuentes | Las fuentes del espacio | lee | POST | /fuentes/{fuente}/cancelar | Cancela la corrida de una fuente | escribe | DEL | /fuentes/{fuente} | Borra una fuente | escribe ### Landings · /api/mod/landing/{espacio} | | MÉTODO | RUTA | PARA QUÉ | PERMISO | POST | /landings | Crea una landing | escribe | GET | /landings | Las landings del espacio | lee | GET | /landings/{landing} | El estado de una landing | lee | GET | /landings/{landing}/html | El HTML de una landing | lee | POST | /landings/{landing}/completar | Responde a lo que falta | escribe | POST | /landings/{landing}/refinar | Pide cambios a una landing | escribe | POST | /landings/{landing}/validar | Valida un HTML editado a mano | escribe | POST | /landings/{landing}/cancelar | Cancela la versión en curso | escribe | DEL | /landings/{landing} | Borra una landing | escribe ## Otras rutas útiles - GET /api/companies: los espacios a los que llega tu clave, con su id y sus módulos. - GET /api/companies/{espacio}/cuenta: la cuenta del espacio (para consultar la bolsa de créditos). - GET /api/rag/{espacio}/documents/{archivo}: descarga un documento. - DELETE /api/rag/{espacio}/clear_cache: vacía la caché de respuestas del espacio (escribe). - /api/tokens: crear, listar y revocar claves. Ver Claves y permisos. ## Antes de integrar - Claves y permisos - Lista de IPs - Errores, límites y créditos --- # Claves y permisos https://dev.bentho.org/api/claves/ API · EMPEZAR # Claves y permisosCada llamada lleva una clave de servicio en la cabecera. La clave dice qué espacios alcanzas y si puedes escribir; Bentho lo recalcula en cada petición. ## La claveCABECERACOPIAR ``` Authorization: Bearer bth_. ``` - bth_, luego un id de 16 caracteres hexadecimales, un punto y un secreto de 43 caracteres (base64url). - El secreto se ve una sola vez, al crearla. Bentho solo guarda su huella y la compara en tiempo constante. - No caduca: vale hasta que la revocas o deja de cumplirse lo que la sostiene (abajo). ## Crear una claveLo normal es crearla en la consola, en el módulo API de tu espacio. Al menos uno de sus espacios tiene que tener contratado el módulo Bentho API. | | CAMPO | QUÉ ES | nombre | De 1 a 80 caracteres. Uno por integración: «erp-produccion», «agente-soporte». | espacios | Los ids a los que llega. Vacío ([]) = todos tus espacios en el momento de cada petición, también los que crees después. | permiso | lee o escribe (por defecto). Si tu cuenta es de solo lectura, la clave sale lee. ## A qué llegaLos espacios de la clave se cruzan con los tuyos en cada petición. Si te quitan un espacio, la clave deja de llegar a él en la llamada siguiente, con 403 "Sin acceso a este espacio." ## Qué puede hacer | | PERMISO | PUEDE | lee | Preguntar (también en vivo), listar y descargar documentos, leer la configuración y la bolsa. | escribe | Todo lo anterior, más subir y borrar documentos, vaciar la caché y cambiar la configuración. El permiso efectivo es el más estricto entre el de la clave y el tuyo. Una clave nunca es administradora, aunque la cree un administrador: las rutas de administración y los campos de plataforma responden 403. ## Cuándo deja de funcionar | | PASA | RESPUESTA | La revocas | 401 desde la petición siguiente | Se borra tu usuario | 401 | Te quitan un espacio | 403 en ese espacio | La prueba del espacio vence | 403 | La cuenta lleva más de 7 días sin pagar, o está suspendida | 402 (la clave sigue siendo válida) | La API del espacio se apaga, o tu IP no está en la lista | 403 (solo a las claves: el Studio sigue entrando) ## Gestionarlas por APILas mismas operaciones que en la consola, en /api/tokens: CREAR · 201COPIAR ``` curl https://bentho.org/api/tokens \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{"nombre": "erp-produccion", "espacios": ["mi-espacio"], "permiso": "lee"}' # {"token": {"id": "7f3a1c9e04b2d8a1", "nombre": "erp-produccion", "espacios": ["mi-espacio"], # "permiso": "lee", "creado": "2026-09-27T15:04:05Z", …, "token": "bth_7f3a1c9e04b2d8a1.…"}} ``` LISTAR · SIN SECRETOSCOPIAR ``` curl https://bentho.org/api/tokens -H "Authorization: Bearer $BENTHO_KEY" # {"tokens": [{"id": …, "llamadas": 1284, "por_ruta": {…}, "ultimo_uso": …, "revocado": false}]} ``` REVOCARCOPIAR ``` curl -X DELETE https://bentho.org/api/tokens/7f3a1c9e04b2d8a1 -H "Authorization: Bearer $BENTHO_KEY" # {"revocado": "7f3a1c9e04b2d8a1"} ``` Errores propios: 403 si pides espacios que no son tuyos o ninguno tiene el módulo; 404 "Credencial no encontrada." (también si es de otra persona); 409 "La credencial ya estaba revocada." ## Buenas prácticas - Una clave por integración: si una se filtra, revocas solo esa. - lee siempre que alcance, sobre todo para agentes. - En una variable de entorno del servidor. Nunca en el navegador ni en el repositorio. - Si la clave va a un sistema con IP fija, añade esa IP en la lista de IPs del espacio. --- # Lista de IPs https://dev.bentho.org/api/ips/ API · EMPEZAR # Lista de IPsCada espacio puede aceptar llamadas solo desde ciertas IPs. Una clave filtrada no sirve desde otro sitio. ## Cómo funciona - Vive en ips_permitidas, dentro de la configuración de la API del espacio. - Lista vacía ([]) = cualquier IP. Es el valor por defecto. - Hasta 100 entradas: IPs sueltas o rangos CIDR, IPv4 o IPv6. - Se aplica solo a las claves. El Studio, con tu sesión, sigue entrando: por ahí arreglas una lista mal puesta. ## Qué IP cuentaLa IP pública con la que tu servidor sale a internet, tal como llega a Bentho. No la de tu red interna ni la de un proxy intermedio. Antes de activar la lista, comprueba tu IP de salida. Si tu servidor está en la nube, puede salir por un rango y no por una IP fija: pon el rango. ## ConfigurarlaPATCH · CLAVE CON PERMISO ESCRIBECOPIAR ``` curl -X PATCH https://bentho.org/api/companies/mi-espacio/api-config \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{"ips_permitidas": ["203.0.113.10", "198.51.100.0/24", "2001:db8::/32"]}' ``` Se guarda normalizada: - Un rango con bits de host se ajusta a su red: 198.51.100.7/24 queda 198.51.100.0/24. - Una IP con /32 (o /128) se guarda sin sufijo. - Los duplicados desaparecen. ## Si la IP no está403COPIAR ``` {"detail": "Esta dirección IP no está autorizada en este espacio."} ``` Una petición rechazada por IP no gasta cuota diaria ni cuenta para el límite por segundo. Si Bentho no puede saber tu IP y la lista no está vacía, también rechaza. Errores al guardar (422): - "«» no es una IP ni un rango CIDR válido." - "Como máximo 100 IPs o rangos." - "«ips_permitidas» tiene que ser una lista." --- # Errores, límites y créditos https://dev.bentho.org/api/errores/ API · EMPEZAR # Errores, límites y créditosTodo lo que puede decir que no, con el texto que devuelve. Con esto, tu cliente sabe qué reintentar y qué no. ## La forma de un errorSIEMPRECOPIAR ``` {"detail": "Sin acceso a este espacio."} ``` Con dos excepciones: la validación de la entrada (422) devuelve una lista en detail, y los 402 devuelven un objeto: 402 · CUENTA NO AL DÍACOPIAR ``` {"detail": {"mensaje": "La cuenta de este espacio no está al día.", "motivo": "pago_vencido", "pagado_hasta": "2026-09-01"}} ``` 402 · CRÉDITOS AGOTADOSCOPIAR ``` {"detail": {"mensaje": "La cuenta de este espacio agotó sus créditos de este ciclo.", "motivo": "bolsa_agotada", "creditos": {"incluidos": 800, "gastados": "800.0000", "restantes": "0.0000"}, "renueva": "2026-10-15"}} ``` motivo puede ser pago_vencido, suspension_comercial o bolsa_agotada. ## Qué puede decir que noPara una ruta de un espacio llamada con una clave: | | STATUS | SI | DETAIL | 401 | Sin clave | No autenticado. | 401 | Clave inexistente, mal formada o revocada | Credencial de servicio inválida o revocada. | 429 | Más de 120 peticiones por minuto con esta clave | Demasiadas peticiones con esta credencial. | 403 | Espacio fuera del alcance de la clave | Sin acceso a este espacio. | 403 | La prueba del espacio venció | La prueba de este espacio ha finalizado. | 402 | La cuenta no está al día | objeto (abajo) | 403 | La API del espacio está apagada | La API de este espacio está apagada. | 403 | Tu IP no está en la lista | Esta dirección IP no está autorizada en este espacio. | 429 | El espacio agotó su cuota diaria | Este espacio agotó su cuota diaria de la API. | 429 | Demasiadas peticiones por segundo en el espacio | Demasiadas peticiones por segundo en este espacio. | 403 | Ruta de escritura con una clave lee | Tu cuenta es de solo lectura en este espacio. | 403 | Ruta de un módulo que el espacio no tiene | módulo no habilitado para este espacio. | 402 | Créditos agotados (preguntar, subir y los módulos) | objeto (abajo) Las validaciones de cada ruta (400, 404, 413, 422) están en su ficha. Una petición rechazada por API apagada o por IP no cuenta para tus límites. ## Otros códigos | | STATUS | CUÁNDO | 404 | La ruta no existe. Si llamas a /api/rag/{espacio} a secas, el detail te dice qué ruta usar. | 405 | Método equivocado en una ruta que existe. Trae la cabecera Allow con los métodos válidos. | 413 | Subida demasiado grande: ver load_documents. | 429 · 503 | El servicio está saturado en ese momento. Llegan sin Retry-After: espera unos segundos y reintenta con espera creciente. | 502 | El servicio no está disponible en ese momento o la pregunta pasó de 90 s. No es tu clave: reintenta con espera creciente. ## Límites | | LÍMITE | VALOR | DÓNDE SE CAMBIA | Por clave | 120 peticiones en cualquier ventana de 60 s (deslizante) | Fijo | Por espacio y clave: tasa | 2 por segundo (1 – 1000) | api-config · solicitudes_por_segundo | Por espacio y clave: ráfaga | 120 seguidas (1 – 5000) | api-config · rafaga | Por espacio: cuota diaria | Sin tope (o 100 – 100 000 000), se reinicia a las 00:00 UTC | api-config · cuota_diaria Los 429 de estos límites traen Retry-After en segundos. El de la cuota diaria apunta a la medianoche UTC. ## Qué reintentar - 429: espera lo que diga Retry-After y reintenta. Si no lo trae, espera unos segundos y dobla la espera en cada intento. - 502 y 503: reintenta con espera creciente, dos o tres veces. - 401, 402, 403, 404, 422: no reintentes. Algo hay que cambiar: la clave, el pago, la configuración o la petición. - 200 con status_code "1001": no es un error de transporte. Reintentar la misma pregunta dará lo mismo. ## Créditos - Gastan créditos las preguntas, la indexación de documentos y lo que hacen los módulos: armar una ficha de Fuentes o lanzar una fuente, y crear, refinar, validar o completar una landing. - Sin créditos se cortan con 402 conversations, conversations/stream, load_documents y las rutas de los módulos que crean o lanzan algo. Leer, listar, configurar y consultar la bolsa siguen funcionando. - El saldo, en la bolsa de créditos. ## Tiempos - Una pregunta tarda de 2 a 20 s. Pon el timeout de tu cliente en 60 s o más. - Una pregunta que pase de 90 s se corta con 502. - En el stream, si no hay datos durante 15 s llega un : keepalive para que la conexión no se corte. --- # Fuentes https://dev.bentho.org/api/fuentes/ API · MÓDULO FUENTES # Fuentes: cómo funcionaFuentes trae información de la web pública a los documentos de tu espacio, para que Bentho la use al responder. Tiene dos formas de hacerlo: - Fichas: le das un tema y una plantilla con los datos que quieres. Bentho busca, lee y llena cada campo con el dato, la página de la que sale y la frase literal que lo respalda. - Fuentes: le das páginas o dominios concretos. Bentho los lee y los publica tal cual, cada vez que la lanzas. ## Antes de empezar - El espacio tiene que tener el módulo Fuentes: fuentes sale en sus módulos en GET /api/companies. Si no, cada ruta responde 403 módulo no habilitado para este espacio. - Armar fichas y crear, lanzar, cancelar o borrar fuentes cambia los documentos del espacio: pide una clave escribe. Leer vale con cualquier clave. - Las rutas cuelgan de /api/mod/fuentes/{espacio}/, con la misma clave y los mismos límites que el resto de la API. ## Una ficha, paso a paso - Ármala con el tema y la plantilla: responde 202 con su id en recibido. - Consulta su estado cada 10 a 15 s hasta que sea publicado o fallido. Suele tardar unos minutos. - Lee lo que encontró en markdown: el valor, la página y la cita de cada campo, y la traza de la búsqueda. - Ya está en los documentos del espacio: Bentho la usa para responder desde ese momento.Busca por vueltas: cada una busca solo los campos que siguen vacíos, y para cuando los llena todos o llega a sus topes (vueltas, páginas o tiempo). Un dato sin página que lo respalde no se inventa: el campo queda «sin respaldo en las páginas leídas». ## La plantillaMarkdown: ## abre una sección y cada línea - Nombre: qué buscar es un campo. La descripción guía la búsqueda: di la unidad o el formato que esperas. El # del título se ignora; el tema llega aparte. PLANTILLACOPIAR ``` # Suelo ## Físico - Textura: proporción de arena, limo y arcilla - Densidad aparente: cifra y unidad ## Químico - pH: valor y método de medida ``` Una plantilla sin ninguna sección con campos da 422 La plantilla no tiene secciones con campos. ## Qué se publica, y dónde - La ficha se publica en los documentos del espacio como ficha-.md, cortada en trozos que se entienden solos. Los campos vacíos no se publican. - Armar otra ficha con el mismo tema la reemplaza: queda una versión nueva del mismo documento. - Una fuente publica lo que lee cada vez que la lanzas. Borrarla quita de los documentos lo que publicó. - Si ningún campo se llenó, la ficha queda publicado pero no publica nada: traza.publicacion.status es sin_datos. ## Para que salga más completa - Aporta 2 a 4 urls concretas del caso: suben cuántos campos se llenan. Si la ficha llena menos de la mitad sin ellas, traza.sugerencia te lo recuerda. - Si hay casos parecidos que se mezclan (dos fincas, dos productos), enciende como.coherencia. - Con como.dominios lee solo de los sitios que confías; con como.instrucciones, dile qué priorizar. ## Créditos - Armar una ficha y lanzar una fuente gastan créditos de la bolsa de tu cuenta. Lo que gasta cada una depende de cuánto tenga que buscar y leer. - Con la bolsa agotada, las rutas que crean o lanzan responden 402 (bolsa_agotada). Leer y borrar siguen funcionando. - El saldo, en la bolsa de créditos. --- # Landings https://dev.bentho.org/api/landings/ API · MÓDULO LANDINGS # Landings: cómo funcionaAPI en preparación. Esta guía describe su contrato. Confirma que el módulo esté disponible y habilitado en tu espacio antes de integrar estas rutas. Le das a Bentho un brief y la URL que recibe los formularios. Bentho escribe una landing de una sola página, la prueba en un navegador (formulario, enlaces, teclado, escritorio y móvil) y te la entrega en un HTML listo para publicar donde quieras. También puedes hacerlo desde la consola: entra al Estudio de un espacio con el módulo activo y abre Landings. El panel permite crear la landing, responder a los datos que falten, refinarla, consultar su calidad y descargar el HTML. ## Antes de empezar - El espacio tiene que tener el módulo Landings: landing sale en sus módulos en GET /api/companies. Si no, cada ruta responde 403 módulo no habilitado para este espacio. - Crear, refinar, validar, completar, cancelar y borrar piden una clave escribe. Leer vale con cualquier clave. - Las rutas cuelgan de /api/mod/landing/{espacio}/, con la misma clave y los mismos límites que el resto de la API. ## El recorrido - Crea la landing: responde 202 con su id y la versión 1 en pendiente. - Consulta su estado cada 10 a 15 s. Suele tardar unos minutos. - Si queda en esperando_datos, enséñale a tu usuario las preguntas de faltantes y manda lo que responda a completar. La versión sigue sola. - Cuando termine (aprobado o revision), descarga su HTML y publícalo. - Para cambiarla, refínala con una instrucción. Si la retocaste a mano, mándala a validar.ESTADOSCOPIAR ``` pendiente → generando → aprobado | revision | fallido ↘ esperando_datos → (completar) → pendiente generando → aplazado → generando (se reanuda sola) cualquiera en curso → (cancelar) → cancelado ``` ## Versiones - Cada generación, refinado o validación es una versión nueva de la misma landing. Las anteriores se conservan y puedes pedir cualquiera con ?version=. - Una landing tiene una sola versión en curso: pedir otra mientras tanto da 409. Cancélala o espera. - Un espacio tiene un tope de landings generándose a la vez: al pasarlo, 429. Las que esperan datos no cuentan. - aprobado quiere decir que pasó las dos revisiones: la de funcionamiento (el formulario envía, los enlaces llevan a su sitio, se usa con teclado, nada se sale de la pantalla) y la de diseño, en escritorio y en móvil. revision trae HTML, pero alguna no pasó: calidad.motivos dice cuál. - El certificado (calidad) vale para un HTML exacto, el de su html_sha256. Si lo retocas, ya no vale: mándalo a validar. ## Datos que faltanBentho no inventa testimonios, reseñas, resultados, ponentes, agendas ni fechas. Si el brief pide algo así sin darlo, antes de escribir te pregunta (hasta cinco cosas). Respondes lo que tengas y omites lo demás; lo omitido se escribe sin ese elemento y sin avisarle al visitante de que falta. Para que no pregunte, crea la landing con revisarBrief: false. ## Lo que recibe tu submitUrlAl enviar, el formulario de la landing hace un POST desde el navegador del visitante a tu submitUrl, con Content-Type: application/json: CUERPO DEL ENVÍOCOPIAR ``` { "page_id": "curso-excel-otono", "source": "https://tu-dominio.com/excel-para-pymes?utm_source=newsletter", "nombre": "Ana", "email": "ana@example.com", "telefono": "+34 600 000 000", "utm_source": "newsletter" } ``` - page_id es el pageId que mandaste al crearla, y source, la dirección de la página. Después, un campo por cada campo del formulario. - Llegan también utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, fbclid, ttclid y msclkid si la visita los traía, aunque el visitante haya pasado por otras páginas antes de enviar. - Contesta con un 2xx y {"success": true}. Con cualquier otra cosa, el visitante ve «No pudimos enviar tu solicitud» y puede reintentar. - El envío sale del navegador: si tu submitUrl está en otro dominio que la landing, tiene que aceptar CORS (la petición previa OPTIONS y el POST con Content-Type: application/json). ## El formulario: formConfigSin formConfig, Bentho arma el formulario según el brief. Con él, lo fijas tú: | | CAMPO | QUÉ ES | fields | Obligatorio. Hasta 20 campos, en orden: name (letras, números y _, empieza por letra; no puede ser page_id ni source), label, type (text, email, tel, number, textarea o select), required (boolean), y si quieres placeholder y options (para select, hasta 30). | success_message | Obligatorio. Lo que ve el visitante al enviar. Hasta 2000 caracteres. | cta_text | El texto del botón de envío. | redirect_url | Adónde lleva al visitante después de enviar (HTTP o HTTPS). | cta_url · cta_links | Adónde llevan los botones que no son el envío: una URL para todos o una lista [{text, url}], en orden. FORMCONFIGCOPIAR ``` { "fields": [ { "name": "nombre", "label": "Nombre", "type": "text", "required": true }, { "name": "email", "label": "Email", "type": "email", "required": true }, { "name": "telefono", "label": "Teléfono", "type": "tel", "required": false } ], "cta_text": "Quiero mi plaza", "success_message": "¡Listo! Te escribimos en menos de 24 horas." } ``` Un formConfig que no cumple esta forma no da 422: la versión termina en fallido y error dice por qué. ## Créditos - Crear, refinar, validar y completar gastan créditos de la bolsa de tu cuenta, como las preguntas. Lo que gasta cada una depende del brief y de cuánto haya que corregir. - Con la bolsa agotada, esas cuatro rutas responden 402 (bolsa_agotada). Leer, cancelar y borrar siguen funcionando. - Cancelar o borrar no devuelve lo que ya se gastó. - El saldo, en la bolsa de créditos. ## Tamaños - El cuerpo de una petición, hasta 24 MB. - prompt, hasta 24 000 caracteres; brandBlock, hasta 20 000; funnelReferenceHtml y el html de validar, hasta 300 000. - El PDF, en base64 dentro del JSON: hasta 16 000 000 de caracteres, unos 12 MB de PDF. --- # conversations https://dev.bentho.org/api/conversations/ POST/api/rag/{espacio}/conversations # Haz una pregunta a tu espacioBentho busca en los documentos del espacio y contesta solo con lo que dicen. Cada respuesta trae sus fuentes y cuánto confía en ella. Si reusas el session_id, entiende las preguntas de seguimiento. - PERMISOlee (vale cualquier clave) - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | question | string | SÍ | La pregunta, en texto libre. | session_id | string | SÍ, EN LA PRÁCTICA | Tu identificador de conversación. Es obligatorio: sin él responde 400. Reúsalo para seguir el hilo; dos claves del mismo dueño con el mismo session_id comparten conversación. | history | [{ role: "user" | "assistant", content }] | no | Turnos previos, si prefieres mandar tú el contexto. Sin él, se usa el historial de la sesión. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | status_code | "1000" | "1001" | "1000" contesta con apoyo en los documentos. "1001" no hay información suficiente o prefiere no responder; response trae entonces el mensaje de rechazo del espacio. | response | string | El texto de la respuesta. Si hay fuentes, termina con el pie «Referencia: …». | sources | string[] | Los documentos citados. Vacío con 1001. | confidence | number | null | De 0 a 1. Desde 0,75 responde; entre 0,55 y 0,75 responde con warning; por debajo, 1001. | warning | boolean | true si solo parte de la respuesta está respaldada. Sigue siendo 1000. | claim_attributions | array | null | Por frase: { sentence, chunk_index, entailment, supported }. | session_id | string | null | El que mandaste. | tenant_id · query | string | El espacio y la pregunta original. | verification · condensed_query | object | null · string | null | Detalle de la verificación y la pregunta reescrita, si la hubo. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 400 | Falta session_id | session_id es obligatorio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 404 | El espacio no existe | — | 422 | Falta question | — | 502 | El servicio no respondió a tiempo: reintenta con espera creciente | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Un error interno al responder no llega como 5xx: llega como 200 con status_code: "1001" y el texto «Ocurrió un error interno procesando la consulta. Intenta de nuevo.». Trátalo como una respuesta sin información. - Una consulta típica tarda de 2 a 20 s. Pon el timeout de tu cliente en 60 s o más. - En espacios con el módulo de Ventas la respuesta tiene otra forma (estado, cotizacion, handoff…) y no usa history. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/rag/mi-espacio/conversations \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "question": "¿Cuántos días tengo para devolver un producto?", "session_id": "erp-consulta-4821" }' ``` ■ 200 OKejemplo, con los campos del esquema ``` { "tenant_id": "mi-espacio", "session_id": "erp-consulta-4821", "query": "¿Cuántos días tengo para devolver un producto?", "status_code": "1000", "response": "Según la política de devoluciones, tienes 30 días desde la entrega para devolver un producto sin usar…\n\nReferencia: politica_devoluciones.pdf", "sources": ["politica_devoluciones.pdf"], "confidence": 0.7556, "warning": false, "claim_attributions": [ … ], "verification": { … }, "condensed_query": null } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # conversations/stream https://dev.bentho.org/api/conversations-stream/ POSTSSE/api/rag/{espacio}/conversations/stream # La misma pregunta, en vivoEl mismo cuerpo que conversations, pero la respuesta llega por eventos (SSE) mientras se escribe. Sirve para mostrarla a una persona sin hacerla esperar. - PERMISOlee (vale cualquier clave) - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | question | string | SÍ | La pregunta. | session_id | string | SÍ, EN LA PRÁCTICA | Igual que en conversations. | history | array | no | Igual que en conversations. ## EVENTOS200 con Content-Type: text/event-stream. Cada evento es una línea data: {…} seguida de una línea en blanco. Las líneas que empiezan por : son : keepalive (cada 15 s sin datos): ignóralas. | | CAMPO | TIPO | QUÉ ES | status | { type, stage: "verifying" } | Solo en espacios con verificación previa: está comprobando antes de generar. | chunk | { type, content } | Un pedazo de texto. Al final llega uno con el pie «Referencia: …» si hay fuentes. | handoff | { type, handoff_id, reason } | Conviene pasar a una persona (low_confidence o contradiction). Llega antes del done. | done | { type, status_code, full_response, confidence, warning, sources } | Cierre normal. Manda su status_code, aunque ya hayan llegado chunks. | error | { type, content } | Algo falló después del 200. El stream termina. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 401 | Antes de abrir el stream: clave inválida | Credencial de servicio inválida o revocada. | 402 | Antes de abrir el stream: créditos agotados | — | evento | Evento error: el servicio no respondió a tiempo | — | evento | Evento error: falta session_id | session_id es obligatorio. | evento | Evento error: el servicio está saturado; reintenta con espera creciente | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Todo lo que se puede rechazar antes (401, 402, 403, 429) llega como respuesta JSON normal, no como evento. Después del 200, cualquier fallo llega como evento error. - En espacios con verificación estricta la respuesta llega en un solo chunk, ya verificada, después de un status. - Los chunk ya enviados no se retiran aunque el done diga "1001": decide con el status_code del done. CURLPYTHONJAVASCRIPT COPIAR ``` curl -N https://bentho.org/api/rag/mi-espacio/conversations/stream \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "question": "¿Cuántos días tengo para devolver un producto?", "session_id": "erp-consulta-4821" }' ``` ■ 200 · EVENTOSderivado del esquema ``` : keepalive data: {"type": "chunk", "content": "Según la política de devoluciones, "} data: {"type": "chunk", "content": "tienes 30 días desde la entrega…"} data: {"type": "chunk", "content": "\n\nReferencia: politica_devoluciones.pdf"} data: {"type": "done", "status_code": "1000", "full_response": "…", "confidence": 0.7556, "warning": false, "sources": ["politica_devoluciones.pdf"]} ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # documents https://dev.bentho.org/api/documents/ GET/api/rag/{espacio}/documents # Los documentos del espacioLa lista de documentos que Bentho puede usar para responder, del más reciente al más antiguo. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_…Para descargar uno: GET /api/rag/{espacio}/documents/{archivo}. Llega con application/pdf para los PDF y text/plain para el resto, sin Content-Disposition: ponle tú el nombre al guardarlo. ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | documents | array | Ordenados por fecha de modificación, el más reciente primero. | documents[].filename | string | El nombre del archivo. | documents[].size | integer | Tamaño en bytes. | documents[].modified | number | Fecha de modificación, en segundos desde 1970 (con decimales). ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 404 | El espacio no existe | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Solo lista las extensiones admitidas: .pdf, .docx, .txt y .md. Un espacio sin documentos devuelve {"documents": []}. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/rag/mi-espacio/documents \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del esquema ``` { "documents": [ { "filename": "politica_devoluciones.pdf", "size": 48213, "modified": 1758000000.25 } ] } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # load_documents https://dev.bentho.org/api/load-documents/ POST/api/rag/{espacio}/load_documents # Sube documentosSube uno o varios archivos. Se guardan al momento y se indexan en segundo plano: consulta indexing_status para saber cuándo puedes preguntarles. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## CUERPO · MULTIPART/FORM-DATA | | CAMPO | TIPO | REQUERIDO | QUÉ ES | files | archivo, repetible | SÍ | Uno por archivo. Admitidos: .pdf, .docx, .txt y .md. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | status | string | Siempre "processing". | files | string[] | Los nombres guardados. | message | string | « archivo(s) guardado(s). Indexación en segundo plano.» ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 400 | Extensión no admitida | Extensión no soportada: . Permitidas: ['.docx', '.md', '.pdf', '.txt'] | 400 | Sin archivos | No se recibieron archivos. | 402 | Créditos agotados (indexar gasta créditos) | — | 403 | Clave de solo lectura | Tu cuenta es de solo lectura en este espacio. | 413 | Más de 200 MB en total | La subida excede el tamaño máximo total permitido. | 413 | Más de 20 archivos | Demasiados archivos (máximo 20 por subida). | 413 | Un archivo de más de 50 MB | El archivo '' excede el máximo de 50 MB. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Subir un archivo con el mismo nombre lo reemplaza. - Si un archivo de la tanda tiene una extensión no admitida, los anteriores quedan guardados pero no se indexan: sube primero solo archivos válidos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/rag/mi-espacio/load_documents \ -H "Authorization: Bearer $BENTHO_KEY" \ -F "files=@manual_usuario.pdf" \ -F "files=@catalogo_productos.docx" ``` ■ 200 OKderivado del esquema ``` { "status": "processing", "files": ["manual_usuario.pdf", "catalogo_productos.docx"], "message": "2 archivo(s) guardado(s). Indexación en segundo plano." } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # documents/{archivo} https://dev.bentho.org/api/delete-document/ DEL/api/rag/{espacio}/documents/{archivo} # Quita un documentoBorra el archivo del espacio y sus fragmentos del índice. Deja de usarse en la siguiente pregunta. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). | archivo | string | SÍ | El nombre exacto, codificado para URL. Sin «/», «\» ni «..». ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | status | string | "success". | message | string | «'' eliminado ( chunks).» ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 400 | Nombre con barras, puntos o vacío | nombre de archivo no válido. | 403 | Clave de solo lectura | Tu cuenta es de solo lectura en este espacio. | 404 | No existe | Documento no encontrado: | 500 | Falló el borrado | Error al eliminar el documento. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X DELETE https://bentho.org/api/rag/mi-espacio/documents/manual_usuario.pdf \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del esquema ``` { "status": "success", "message": "'manual_usuario.pdf' eliminado (42 chunks)." } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # indexing_status https://dev.bentho.org/api/indexing-status/ GET/api/rag/{espacio}/indexing_status # ¿Ya está listo lo que subí?El estado de la última subida del espacio. Cuando dice «done», ya puedes preguntarle a esos documentos. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | status | "idle" | "processing" | "done" | "error" | idle: nada en curso. processing: indexando. done: listo. error: falló. | files | string[] | Los archivos de la última subida. | message | string | « documento(s) indexado(s) — chunks.» cuando termina. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 404 | El espacio no existe | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Es el estado de la última subida y vive en memoria: si el servicio se reinicia vuelve a idle. Consulta cada pocos segundos y para en done o error. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/rag/mi-espacio/indexing_status \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del esquema ``` { "status": "done", "files": ["manual_usuario.pdf"], "message": "1 documento(s) indexado(s) — 42 chunks." } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # config · Cerebro https://dev.bentho.org/api/config/ PATCH/api/rag/{espacio}/config # Ajusta cómo responde el CerebroCambia solo los campos que mandes. Surte efecto en la siguiente pregunta. Los rangos válidos de cada campo te los da el GET de la misma ruta en rangos. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_…GET /api/rag/{espacio}/config devuelve el mismo sobre sin cambiar nada (vale con una clave lee). ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | temperature | float | no | 0 – 0,5. Más alto, más variación al redactar. | relevance_threshold | float | no | 0 – 0,75. Por debajo, un fragmento no cuenta como relevante. | citation_max | int | no | 0 – 5 fuentes citadas por respuesta. | rerank_top_n | int | no | 1 – 10 fragmentos tras reordenar. | bm25_weight · semantic_weight | float | no | 0 – 1 cada uno; no pueden ser los dos 0. | system_prompt | string | no | Hasta 8000 caracteres. | refusal_message | string | no | Lo que responde con 1001. Hasta 1000 caracteres. | citation_label | string | no | El rótulo del pie de fuentes («Referencia»). Hasta 40. | strict_source_only | bool | no | Solo contesta con lo que dicen los documentos. | nli_entail_min | float | no | 0,4 – 0,85. Cuánto tiene que apoyar el texto a cada frase. | cache_threshold | float | no | 0 – 0,1. Parecido mínimo para reusar una respuesta. | num_predict | int | no | 512 – 4096. Hasta dónde puede alargarse una respuesta: más alto, más larga. | … | | no | Y 10 más: la lista completa, con rangos, sale en editables y rangos del GET. ## RESPUESTA 200El mismo sobre que el GET, con la configuración ya guardada. | | CAMPO | TIPO | QUÉ ES | config | object | La configuración del espacio. | editables | string[] | Los campos que puede cambiar ESTA clave. Con lee: []. | rangos | object | Por campo: { tipo, min?, max?, largo_max?, opciones? }. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | Clave de solo lectura | Tu cuenta es de solo lectura en este espacio. | 403 | Un campo que solo cambia Bentho | «» solo lo puede cambiar un administrador de la plataforma. | 422 | Cuerpo vacío | No hay nada que cambiar. | 422 | Fuera de rango | «» tiene que estar entre y . | 422 | Campo desconocido | «» no se puede cambiar desde aquí. | 422 | Los dos pesos a 0 | La búsqueda necesita algún peso: no pueden ser los dos 0. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - No admite null: cada campo exige su tipo. Un entero vale donde se pide un decimal. - Los demás campos de la configuración solo los cambia Bentho: con una clave responden 403. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X PATCH https://bentho.org/api/rag/mi-espacio/config \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "temperature": 0.2, "citation_max": 3 }' ``` ■ 200 OKderivado del esquema ``` { "config": { "tenant_id": "mi-espacio", "temperature": 0.2, "citation_max": 3, … }, "editables": ["bm25_weight", "cache_threshold", "citation_label", "citation_max", …], "rangos": { "temperature": { "tipo": "float", "min": 0.0, "max": 0.5 }, "name": { "tipo": "str", "largo_max": 80 }, … } } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # api-config https://dev.bentho.org/api/api-config/ PATCH/api/companies/{espacio}/api-config # Límites, cuota diaria e IPs del espacioDecide si la API del espacio está activa, cuántas peticiones por segundo acepta, su ráfaga, su cuota diaria y qué IPs pueden llamar. Se valida el resultado: lo guardado más lo que mandas. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | activa | bool | no | Apaga o enciende la API del espacio. Ojo: una clave que la apaga se deja fuera a sí misma. | solicitudes_por_segundo | int | no | 1 – 1000. Por defecto, 2. | rafaga | int | no | 1 – 5000 y no menor que solicitudes_por_segundo. Por defecto, 120. | cuota_diaria | int | null | no | 100 – 100 000 000 peticiones al día (UTC). null = sin tope. | ips_permitidas | string[] | no | Hasta 100 IPs o rangos CIDR, v4 o v6. [] = cualquiera. Ver Lista de IPs. ## RESPUESTA 200Los cinco campos, como quedaron guardados (las IPs, ya normalizadas). | | CAMPO | TIPO | QUÉ ES | config | object | activa, solicitudes_por_segundo, rafaga, cuota_diaria, ips_permitidas. ## GET /API/COMPANIES/{ESPACIO}/API-CONFIG DEVUELVE ADEMÁS | | CAMPO | TIPO | QUÉ ES | techo_por_minuto | int | El tope global por clave (120 por defecto). | uso | object | Del día (UTC): solicitudes, atendidas, rechazadas y por_motivo (apagada, ip, cuota, tasa). | claves | array | Tus claves que alcanzan este espacio, sin secreto. | contratado | bool | Si el espacio tiene el módulo «Bentho API». ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | Sin el módulo contratado | Este espacio no tiene contratado el módulo «Bentho API». | 403 | Clave de solo lectura | Tu cuenta es de solo lectura en este espacio. | 404 | El espacio no existe | Espacio no encontrado. | 422 | Ráfaga menor que la tasa | «rafaga» no puede ser menor que «solicitudes_por_segundo»: el cubo se vaciaría antes de rellenarse un segundo. | 422 | IP mal escrita | «» no es una IP ni un rango CIDR válido. | 422 | Más de 100 IPs | Como máximo 100 IPs o rangos. | 422 | Campo desconocido | Campos desconocidos: ['', …]. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Guardar reinicia los cubos del espacio, no los contadores del día. - Estos límites se aplican solo a las claves. El Studio, con tu sesión, sigue entrando aunque apagues la API. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X PATCH https://bentho.org/api/companies/mi-espacio/api-config \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "solicitudes_por_segundo": 5, "rafaga": 12, "cuota_diaria": 5000, "ips_permitidas": [ "203.0.113.10/32", "198.51.100.7/24" ] }' ``` ■ 200 OKderivado del esquema ``` { "config": { "activa": true, "solicitudes_por_segundo": 5, "rafaga": 12, "cuota_diaria": 5000, "ips_permitidas": ["203.0.113.10", "198.51.100.0/24"] } } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # bolsa de créditos https://dev.bentho.org/api/bolsa/ GET/api/cuentas/{cuenta}/bolsa # Tus créditosLos créditos incluidos, gastados y restantes de la cuenta, que agrupa tus espacios. Es lo que mira Bentho para cortar con 402 cuando se agotan. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | cuenta | string | SÍ | El id de la cuenta. Desde un espacio: GET /api/companies/{espacio}/cuenta → cuenta.id. | dias | int, query | no | Mide los últimos N días. Sin él, el ciclo en curso: la misma ventana con la que se corta. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | creditos.permitido | bool | false = bolsa agotada. | creditos.incluidos | int | null | Los del plan. null = sin techo. | creditos.gastados | string | Decimal como texto, 4 decimales: "0.3426". | creditos.restantes | string | null | Lo que queda del ciclo. | creditos.porcentaje | string | null | Fracción gastada, de 0 a 1. | creditos.motivo | string | ok, bolsa_agotada, sin_plan o sin_creditos_acordados. | dias · renueva | int · string | null | La ventana medida y el primer día del ciclo siguiente. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | La cuenta no es tuya | Sin acceso a esta cuenta. | 404 | No existe | Cuenta no encontrada. | 422 | dias no es un entero | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - gastados y restantes son texto, no números: así no pierden precisión. Conviértelos con un decimal de verdad (Decimal en Python). - Consulta a cada módulo en el momento: puede tardar más que las demás rutas. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/cuentas/mi-cuenta/bolsa \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del esquema ``` { "cuenta": "mi-cuenta", "plan_id": "crecimiento", "creditos": { "permitido": true, "motivo": "ok", "incluidos": 800, "gastados": "0.3426", "restantes": "799.6574", "porcentaje": "0.0004" }, "dias": 12, "renueva": "2026-10-15" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Armar ficha https://dev.bentho.org/api/fuentes/ficha-armar/ POST/api/mod/fuentes/{espacio}/fichas # Arma una fichaLe das un tema y una plantilla con los campos que quieres. Bentho busca en la web pública, lee las páginas y llena cada campo con el dato, la página de la que sale y la frase que lo respalda. Al terminar, la ficha se publica en los documentos del espacio. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | tema | string | SÍ | De qué trata la ficha, de 2 a 120 caracteres. | plantilla | string | SÍ | Los campos, en markdown: ## por sección y una línea - Nombre: qué buscar por campo. Su forma, en la guía. | paginas | integer | no | Cuántas páginas leer como mucho, de 1 a 5000. Por defecto 6. | urls | string[] | no | Páginas que ya conoces sobre el caso, HTTP o HTTPS. Se leen además de lo que encuentre, y marcan dónde seguir buscando. | como | object | no | Cómo buscar: ver como. ## RESPUESTA 202La ficha recién creada. Guarda su id. | | CAMPO | TIPO | QUÉ ES | id | string | El id de la ficha. | tema | string | El tema, sin espacios en los extremos. | status | "recibido" | En la cola. ## COMO | | CAMPO | TIPO | QUÉ ES | idioma | string | El idioma de la ficha y de la búsqueda. Por defecto "es". | dominios | string[] | Lee solo páginas de estos dominios (hasta 50). Vacío: toda la web pública. | rondas | integer | Vueltas de búsqueda, de 1 a 8 (por defecto 4). Cada una busca solo los campos que siguen vacíos. | paginas_por_ronda | integer | Páginas nuevas que lee cada vuelta, de 1 a 12 (por defecto 4). | instrucciones | string | Indicaciones para buscar, hasta 500 caracteres: «solo fuentes oficiales», «precios en pesos colombianos». | coherencia | boolean | Una ficha, un caso: descarta los datos de páginas que hablan de otro caso parecido. Por defecto false. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 422 | La plantilla no tiene ninguna sección con campos | La plantilla no tiene secciones con campos | 422 | Un campo fuera de su rango o de su tipo (detail es una lista) | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Responde enseguida: el trabajo sigue en segundo plano y suele tardar unos minutos. Consulta el estado cada 10 a 15 s. - Armar otra ficha con el mismo tema la reemplaza en los documentos del espacio: queda una versión nueva del mismo documento. - Si la web abierta da menos de la mitad de los campos, aportar 2 a 4 urls concretas del caso suele subir cuántos se llenan. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fichas \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "tema": "Café de especialidad del Huila", "plantilla": "# Café\n\n## Origen\n- Altitud: metros sobre el nivel del mar\n- Variedades: las que más se cultivan\n\n## Taza\n- Notas: aroma y sabor\n- Acidez: cómo la describen los catadores\n", "paginas": 6 }' ``` ■ 202 ACCEPTEDejemplo, con los campos del código ``` { "id": "8d4e1b7a2c9f4e6d8b3a5c7e9f1d2b4a", "tema": "Café de especialidad del Huila", "status": "recibido", … } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Estado de ficha https://dev.bentho.org/api/fuentes/ficha/ GET/api/mod/fuentes/{espacio}/fichas/{ficha} # El estado de una fichaLa ficha con su estado. La ruta que consultas mientras se arma. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | ficha | string | SÍ | El id de la ficha: el que devolvió armarla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | id · tema | string | El id y el tema. | status | string | Su estado: ver estados. | pages | integer | Páginas leídas. | error | string | Por qué falló. Vacío si no falló. | markdown | string | La ficha, cuando está publicada. Vacío antes. | created_at · updated_at | number | Segundos desde 1970, con decimales. ## ESTADOS DE UNA FICHA | | CAMPO | TIPO | QUÉ ES | recibido | en curso | En la cola, esperando su turno. | armando | en curso | Buscando, leyendo y llenando campos. | publicado | terminada | Armada y publicada en los documentos del espacio. Lo que encontró, en GET …/markdown. | fallido | terminada | No se pudo armar: mira error. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 404 | No hay una ficha con ese id en el espacio | La ficha no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Consulta cada 10 a 15 s. Para cuando status sea publicado o fallido. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fichas/8d4e1b7a2c9f4e6d8b3a5c7e9f1d2b4a \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKejemplo, con los campos del código ``` { "id": "8d4e1b7a2c9f4e6d8b3a5c7e9f1d2b4a", "tema": "Café de especialidad del Huila", "status": "armando", "pages": 0, "error": "", "markdown": "", "created_at": 1790000000.12, "updated_at": 1790000003.4, … } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Ficha en markdown https://dev.bentho.org/api/fuentes/ficha-markdown/ GET/api/mod/fuentes/{espacio}/fichas/{ficha}/markdown # La ficha armada y cómo se armóEl markdown de la ficha y su traza: qué páginas leyó, cuántos campos llenó, por qué paró de buscar y si se publicó. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | ficha | string | SÍ | El id de la ficha: el que devolvió armarla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | tema | string | El tema. | markdown | string | La ficha: cada campo con su valor, su Fuente y su Cita literal. Los vacíos dicen «sin respaldo en las páginas leídas». | pages | integer | Páginas leídas. | traza.campos · llenos | integer | Campos de la plantilla y cuántos llenó. | traza.completitud | number | La fracción llena, de 0 a 1. | traza.paginas[] | { url, tipo, caracteres, pasajes, sobre_tema } | Cada página leída y si trataba el tema. | traza.rondas[] | { ronda, consultas, nuevas } | Cada vuelta de búsqueda: qué buscó y cuántas páginas nuevas encontró. | traza.paginas_leidas | integer | Las páginas que leyó. | traza.paginas_con_texto | integer | Las que tenían algo útil. | traza.motivo_cierre | string | Por qué dejó de buscar: completa, rondas, paginas, tiempo… | traza.sugerencia | string | Solo si llenó menos de la mitad sin urls tuyas: qué aportar. | traza.publicacion | { status, document_id, version, unidades } | Si llegó a los documentos del espacio: published, sin_datos (ningún campo lleno, no publica nada) o fallida. | traza.segundos | number | Lo que tardó en armarse. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 404 | No hay una ficha con ese id en el espacio | La ficha no existe | 409 | La ficha no está en publicado (aún se arma, o falló) | La ficha todavía no está armada Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - En los documentos del espacio la ficha se llama ficha-.md y va cortada en trozos que se entienden solos, para que Bentho la use al responder. - La traza trae más campos de uso interno: no te apoyes en ellos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fichas/8d4e1b7a2c9f4e6d8b3a5c7e9f1d2b4a/markdown \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKejemplo, con los campos del código ``` { "tema": "Café de especialidad del Huila", "markdown": "# Café de especialidad del Huila\n\n> Ficha armada por Fuentes el 2026-10-01: 3 de 4 campos con respaldo, de 6 páginas leídas. …\n\n## Origen\n\n- **Altitud:** entre 1.200 y 2.000 m s. n. m.\n - Fuente: https://example.com/huila/cafe\n - Cita: «se cultiva entre 1.200 y 2.000 metros»\n…", "pages": 6, "traza": { "campos": 4, "llenos": 3, "completitud": 0.75, "paginas": [{ "url": "https://example.com/huila/cafe", "tipo": "html", "caracteres": 18240, "pasajes": 21, "sobre_tema": true }, …], "rondas": [{ "ronda": 1, "consultas": ["café Huila altitud variedades"], "nuevas": 4 }, …], "paginas_leidas": 6, "paginas_con_texto": 5, "motivo_cierre": "rondas", "publicacion": { "status": "published", "document_id": "…", "version": 1, "unidades": 5 }, "segundos": 84.2, … }, … } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Fichas https://dev.bentho.org/api/fuentes/fichas/ GET/api/mod/fuentes/{espacio}/fichas # Las fichas del espacioLas últimas fichas, la más reciente primero, sin plantilla ni markdown. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | limite | int, query | no | Cuántas, de 1 a 200. Por defecto 50. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | fichas | array | La más reciente primero. Cada una con id, tema, status, pages, error, created_at y updated_at, como en el estado. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 422 | Un campo fuera de su rango o de su tipo (detail es una lista) | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fichas \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "fichas": [ { "id": "8d4e1b7a2c9f4e6d8b3a5c7e9f1d2b4a", "tema": "Café de especialidad del Huila", "status": "publicado", "pages": 6, "error": "", "created_at": 1790000000.12, "updated_at": 1790000084.3, … } ] } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Crear fuente https://dev.bentho.org/api/fuentes/fuente-crear/ POST/api/mod/fuentes/{espacio}/fuentes # Crea una fuenteUna fuente son páginas o dominios que Bentho lee y publica en los documentos del espacio cada vez que la lanzas. Crearla no la lee: para eso, lánzala. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | nombre | string | SÍ | Para reconocerla, de 1 a 160 caracteres. | tema | string | no | De qué tratan las páginas, hasta 400 caracteres. | urls | string[] | UNA DE LAS DOS | Las páginas que se leen, hasta 50. | dominios | string[] | UNA DE LAS DOS | Dominios que se recorren, hasta 50. | campos | [{ nombre, descripcion }] | no | Hasta 20 datos que sacar de cada página. nombre: letras, números, _ y espacios, hasta 80; descripcion, hasta 400. | limites | { paginas, profundidad } | no | Páginas como mucho, de 1 a 50 (por defecto 20), y cuántos enlaces seguir desde cada una, 1 o 2 (por defecto 1). ## RESPUESTA 201La fuente, con estado lista. | | CAMPO | TIPO | QUÉ ES | id · nombre · tema | string | Los que diste al crearla. | urls · dominios | string[] | Los tuyos. | campos · limites | array · object | También los tuyos (limites, con sus valores por defecto). | estado | string | El de la última corrida, o lista si nunca se lanzó: ver estados. | paginas | integer | Páginas publicadas en la última corrida. | error | string | Por qué falló. Vacío si no falló. | run_id | string | null | La última corrida; null si ninguna. | actualizado | number | Segundos desde 1970, con decimales. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 422 | Sin urls ni dominios | La fuente necesita URLs o dominios | 422 | Un campo fuera de su rango o de su tipo (detail es una lista) | — Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fuentes \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "nombre": "Normativa de etiquetado", "tema": "etiquetado de alimentos", "urls": [ "https://example.com/normativa/etiquetado" ], "campos": [ { "nombre": "Plazo de adaptación", "descripcion": "fecha límite" } ] }' ``` ■ 201 CREATEDejemplo, con los campos del código ``` { "id": "c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40", "nombre": "Normativa de etiquetado", "tema": "etiquetado de alimentos", "urls": ["https://example.com/normativa/etiquetado"], "dominios": [], "campos": [{ "nombre": "Plazo de adaptación", "descripcion": "fecha límite" }], "limites": { "paginas": 20, "profundidad": 1 }, "estado": "lista", "paginas": 0, "error": "", "run_id": null, "actualizado": 1790000420.5 } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Lanzar fuente https://dev.bentho.org/api/fuentes/fuente-lanzar/ POST/api/mod/fuentes/{espacio}/fuentes/{fuente}/lanzar # Lanza una fuenteLee las páginas de la fuente y publica lo leído en los documentos del espacio. Si ya hay una corrida en la cola, te devuelve esa. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | fuente | string | SÍ | El id de la fuente: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 202 | | CAMPO | TIPO | QUÉ ES | run_id | string | La corrida. | status | "recibido" | En la cola. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 404 | No hay una fuente con ese id en el espacio | La fuente no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Sigue la corrida con GET fuentes/{fuente}: su estado pasa a publicado, fallido o cancelado. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X POST https://bentho.org/api/mod/fuentes/mi-espacio/fuentes/c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40/lanzar \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 202 ACCEPTEDderivado del código ``` { "run_id": "4b0e7c2a9d1f4e8a6c3b5d7f9e2a1c04", "status": "recibido" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Fuente https://dev.bentho.org/api/fuentes/fuente/ GET/api/mod/fuentes/{espacio}/fuentes/{fuente} # Una fuente y su última corridaLa fuente, con el estado de su última corrida. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | fuente | string | SÍ | El id de la fuente: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | id · nombre · tema | string | Los que diste al crearla. | urls · dominios | string[] | Los tuyos. | campos · limites | array · object | También los tuyos (limites, con sus valores por defecto). | estado | string | El de la última corrida, o lista si nunca se lanzó: ver estados. | paginas | integer | Páginas publicadas en la última corrida. | error | string | Por qué falló. Vacío si no falló. | run_id | string | null | La última corrida; null si ninguna. | actualizado | number | Segundos desde 1970, con decimales. ## ESTADOS DE UNA FUENTE | | CAMPO | TIPO | QUÉ ES | lista | sin lanzar | Creada; todavía no se ha lanzado. | recibido | en curso | En la cola, esperando su turno. | adquirido · normalizado | en curso | Leyendo las páginas y limpiándolas. | estructurado · revisado | en curso | Sacando los campos y revisando antes de publicar. | publicado | terminada | Lo leído está en los documentos del espacio. | fallido | terminada | No se pudo: mira error. | cancelado | terminada | La cancelaste. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 404 | No hay una fuente con ese id en el espacio | La fuente no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fuentes/c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40 \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKejemplo, con los campos del código ``` { "id": "c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40", "nombre": "Normativa de etiquetado", "tema": "etiquetado de alimentos", "urls": ["https://example.com/normativa/etiquetado"], "dominios": [], "campos": [{ "nombre": "Plazo de adaptación", "descripcion": "fecha límite" }], "limites": { "paginas": 20, "profundidad": 1 }, "estado": "publicado", "paginas": 12, "error": "", "run_id": "4b0e7c2a9d1f4e8a6c3b5d7f9e2a1c04", "actualizado": 1790000420.5 } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Fuentes https://dev.bentho.org/api/fuentes/fuentes/ GET/api/mod/fuentes/{espacio}/fuentes # Las fuentes del espacioTodas las fuentes, la más reciente primero, cada una con su última corrida. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | fuentes | array | La más reciente primero. Cada una, con los campos de GET fuentes/{fuente}. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/fuentes/mi-espacio/fuentes \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "fuentes": [ { "id": "c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40", "nombre": "Normativa de etiquetado", "estado": "publicado", … } ] } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Cancelar fuente https://dev.bentho.org/api/fuentes/fuente-cancelar/ POST/api/mod/fuentes/{espacio}/fuentes/{fuente}/cancelar # Cancela la corrida de una fuentePara la última corrida. Si aún estaba en la cola, se cancela ya; si estaba leyendo, para al acabar el paso en curso. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | fuente | string | SÍ | El id de la fuente: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | run_id | string | La corrida. | status | string | cancelado si ya paró; si no, su estado actual: consulta la fuente. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 404 | No hay una fuente con ese id en el espacio | La fuente no existe | 404 | La fuente nunca se lanzó | La fuente no tiene corridas Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X POST https://bentho.org/api/mod/fuentes/mi-espacio/fuentes/c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40/cancelar \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "run_id": "4b0e7c2a9d1f4e8a6c3b5d7f9e2a1c04", "status": "cancelado" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Fuentes · Borrar fuente https://dev.bentho.org/api/fuentes/fuente-borrar/ DEL/api/mod/fuentes/{espacio}/fuentes/{fuente} # Borra una fuenteBorra la fuente, para la corrida que estuviera en la cola y quita de los documentos del espacio lo que publicó. No se puede deshacer. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Fuentes. | fuente | string | SÍ | El id de la fuente: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | id | string | La fuente borrada. | status | "deleted" | Hecho. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Fuentes | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 404 | No hay una fuente con ese id en el espacio | La fuente no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X DELETE https://bentho.org/api/mod/fuentes/mi-espacio/fuentes/c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40 \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "id": "c27a9e4f1b8d4a6c9e2f7b3d5a1c8e40", "status": "deleted" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Crear https://dev.bentho.org/api/landings/crear/ POST/api/mod/landing/{espacio}/landings # Crea una landingMandas el brief y la URL que recibe el formulario. Bentho escribe la landing, la prueba en un navegador y la deja lista para publicar. Contesta al momento con el id; el trabajo sigue en segundo plano. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | prompt | string | SÍ | El brief: qué ofreces, a quién, con qué tono, qué secciones y qué datos (precios, fechas, testimonios). Hasta 24 000 caracteres. | submitUrl | string | SÍ | Adónde envía sus datos el formulario. HTTP o HTTPS, sin usuario ni contraseña. Qué le llega, en la guía. | titulo | string | no | Para reconocerla en la lista. Hasta 120 caracteres; sin él, el comienzo del brief. | pageId | string | no | Tu identificador de la página, hasta 200 caracteres. El formulario lo manda como page_id en cada envío. | brandBlock | string | no | Tu marca, en texto: nombre, colores, tipografías, tono, URL del logotipo. Hasta 20 000 caracteres. | formConfig | object | no | El formulario: campos, mensaje de éxito, botones y redirección. Su forma, en la guía. | chatHistory | [{ role, content }] | no | La conversación con tu usuario que llevó a esta petición, si la hay. Hasta 50 mensajes de 8000 caracteres. | funnelReferenceHtml | string | no | El HTML de otra página de tu embudo, para que esta siga su estilo. Hasta 300 000 caracteres. | pdf | { data, name? } | no | Un PDF con la información del producto, en base64 en data. Hasta 16 000 000 de caracteres (unos 12 MB de PDF). | revisarBrief | boolean | no | Por defecto true: antes de escribir, revisa si el brief pide datos que no da y te los pregunta (esperando_datos). Con false, no pregunta. ## RESPUESTA 202 | | CAMPO | TIPO | QUÉ ES | id | string | El id de la landing. | version | integer | El número de la versión que se encoló. | trabajo | string | El id de esa versión. Para seguirla te basta con id y version. | status | "pendiente" | Siempre pendiente al encolar. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 413 | El cuerpo pasa de 24 MB | Cuerpo demasiado grande | 422 | Falta prompt | prompt es obligatorio | 422 | submitUrl no es una URL HTTP/HTTPS, o lleva usuario o contraseña | submitUrl debe ser una URL HTTP/HTTPS sin credenciales | 422 | Un campo que no es de esta ruta | Campos no admitidos: … | 429 | El espacio tiene demasiadas landings generándose a la vez | Hay demasiadas landings en curso en este espacio; espera a que terminen. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Responde enseguida: el trabajo sigue en segundo plano y suele tardar unos minutos. Sigue la versión con GET landings/{landing}. - Mientras se prueba, el formulario no envía nada de verdad: a tu submitUrl no le llegan envíos de prueba. - Un formConfig que no cumple su forma no da 422: la versión termina en fallido y error dice por qué. - Los 422 del módulo traen el detail como texto ("prompt es obligatorio"), no como lista. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Landing para el curso online «Excel para pymes»: 6 semanas, en directo los martes a las 19:00, 149 €. Público: dueños de pequeños negocios. Tono cercano. Formulario de preinscripción con nombre, email y teléfono.", "submitUrl": "https://example.com/api/leads", "titulo": "Excel para pymes" }' ``` ■ 202 ACCEPTEDejemplo, con los campos del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "version": 1, "trabajo": "b81e6d0c47a94f2e9c3d5a1b7e2f8c60", "status": "pendiente" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Lista https://dev.bentho.org/api/landings/lista/ GET/api/mod/landing/{espacio}/landings # Las landings del espacioLas landings del espacio, la última que cambió primero, cada una con su última versión. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | limite | int, query | no | Cuántas, de 1 a 200. Por defecto 50. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | landings | array | La última que cambió, primero. Cada una con los campos de GET landings/{landing} salvo versiones, y además: | landings[].ultima | object | null | Su última versión, con la misma forma que versiones[] en GET landings/{landing}. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 422 | limite no es un número | limite inválido Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "landings": [ { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "titulo": "Excel para pymes", "submit_url": "https://example.com/api/leads", "page_id": null, "status": "aprobado", "version_actual": 2, "version_aprobada": 2, "version_con_html": 2, "creada": 1790000000.12, "actualizada": 1790000420.5, "ultima": { "version": 2, "tipo": "generar", "status": "aprobado", … } } ] } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Estado https://dev.bentho.org/api/landings/estado/ GET/api/mod/landing/{espacio}/landings/{landing} # El estado de una landingLa landing con todas sus versiones, la más reciente primero. Es la ruta que consultas mientras se escribe, hasta que su status termina o pide datos. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | id · titulo | string | El id y el título. | submit_url · page_id | string · string | null | Los que mandaste al crearla. | status | string | El estado de la última versión. | version_actual | integer | La última versión, termine como termine. | version_aprobada | integer | null | La última que pasó las dos revisiones. null si ninguna. | version_con_html | integer | null | La última que tiene HTML, aprobada o no. | creada · actualizada | number | Segundos desde 1970, con decimales. | versiones | array | Todas, la más reciente primero. | versiones[].version | integer | 1, 2, 3… | versiones[].tipo | "generar" | "refinar" | "validar" | Qué la creó. | versiones[].status | string | Su estado: ver estados. | versiones[].etapa | string | null | Qué está haciendo ahora, para enseñárselo a tu usuario. Texto libre: no lo compares. | versiones[].faltantes | array | null | Solo en esperando_datos: hasta 5 datos que el brief pide y no da, cada uno con clave, seccion, pregunta y ejemplo. Respóndelos con completar. | versiones[].calidad | object | null | El certificado de las revisiones, cuando la versión termina: ver calidad. | versiones[].error | string | null | Por qué falló o se canceló, en una frase para tu usuario. | versiones[].creada | number | Segundos desde 1970, con decimales. | versiones[].iniciada · terminada | number | null | Igual; null mientras no ha empezado o no ha terminado. ## ESTADOS DE UNA VERSIÓN | | CAMPO | TIPO | QUÉ ES | pendiente | en curso | En la cola, esperando su turno. | generando | en curso | Escribiendo, probando o reparando. Mira etapa. | aplazado | en curso | Esperando capacidad. Se reanuda sola: no hagas nada. | esperando_datos | espera tu respuesta | El brief pide datos que no da. Responde con completar; no gasta mientras espera. | aprobado | terminada | Pasó las dos revisiones: lista para publicar. | revision | terminada | Tiene HTML, pero no pasó alguna revisión: calidad.motivos dice cuál. Refínala o revísala tú. | fallido | terminada | No se pudo terminar: mira error. | cancelado | terminada | La cancelaste (o borraste la landing). ## CALIDAD | | CAMPO | TIPO | QUÉ ES | status | "approved" | "needs_review" | "failed" | approved solo si pasó las dos revisiones. | motivos | string[] | Por qué no se aprobó. Vacío si se aprobó. | emitido | string | null | Cuándo, en ISO 8601. | html_sha256 | string | null | El SHA-256 del HTML que certifica. Vale para ese HTML exacto: si lo cambias, mándalo a validar. | funcional | object | null | La revisión de funcionamiento: status (passed o needs_review), brief_cumplido, los escenarios que probó y sus hallazgos. | visual | object | null | La revisión de diseño, en escritorio y en móvil: status, el umbral y una nota de 0 a 100 en cada una de sus dimensiones (hierarchy, composition, typography, spacing, consistency, legibility, imagery, mobile). Para aprobar, todas llegan al umbral. | hallazgos[] | { severidad, descripcion, correccion } | Lo que encontró cada revisión. severidad es blocker, major o minor; solo los minor dejan aprobar. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Consulta cada 10 a 15 s. Para cuando status sea aprobado, revision, fallido o cancelado, o cuando sea esperando_datos: ahí espera tu respuesta. - Una versión en aplazado sigue sola. Puede tardar más, pero no hace falta que hagas nada. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3 \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKejemplo, con los campos del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "titulo": "Excel para pymes", "submit_url": "https://example.com/api/leads", "page_id": null, "status": "esperando_datos", "version_actual": 1, "version_aprobada": null, "version_con_html": null, "creada": 1790000000.12, "actualizada": 1790000038.4, "versiones": [ { "version": 1, "tipo": "generar", "status": "esperando_datos", "etapa": null, "faltantes": [ { "clave": "fecha_inicio", "seccion": "Hero", "pregunta": "¿Qué día empieza el curso?", "ejemplo": "Empieza el martes 3 de noviembre." }, { "clave": "testimonios", "seccion": "Opiniones", "pregunta": "¿Tienes opiniones reales de alumnos, con su nombre?", "ejemplo": "«Ahora cierro el mes en una tarde», Ana R., panadería." } ], "calidad": null, "error": null, "creada": 1790000000.12, "iniciada": 1790000001.3, "terminada": null } ] } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · HTML https://dev.bentho.org/api/landings/html/ GET/api/mod/landing/{espacio}/landings/{landing}/html # El HTML de una landingEl HTML listo para publicar, con su certificado de calidad. Sin version, la última aprobada; si ninguna lo está, la última que tenga HTML. - PERMISOlee (vale cualquier clave) - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). | version | int, query | no | Una versión concreta. ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | version | integer | La versión que te da. | html | string | Un documento completo, en un solo archivo y con su formulario conectado. Publícalo tal cual. | calidad | object | null | Su certificado (abajo). Publica lo que tenga status: "approved"; lo demás, revísalo antes. ## CALIDAD | | CAMPO | TIPO | QUÉ ES | status | "approved" | "needs_review" | "failed" | approved solo si pasó las dos revisiones. | motivos | string[] | Por qué no se aprobó. Vacío si se aprobó. | emitido | string | null | Cuándo, en ISO 8601. | html_sha256 | string | null | El SHA-256 del HTML que certifica. Vale para ese HTML exacto: si lo cambias, mándalo a validar. | funcional | object | null | La revisión de funcionamiento: status (passed o needs_review), brief_cumplido, los escenarios que probó y sus hallazgos. | visual | object | null | La revisión de diseño, en escritorio y en móvil: status, el umbral y una nota de 0 a 100 en cada una de sus dimensiones (hierarchy, composition, typography, spacing, consistency, legibility, imagery, mobile). Para aprobar, todas llegan al umbral. | hallazgos[] | { severidad, descripcion, correccion } | Lo que encontró cada revisión. severidad es blocker, major o minor; solo los minor dejan aprobar. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe | 404 | Esa versión no existe | La versión no existe | 409 | Sin version: ninguna versión tiene HTML todavía | La landing todavía no tiene HTML | 409 | Esa versión no tiene HTML (en curso, fallida o cancelada) | La versión todavía no tiene HTML | 422 | version no es un número | version inválido Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Un 409 aquí no es un error de tu lado: la versión aún no termina. Espera a que version_con_html deje de ser null en el estado. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3/html \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKejemplo, con los campos del código ``` { "version": 2, "html": "…", "calidad": { "status": "approved", "motivos": [], "emitido": "2026-10-02T15:04:05.000Z", "html_sha256": "9b1c…", "funcional": { "status": "passed", "brief_cumplido": true, "escenarios": [ … ], "hallazgos": [] }, "visual": { "status": "passed", "umbral": 75, "dimensiones": { "hierarchy": 88, … }, "hallazgos": [] } } } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Completar datos https://dev.bentho.org/api/landings/completar/ POST/api/mod/landing/{espacio}/landings/{landing}/completar # Responde a lo que faltaCuando una versión queda en esperando_datos, mandas aquí lo que tu usuario responda a sus faltantes y la versión sigue. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | respuestas | { clave: texto } | no | Una respuesta por clave de faltantes. Hasta 4000 caracteres cada una. Se añaden al brief. | omitir | string[] | no | Las claves que tu usuario no tiene o no quiere dar. Esa parte se escribe sin ese dato, y sin decirle al visitante que falta. ## RESPUESTA 202 | | CAMPO | TIPO | QUÉ ES | id · version | string · integer | La landing y la versión que sigue. | status | "pendiente" | Vuelve a la cola. | aportados | string[] | Las claves que respondiste. | declinados | string[] | Las que omitiste o dejaste sin responder. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe | 409 | Ninguna versión está en esperando_datos | La landing no está esperando datos. | 422 | Una clave que no está en faltantes | Claves desconocidas: … | 422 | respuestas no es un objeto de textos, o uno pasa de 4000 caracteres | respuestas debe ser un objeto {clave: texto} de hasta 4000 caracteres por respuesta Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Lo que no respondas ni omitas cuenta como omitido: un cuerpo vacío sigue sin ninguno de esos datos. - Responde enseguida: el trabajo sigue en segundo plano y suele tardar unos minutos. Sigue la versión con GET landings/{landing}. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3/completar \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "respuestas": { "fecha_inicio": "Empieza el martes 3 de noviembre de 2026." }, "omitir": [ "testimonios" ] }' ``` ■ 202 ACCEPTEDejemplo, con los campos del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "version": 1, "status": "pendiente", "aportados": ["fecha_inicio"], "declinados": ["testimonios"] } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Refinar https://dev.bentho.org/api/landings/refinar/ POST/api/mod/landing/{espacio}/landings/{landing}/refinar # Pide cambios a una landingCrea una versión nueva sobre la última que tiene HTML, con la instrucción que le des. Las anteriores se conservan: puedes volver a cualquiera con ?version=. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | prompt | string | SÍ | Qué cambiar, en texto libre. Hasta 24 000 caracteres. | brandBlock | string | no | Tu marca, en texto: nombre, colores, tipografías, tono, URL del logotipo. Hasta 20 000 caracteres. | formConfig | object | no | El formulario: campos, mensaje de éxito, botones y redirección. Su forma, en la guía. | chatHistory | [{ role, content }] | no | La conversación con tu usuario que llevó a esta petición, si la hay. Hasta 50 mensajes de 8000 caracteres. ## RESPUESTA 202 | | CAMPO | TIPO | QUÉ ES | id | string | El id de la landing. | version | integer | El número de la versión que se encoló. | trabajo | string | El id de esa versión. Para seguirla te basta con id y version. | status | "pendiente" | Siempre pendiente al encolar. | base | integer | La versión sobre la que trabaja. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe | 409 | La landing ya tiene una versión en curso: espera o cancélala | La landing ya tiene una versión en curso. | 409 | Ninguna versión tiene HTML todavía | La landing todavía no tiene una versión sobre la que trabajar. | 422 | Falta prompt | prompt es obligatorio | 429 | El espacio tiene demasiadas landings generándose a la vez | Hay demasiadas landings en curso en este espacio; espera a que terminen. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Retoca sin reescribir: cambia lo que pides y deja el resto. La versión nueva pasa otra vez por las dos revisiones. - Refinar no revisa el brief: no pasa por esperando_datos. Si el cambio trae datos nuevos, ponlos en el prompt. - Responde enseguida: el trabajo sigue en segundo plano y suele tardar unos minutos. Sigue la versión con GET landings/{landing}. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3/refinar \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Cambia el botón principal a «Reserva tu plaza» y pon el precio junto al formulario." }' ``` ■ 202 ACCEPTEDejemplo, con los campos del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "version": 3, "trabajo": "5d2c8e1f9a0b4c7d8e6f1a2b3c4d5e6f", "status": "pendiente", "base": 2 } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Validar https://dev.bentho.org/api/landings/validar/ POST/api/mod/landing/{espacio}/landings/{landing}/validar # Valida un HTML editado a manoSi retocaste la landing por tu cuenta, mándala aquí: Bentho la vuelve a probar y repara lo que falle sin cambiar su contenido. Sin html, valida la última versión. - PERMISOescribe - CRÉDITOSgasta créditos - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). ## CUERPO · JSON | | CAMPO | TIPO | REQUERIDO | QUÉ ES | html | string | no | El documento completo, de a . Hasta 300 000 caracteres. Parte del html de GET …/html. | formConfig | object | no | El formulario: campos, mensaje de éxito, botones y redirección. Su forma, en la guía. ## RESPUESTA 202 | | CAMPO | TIPO | QUÉ ES | id | string | El id de la landing. | version | integer | El número de la versión que se encoló. | trabajo | string | El id de esa versión. Para seguirla te basta con id y version. | status | "pendiente" | Siempre pendiente al encolar. | base | integer | La última versión con HTML. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 402 | La cuenta agotó sus créditos del ciclo | La cuenta de este espacio agotó sus créditos de este ciclo. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe | 409 | La landing ya tiene una versión en curso: espera o cancélala | La landing ya tiene una versión en curso. | 409 | Ninguna versión tiene HTML todavía | La landing todavía no tiene una versión sobre la que trabajar. | 422 | html no empieza por | html debe ser un documento completo (…) | 429 | El espacio tiene demasiadas landings generándose a la vez | Hay demasiadas landings en curso en este espacio; espera a que terminen. Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Responde enseguida: el trabajo sigue en segundo plano y suele tardar unos minutos. Sigue la versión con GET landings/{landing}. CURLPYTHONJAVASCRIPT COPIAR ``` curl https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3/validar \ -H "Authorization: Bearer $BENTHO_KEY" \ -H "Content-Type: application/json" \ -d '{ "html": "…" }' ``` ■ 202 ACCEPTEDejemplo, con los campos del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "version": 4, "trabajo": "9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b", "status": "pendiente", "base": 3 } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Cancelar https://dev.bentho.org/api/landings/cancelar/ POST/api/mod/landing/{espacio}/landings/{landing}/cancelar # Cancela la versión en cursoPara la versión que se está escribiendo o que espera datos. Las versiones terminadas no cambian. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | id | string | La landing. | status | "cancelado" | "cancelando" | cancelado: ya está parada (o no había nada en curso). cancelando: se para al acabar el paso en curso; consulta el estado. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - No gasta créditos y funciona aunque la bolsa esté agotada. Lo que la versión ya gastó no se devuelve. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X POST https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3/cancelar \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "status": "cancelando" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # Landings · Borrar https://dev.bentho.org/api/landings/borrar/ DEL/api/mod/landing/{espacio}/landings/{landing} # Borra una landingBorra el brief y el HTML de todas sus versiones, y cancela lo que estuviera en curso. No se puede deshacer. - PERMISOescribe - CRÉDITOSno gasta - AUTENTICACIÓNBearer bth_… ## PARÁMETROS | | CAMPO | TIPO | REQUERIDO | QUÉ ES | espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Landings. | landing | string | SÍ | El id de la landing: el que devolvió crearla (32 caracteres hexadecimales). ## RESPUESTA 200 | | CAMPO | TIPO | QUÉ ES | id | string | La landing borrada. | status | "deleted" | Hecho. ## ERRORES DE ESTA RUTA · SIEMPRE {"detail": …} | | STATUS | CUÁNDO | DETAIL LITERAL | 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. | 403 | El espacio no tiene el módulo Landings | módulo no habilitado para este espacio. | 404 | No hay una landing con ese id en el espacio (o se borró) | La landing no existe Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos. ## CONVIENE SABER - Lo gastado sigue contando en tu bolsa: borrar no devuelve créditos. CURLPYTHONJAVASCRIPT COPIAR ``` curl -X DELETE https://bentho.org/api/mod/landing/mi-espacio/landings/3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3 \ -H "Authorization: Bearer $BENTHO_KEY" ``` ■ 200 OKderivado del código ``` { "id": "3f9c2a7e5b1d4c8fa6e0b2d9c4f1a7e3", "status": "deleted" } ``` PARA AGENTESTodo esto en texto: /llms-full.txt y la skill bentho-api. --- # ADK https://dev.bentho.org/adk/ ADK · PRONTO # Agent Development KitEstamos preparando el ADK de Bentho: el kit para construir agentes que usan tus espacios como fuente, en Python y JavaScript, sin escribir a mano las cabeceras, los reintentos ni el manejo de eventos. Todavía no está publicado. No hace falta esperar. La API es HTTP y JSON: cualquier lenguaje que haga una petición sirve hoy. Los ejemplos de cada ruta ya vienen en curl, Python y JavaScript. ## PythonMientras llega el paquete, basta requests (o httpx si trabajas con asyncio): PYTHONCOPIAR ``` import os, requests BENTHO = "https://bentho.org/api" CABECERAS = {"Authorization": f"Bearer {os.environ['BENTHO_KEY']}"} def preguntar(espacio: str, pregunta: str, sesion: str | None = None) -> dict: r = requests.post( f"{BENTHO}/rag/{espacio}/conversations", headers=CABECERAS, json={"question": pregunta, "session_id": sesion}, timeout=60, ) r.raise_for_status() return r.json() ``` ## JavaScriptCon fetch, en Node 18+ o en el navegador de tu backend. No pongas la clave en código que llegue al navegador de tus usuarios. JAVASCRIPTCOPIAR ``` const BENTHO = "https://bentho.org/api"; export async function preguntar(espacio, pregunta, sesion) { const r = await fetch(`${BENTHO}/rag/${espacio}/conversations`, { method: "POST", headers: { Authorization: `Bearer ${process.env.BENTHO_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ question: pregunta, session_id: sesion }), signal: AbortSignal.timeout(60_000), }); if (!r.ok) throw new Error(`Bentho respondió ${r.status}`); return r.json(); } ``` ## Mientras tanto, HTTPEmpieza por el quickstart y ten a mano errores, límites y créditos: son las dos páginas que un cliente propio necesita para ser robusto. Si tu agente ya lee skills, dale la skill bentho-api: le explica la API entera. --- # Skills https://dev.bentho.org/skills/ SKILLS # Enséñale Bentho a tu agenteSi un agente escribe tu integración o llama a la API por ti, dale el contexto correcto en vez de dejar que lo adivine. Aquí tienes dos formas: una skill lista para instalar y el texto de toda la documentación en formato para modelos. ## Skill bentho-apiUn SKILL.md con lo que un agente necesita para usar la API sin inventar nada: cómo autenticarse, qué ruta usar para cada tarea, qué significan status_code, confidence y warning, y cómo reaccionar a cada error (cuándo reintentar y cuándo parar). Ver o descargar SKILL.md ## llms.txtPara agentes que leen documentación por su cuenta: - /llms.txt: el índice de páginas, con una línea por página. - /llms-full.txt: todo el contenido en texto plano, en un solo archivo. ## Instálala en tu agente ### Claude CodeLas skills de un proyecto viven en .claude/skills/. Desde la raíz de tu repositorio: BASHCOPIAR ``` mkdir -p .claude/skills/bentho-api curl -fsSL https://dev.bentho.org/skills/bentho-api/SKILL.md \ -o .claude/skills/bentho-api/SKILL.md ``` El agente la usa cuando la tarea tiene que ver con Bentho. Necesita la clave en una variable de entorno (BENTHO_KEY), nunca pegada en el código. ### Otros agentesPásale la URL de /llms.txt o el contenido de SKILL.md como instrucciones del sistema. Dale la clave con el menor permiso que sirva. Si el agente solo pregunta y lee, usa una clave lee: no podrá subir ni borrar documentos ni cambiar la configuración. --- # Cambios https://dev.bentho.org/cambios/ CAMBIOS # Qué cambió en la API, y cuándoCada cambio que ve quien integra, del más reciente al más antiguo. La regla de v1 es simple: se agregan campos, nunca se quitan ni se renombran. ## Landings por la APIEN PREPARACIÓN · 2026-10-02 Ya puedes consultar la guía y preparar la integración de Landings. Su uso por API o desde el Estudio requiere que el módulo esté disponible y habilitado en tu espacio. Crear, refinar, validar y completar gastan créditos. ## Fuentes por la APINUEVO · 2026-10-01 Con el módulo Fuentes, arma fichas con datos de la web pública (cada uno con su página y su cita) y publícalas en los documentos del espacio. Armar una ficha y lanzar una fuente gastan créditos. ## Validaciones más estrictas en la entradaSEGURIDAD · 2026-09-25 Ninguna ruta ni campo cambió de forma. ## Consumo medido en créditos, por rutaNUEVO · 2026-09-24 Cada llamada descuenta créditos de la bolsa de tu cuenta según su uso. Consulta el saldo con GET /api/cuentas/{cuenta}/bolsa. ## La lista de IPs compara con la IP pública de tu servidorCORRECCIÓN · 2026-09-18 Una lista que incluye tu IP ya no te rechaza por error. ## Los mandos de confianza del Cerebro, con sus rangosNUEVO · 2026-09-18 GET /api/rag/{espacio}/config devuelve, además de la configuración, qué campos puedes editar y el rango válido de cada uno. ## api-config: límites, cuota diaria e IPs por espacioNUEVO · 2026-09-18 Cada espacio decide si su API está activa, cuántas peticiones por segundo acepta, su ráfaga, su cuota diaria y qué IPs pueden llamar. ## El consumo se atribuye a la clave que llamaNUEVO · 2026-09-17 Ves cuánto consume cada clave. ## Claves de servicio bth_NUEVO · 2026-09-16 Claves con alcance por espacios, permiso de lectura o escritura y revocación. El secreto se muestra una sola vez.