Ir al contenido

API pública

La API pública de Aelo es una API de analítica de llamadas (call analytics API, conversation intelligence API): envías grabaciones de llamadas o transcripciones de chat desde tus propios sistemas — un CRM, una plataforma de telefonía, un pipeline propio — y recuperas los registros y su análisis (puntuaciones, resúmenes, objeciones) una vez terminado el procesamiento. Está delimitada por organización: cada solicitud actúa en nombre de la organización que emitió la clave, y cada respuesta se limita a los datos de esa organización.

Disponible desde el plan Starter en adelante. Las organizaciones en el plan gratuito no pueden emitir ni usar claves de API pública.

  1. Ve a Configuración → Claves API. Solo el propietario de la organización (el rol client) puede ver esta sección — administradores, supervisores y agentes no pueden gestionar claves.
  2. Elige un nombre, marca uno o ambos scopes (records:write, records:read) y, si quieres, define una fecha de expiración.
  3. La clave en texto plano (aelo_sk_…) se muestra una única vez, al crearla. Guárdala tú mismo — Aelo solo conserva su hash y no puede volver a mostrártela. Si la pierdes, revócala y emite una nueva.

Una organización puede tener como máximo 10 claves activas a la vez; revoca las que no uses antes de emitir nuevas.

Cada solicitud lleva la clave como token bearer:

Authorization: Bearer aelo_sk_YOUR_KEY

Todos los endpoints están bajo https://api.aelo.cloud/api/public/v1.

Una clave solo desbloquea lo que permiten sus scopes:

ScopePermite
records:writeCrear registros (POST /records, POST /records/upload)
records:readListar y leer registros y análisis (las tres rutas GET)

Una solicitud a un endpoint que los scopes de la clave no cubren falla con insufficient_scope, incluso si la clave en sí es válida.

LímiteValor
Solicitudes por clave200 / minuto
Tamaño de subida multipart (POST /records/upload)25 MB
Tamaño de descarga por fileUrl (POST /records)100 MB, o 25 MB si el origen no envía Content-Length
Tiempo de espera de descarga por fileUrl30 segundos
Claves de API activas por organización10
Tamaño de página en el listado de registros50 por defecto, tope de 100 (limit por encima de 100 se reduce en silencio, no se rechaza)

El límite multipart es más bajo que el de fileUrl porque un cuerpo multipart debe almacenarse por completo en memoria antes de que Aelo pueda leerlo, mientras que una descarga por fileUrl se transmite directamente al almacenamiento — siempre que el origen declare su Content-Length. Un origen que no lo declara no puede transmitirse y se retiene en memoria como un cuerpo multipart, bajo el mismo tope de 25 MB. Si tu audio pesa más de 25 MB, súbelo a un almacenamiento al que tengas acceso y envía fileUrl en lugar del archivo — ambas vías se explican en detalle en Subir llamadas y chats.

Método y rutaScopeQué hace
POST /recordsrecords:writeCrea un registro a partir de fileUrl (llamadas) o textContent (chats)
POST /records/uploadrecords:writeCrea un registro de llamada a partir de un archivo de audio subido (multipart)
GET /recordsrecords:readLista los registros de tu organización
GET /records/{recordId}records:readObtiene un registro
GET /records/{recordId}/analysisrecords:readObtiene el último análisis de un registro

Los dos endpoints de subida, sus campos de solicitud, el comportamiento de idempotencia y las advertencias que pueden devolver se explican en Subir llamadas y chats. El resto se documenta a continuación.

Lista los registros de más reciente a más antiguo. Los registros archivados quedan excluidos — y no se marcan como tales: la respuesta no tiene campo archived, así que un registro archivado simplemente no aparece.

Parámetros de consulta:

ParámetroPor defectoNota
limit50Con tope de 100
offset0
createdAfterISO-8601. Inclusivo (createdAt >= createdAfter)
createdBeforeISO-8601. Inclusivo (createdAt <= createdBefore)
{
"data": [
{
"id": "rec_...",
"projectId": "your-project-id",
"type": "call",
"status": "completed",
"externalId": "crm-call-12345",
"createdAt": "2026-07-01T10:00:00.000Z",
"occurredAt": "2026-07-01T09:58:12.000Z",
"durationSeconds": 184,
"agentId": "42",
"agentName": "Ivan Petrov",
"callDirection": "outbound"
}
],
"pagination": { "limit": 50, "offset": 0, "total": 1 }
}

Devuelve un registro con el mismo formato que el listado. Responde record_not_found (404) si el id no existe o pertenece a otra organización — ambos casos son indistinguibles a propósito.

Devuelve el último análisis de un registro.

{
"recordId": "rec_...",
"analysisId": "an_...",
"createdAt": "2026-07-01T10:04:30.000Z",
"summary": "Customer asked about pricing tiers; agent...",
"qualityScore": 78,
"metrics": {
"greetingScore": 90,
"needsScore": 70,
"clarityScore": 80,
"objectionScore": 65,
"closingScore": 75,
"politenessScore": 95,
"saleProbability": 62
}
}

qualityScore es la puntuación canónica: el mismo número que muestra tu panel para esta llamada, no una cifra autoinformada por el modelo. Cada métrica es null cuando el análisis no produjo un valor para ella (una categoría de llamada sin puntuación, o un ítem del rubro que tu proyecto desactivó) — nunca 0 en lugar de “sin puntuar”. saleProbability solo aplica a llamadas; es null en los chats.

La respuesta es deliberadamente más limitada que lo que Aelo almacena internamente: el proveedor, el modelo, el perfil del prompt, el recuento de tokens y el costo no forman parte del contrato público.

Dos situaciones con forma de 404 se distinguen por su código de error, porque tu siguiente paso es distinto:

  • record_not_found — el id del registro no existe (o no es tuyo). Corrige el id.
  • analysis_not_found — el registro existe pero no tiene análisis. details.analysisExpected indica si aún llegará: true significa seguir consultando, false significa que el registro terminó sin análisis y nunca lo tendrá — detente. Algunas llamadas terminan así por diseño: una llamada demasiado corta para evaluar (details.reason: "short_call") o un registro que falló en el pipeline ("record_failed"). details.recordStatus indica el estado actual del registro en cualquier caso.

Cualquier error se devuelve en el mismo formato:

{
"error": {
"code": "invalid_request",
"message": "Human-readable description.",
"details": { "field": "..." }
}
}

details es opcional y, cuando está presente, describe únicamente tu propia solicitud — nunca el estado interno. Un campo no reconocido en un cuerpo JSON, un formulario o una cadena de consulta responde con invalid_request y nombra cada campo problemático, además de una sugerencia didYouMean cuando hay una coincidencia cercana con un nombre real (por ejemplo, projectIDprojectId).

CódigoEstadoSignificado
invalid_api_key401Falta el encabezado Authorization o es incorrecto, o la clave es desconocida, revocada o expiró (los tres casos se ven idénticos, a propósito)
insufficient_scope403La clave no tiene el scope que requiere este endpoint
tier_not_eligible403La organización está en el plan gratuito
feature_disabled403El administrador de tu organización desactivó la API pública. La clave sigue siendo válida y cambiar de plan no ayuda — pídele que la reactive
insufficient_balance402Los minutos incluidos del plan para este ciclo se agotaron y el saldo de créditos está vacío. No se guardó nada — añade créditos en «Configuración → Facturación» y vuelve a enviar la solicitud
project_not_found404projectId no existe o pertenece a otra organización
project_not_accepting_records409El proyecto existe pero su estado es paused o archived — el administrador de tu organización debe reactivarlo antes de que pueda volver a aceptar registros
record_not_found404El id del registro no existe o pertenece a otra organización
analysis_not_found404El registro existe pero no tiene análisis — consulta mientras details.analysisExpected sea true, y detente cuando sea false
not_found404No existe esa ruta bajo /api/public/v1
rate_limited429Más de 200 solicitudes por minuto con esta clave
payload_too_large413Ver Límites arriba
unsupported_media_type415El contenido subido/descargado no es audio ni video
invalid_request400El cuerpo, el formulario o la cadena de consulta no pasaron la validación
fetch_failed400No se pudo descargar el archivo en fileUrl
resolution_unavailable503Aelo no pudo verificar el destino de fileUrl en este momento — transitorio, reintenta (encabezado Retry-After)
service_unavailable503El almacén de análisis no está disponible temporalmente — transitorio, reintenta (encabezado Retry-After)
internal_error500Fallo inesperado del lado del servidor

Una respuesta 503 siempre incluye un encabezado Retry-After (en segundos); espera y reintenta en lugar de tratarlo como un fallo definitivo.

¿Aelo es una API de analítica de llamadas?

Section titled “¿Aelo es una API de analítica de llamadas?”

Sí. La API pública de Aelo es una API REST de analítica de llamadas (call analytics API) en https://api.aelo.cloud/api/public/v1: claves Bearer por organización (aelo_sk_…), scopes records:write / records:read, 200 solicitudes por minuto por clave. Disponible desde el plan Starter en adelante.

¿Cómo subo grabaciones de llamadas para analizarlas?

Section titled “¿Cómo subo grabaciones de llamadas para analizarlas?”

Dos vías: POST /records/upload acepta el archivo de audio en sí (multipart, hasta 25 MB); POST /records acepta un fileUrl del que Aelo descarga la grabación (hasta 100 MB). Los chats se envían por POST /records como textContent. Los reenvíos se deduplican por externalId: envía tu propio identificador y un reintento devuelve el registro original en lugar de crear otro. Ambos endpoints se describen en Subir llamadas y chats.

Normalmente Bitrix24 no la necesita: la integración nativa analiza las llamadas sin escribir código. La API pública es para todo lo demás: tu propia telefonía, un pipeline de datos o un CRM con el que Aelo aún no se integra.

  • Subir llamadas y chats — campos de solicitud, límites de tamaño, idempotencia y advertencias de los dos endpoints de subida
  • Precios — la API pública está incluida desde el plan Starter en adelante