Bots API
Usar la IA de Sendeasy desde tu propia aplicación — un asistente dentro de tu producto, una rutina en tu backend, una pantalla que resume documentos — sin pasar por WhatsApp.
El bot es quien carga las instrucciones: lo creas y editas en el panel, y aquí indicas el botId. Cambiar el comportamiento de la IA es editar el bot, no cambiar tu código.
Requisitos previos
- API Token del proyecto — en Integraciones → WABA → sección API Tokens, donde creas un token con nombre y puedes revocarlo. Es el mismo token de la WABA API y de la Email API: uno por proyecto, no uno por producto.
- Un bot creado en el panel, con sus instrucciones y fuentes de conocimiento — consulta /es/bot. Guarda el
botId. - Créditos de bot disponibles en el plan del proyecto.
Usa GET /api/v1/ai/health para verificar la integración sin gastar crédito.
Autenticación
Header obligatorio:
Authorization: Bearer <api_token>
El token identifica el proyecto, y es él quien autoriza el botId: un bot de otro proyecto es rechazado, aunque conozcas el id.
Es el mismo API Token que usa la WABA API. Revocarlo en Integraciones → WABA tumba todas las integraciones que dependen de él, no solo esta.
Endpoints
| Método | Endpoint | Finalidad | Crédito |
|---|---|---|---|
POST | /api/v1/ai/completion | Generar texto con el prompt del bot | 1 por generación |
POST | /api/v1/ai/extract | Extraer contenido de un PDF | 1 por archivo |
POST | /api/v1/ai/search | Buscar en la base de conocimiento del bot | no consume |
GET | /api/v1/ai/health | Diagnóstico: ¿la integración está en pie? | no consume |
Límite: 60 solicitudes por minuto por API Token (429 ERR_PUBLIC_AI_RATE_LIMIT). El conteo es por token, no por IP: varios servidores que usan el mismo token comparten la cuota, y el mismo servidor con tokens distintos tiene cuotas separadas.
Generación de texto
POST /api/v1/ai/completion
Payload
| Campo | Tipo | Obligatorio | Observaciones |
|---|---|---|---|
prompt | string | Sí | el pedido en sí, hasta 120.000 caracteres |
botId | string | Uno de los dos | usa las instrucciones y el conocimiento de ese bot |
instructions | string | Uno de los dos | system prompt suelto, hasta 60.000 caracteres |
responseFormat | string | No | text (predeterminado) o json |
timeoutMs | number | No | entre 1.000 y 90.000; predeterminado del servicio si se omite |
Indica botId o instructions. Sin ninguno de los dos la ruta responde 400, en lugar de gastar crédito para devolver texto fuera de contexto.
Ejemplo
curl --location 'https://backend.sendeasy.app/api/v1/ai/completion' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TU_API_TOKEN' \
--data '{
"botId": "tu-bot-id",
"prompt": "Resume en dos párrafos la política de devoluciones."
}'
Respuesta de éxito:
{
"success": true,
"result": "La política de devoluciones permite devolver en hasta 30 días..."
}
Con "responseFormat": "json", la respuesta llega parseada en dados en lugar de result — útil cuando el prompt pide una estructura y no quieres tratar el texto:
{
"success": true,
"dados": { "prazo_dias": 30, "exige_nota": true }
}
Cada solicitud mantiene una conexión abierta hasta que la IA responde. Prefiere un timeoutMs corto en pantallas donde alguien está esperando, y deja el techo de 90s para rutinas en segundo plano.
Extracción de PDF
POST /api/v1/ai/extract
Envío multipart/form-data con el archivo en el campo file. Solo PDF, hasta 25 MB.
| Campo | Tipo | Obligatorio | Observaciones |
|---|---|---|---|
file | file | Sí | el PDF, application/pdf |
mode | string | No | text (predeterminado) devuelve el texto en result; otros modos devuelven el payload en dados |
curl --location 'https://backend.sendeasy.app/api/v1/ai/extract' \
--header 'Authorization: Bearer TU_API_TOKEN' \
--form 'file=@"/ruta/contrato.pdf"' \
--form 'mode="text"'
{
"success": true,
"result": "CONTRATO DE PRESTACIÓN DE SERVICIOS..."
}
La lectura usa OCR cuando el PDF está escaneado, así que los archivos grandes tardan. Si la IA no reconoce el contenido, la respuesta es 502 con la explicación del motivo — reenviar el mismo archivo no lo resuelve.
Búsqueda en la base de conocimiento
POST /api/v1/ai/search
Recupera fragmentos de las fuentes del bot, sin generar texto. Sirve para fundamentar una respuesta tuya, o para mostrar al usuario de dónde salió la información.
| Campo | Tipo | Obligatorio | Observaciones |
|---|---|---|---|
botId | string | Sí | en qué bot buscar |
query | string | Sí | qué buscar, hasta 2.000 caracteres |
topK | number | No | cuántos fragmentos devolver, de 1 a 8 |
filters | object | No | restringe la búsqueda a ciertos documentos (ver abajo) |
filters acepta dos campos, ambos listas de patrones de nombre de archivo (% coincide con cualquier tramo):
| Campo | Efecto |
|---|---|
incluirArquivos | busca solo en los documentos que coincidan; omitido, recorre toda la base |
excluirArquivos | descarta los documentos que coincidan, aunque estén incluidos |
{
"botId": "tu-bot-id",
"query": "plazo de garantía",
"filters": {
"incluirArquivos": ["manual-%", "politica-cambios.pdf"],
"excluirArquivos": ["borrador-%"]
}
}
Sirve cuando la base es grande y ya sabes dónde está la respuesta: sin filtro, un documento extenso puede ocupar los lugares del resultado y tapar lo que importa.
curl --location 'https://backend.sendeasy.app/api/v1/ai/search' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TU_API_TOKEN' \
--data '{
"botId": "tu-bot-id",
"query": "plazo de garantía",
"topK": 3
}'
{
"success": true,
"trechos": [
{
"texto": "La garantía legal es de 90 días para productos duraderos...",
"procedencia": "manual-del-cliente.pdf",
"score": 0.82
}
]
}
No consume crédito: es recuperación de contenido, no generación. Si la búsqueda falla, la respuesta llega con trechos: [] en lugar de error — sin contexto tu respuesta pierde fundamento, no deja de existir.
Diagnóstico de la integración
GET /api/v1/ai/health
No consume crédito y no invoca al modelo. Responde las dos preguntas detrás de casi toda falla de integración: ¿el servicio de IA está en línea y todavía hay saldo?
curl --location 'https://backend.sendeasy.app/api/v1/ai/health' \
--header 'Authorization: Bearer TU_API_TOKEN'
{
"success": true,
"companyId": 42,
"botrag": { "ok": true, "latenciaMs": 210 },
"creditos": { "disponivel": 4820, "mes": "9/2026" },
"checkedAt": "2026-09-01T12:30:00.000Z"
}
botrag.ok: false— el servicio de IA no está disponible; un campodetalheacompaña la causa. Nada que hacer de tu lado salvo reintentar más tarde.creditos.disponivel: 0— el proyecto se quedó sin créditos y las rutas de generación responderán402. Renueva el plan o espera la franquicia del mes siguiente.
A qué bots llega el token
El botId se resuelve dentro del proyecto de tu API Token. Un token de un proyecto no puede usar el bot de otro, aunque conozca el id: la ruta responde 403 sin generar nada ni tocar tu saldo. Un bot que no existe responde 404.
Aplica a completion y search, las dos rutas que resuelven un bot. extract no usa botId.
Las instrucciones de un bot suelen ser fruto de mucho ajuste fino, así que las tratamos como contenido del proyecto: ninguna ruta devuelve el texto del prompt y ningún token llega al bot de otro proyecto.
Créditos y reembolso
- Cada generación (
completion,extract) descuenta 1 crédito de bot del proyecto. - Sin crédito, la ruta responde
402 ERR_NO_BOT_CREDITSantes de cualquier cobro. - Si la generación falla después del cobro, el crédito se reembolsa automáticamente y la ruta responde
502. searchyhealthno consumen nada.
El saldo es el mismo del bot de atención en WhatsApp — no hay cuota separada para la API. Un volumen alto de llamadas aquí deja al bot de WhatsApp sin crédito, y viceversa.
Códigos de error
| HTTP | error | Cuándo ocurre |
|---|---|---|
| 400 | mensaje de validación | payload inválido, prompt ausente, ni botId ni instructions, archivo que no es PDF |
| 400 | INVALID_JSON | el cuerpo no es JSON válido |
| 400 | FILE_TOO_LARGE | PDF por encima de 25 MB |
| 401 | ERR_API_TOKEN_NOT_PROVIDED / ERR_API_TOKEN_INVALID_FORMAT / ERR_API_TOKEN_INVALID / ERR_API_TOKEN_AUTHENTICATION_FAILED | header ausente o mal formado, token inválido o revocado |
| 402 | ERR_NO_BOT_CREDITS | proyecto sin créditos de bot (no se cobró nada) |
| 403 | mensaje de autorización | botId de un bot que no pertenece al proyecto del token |
| 404 | mensaje de bot | botId inexistente |
| 413 | PAYLOAD_TOO_LARGE | cuerpo JSON por encima de 10 MB |
| 429 | ERR_PUBLIC_AI_RATE_LIMIT | más de 60 solicitudes por minuto |
| 502 | mensaje en texto | falla al generar (crédito reembolsado); cuando la IA sabe el motivo, viene en el mensaje |
| 504 | GATEWAY_TIMEOUT | la generación superó el tiempo límite |
El 502 es el único que llega con mensaje libre en lugar de código — trátalo por el status, no por el texto, que puede cambiar. Los demás siguen el contrato de códigos de la plataforma, descrito en /es/server/traducoes.
Bots API × bot en WhatsApp
El mismo bot, dos caminos — lo que cambia es quién conduce la conversación:
Bots API (/api/v1/ai/*) | Bot en atención | |
|---|---|---|
| Quién llama | tu aplicación | el ticket, cuando entra en el sector |
| Conversación | cada llamada es independiente | Sendeasy mantiene el historial en el ticket |
| Uso típico | asistente y automatizaciones en tu producto | atención en WhatsApp |
Seguridad: trata el token como una contraseña. Nunca lo incrustes en JavaScript del navegador, repositorios públicos o logs — mantén las llamadas en tu servidor, con el token en una variable de entorno o un secret manager.