Перейти к содержимому

Публичный API

Публичный API Aelo — это API аналитики звонков (call analytics API, conversation intelligence API): вы отправляете записи звонков или чатов из ваших собственных систем — CRM, платформы телефонии, кастомного пайплайна — и забираете записи и их анализ (оценки, резюме, возражения) после завершения обработки. API привязан к организации: каждый запрос действует от имени организации, выдавшей ключ, и каждый ответ ограничен данными этой организации.

Доступен на тарифах Starter и выше. Организации на бесплатном тарифе не могут ни выпускать, ни использовать публичные API-ключи.

  1. Перейдите в Настройки → API ключи. Этот раздел видит только владелец организации (роль client) — администраторы, супервайзеры и агенты не могут управлять ключами.
  2. Выберите имя, отметьте один или оба скоупа (records:write, records:read) и при необходимости задайте дату истечения.
  3. Ключ в открытом виде (aelo_sk_…) показывается один раз, в момент создания. Сохраните его сами — Aelo хранит только его хеш и не сможет показать его повторно. Если ключ потерян, отзовите его и выпустите новый.

Организация может держать не более 10 активных ключей одновременно — отзывайте неиспользуемые, прежде чем выпускать новые.

Каждый запрос передаёт ключ как bearer-токен:

Authorization: Bearer aelo_sk_YOUR_KEY

Все эндпоинты находятся под https://api.aelo.cloud/api/public/v1.

Ключ открывает доступ только к тому, что разрешают его скоупы:

СкоупДаёт доступ к
records:writeСоздание записей (POST /records, POST /records/upload)
records:readСписок и чтение записей и анализов (три маршрута GET)

Запрос к эндпоинту, который не покрывают скоупы ключа, завершится ошибкой insufficient_scope, даже если сам ключ действителен.

ЛимитЗначение
Запросов на ключ200 / минуту
Размер multipart-загрузки (POST /records/upload)25 МБ
Размер файла по fileUrl (POST /records)100 МБ, либо 25 МБ, если источник не сообщает Content-Length
Таймаут загрузки по fileUrl30 секунд
Активных API-ключей на организацию10
Размер страницы списка записей50 по умолчанию, максимум 100 (limit выше 100 молча уменьшается, а не отклоняется)

Лимит для multipart ниже лимита для fileUrl, потому что multipart-тело нужно полностью буферизовать в памяти перед тем, как Aelo сможет его прочитать, а загрузка по fileUrl идёт потоком напрямую в хранилище — при условии, что источник сообщает свой Content-Length. Источник, который его не сообщает, потоком передать нельзя: он буферизуется в памяти, как multipart-тело, и ограничен теми же 25 МБ. Если ваш аудиофайл больше 25 МБ, загрузите его в хранилище, к которому у вас есть доступ, и передайте fileUrl вместо самого файла — оба варианта подробно разобраны в Загрузке звонков и чатов.

Метод и путьСкоупЧто делает
POST /recordsrecords:writeСоздаёт запись из fileUrl (звонки) или textContent (чаты)
POST /records/uploadrecords:writeСоздаёт запись звонка из загруженного аудиофайла (multipart)
GET /recordsrecords:readСписок записей вашей организации
GET /records/{recordId}records:readПолучить одну запись
GET /records/{recordId}/analysisrecords:readПолучить последний анализ записи

Оба эндпоинта загрузки, их поля запроса, поведение идемпотентности и возвращаемые предупреждения разобраны в Загрузке звонков и чатов. Остальные описаны ниже.

Возвращает записи от новых к старым. Архивные записи исключены — и никак не помечены: в ответе нет поля archived, поэтому архивная запись просто не появляется в списке.

Параметры запроса:

ПараметрПо умолчаниюПримечание
limit50Ограничен сверху значением 100
offset0
createdAfterISO-8601. Включительно (createdAt >= createdAfter)
createdBeforeISO-8601. Включительно (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 }
}

Возвращает одну запись в том же формате, что и список. Отвечает record_not_found (404), если id не существует или принадлежит другой организации — эти два случая неотличимы намеренно.

Возвращает последний анализ записи.

{
"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 — это каноническая оценка: то же число, что показывает ваш дашборд для этого звонка, а не самооценка модели. Каждая метрика равна null, если анализ не дал по ней значения (безоценочная категория звонка или пункт рубрики, отключённый в вашем проекте) — никогда не 0 вместо «не оценено». saleProbability применяется только к звонкам; для чатов оно всегда null.

Ответ намеренно уже, чем то, что Aelo хранит внутри: провайдер, модель, профиль промпта, число токенов и стоимость не входят в публичный контракт.

Две ситуации, выглядящие как 404, различаются кодом ошибки, потому что дальнейшее действие разное:

  • record_not_found — не существует сам id записи (или она не ваша). Исправьте id.
  • analysis_not_found — запись существует, но анализа у неё нет. details.analysisExpected говорит, появится ли он: true — продолжайте опрашивать, false — запись завершилась без анализа и никогда его не получит, опрос пора прекратить. Часть звонков заканчивается так по замыслу: слишком короткий для оценки звонок (details.reason: "short_call") или запись, упавшая в пайплайне ("record_failed"). details.recordStatus в любом случае сообщает текущий статус записи.

Любая ошибка возвращается в одном формате:

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

details необязательно и, если присутствует, описывает только ваш собственный запрос — никогда не внутреннее состояние. Нераспознанное поле в JSON-теле, форме или строке запроса отвечает invalid_request и называет каждое проблемное поле, а также подсказку didYouMean, если найдено близкое совпадение с реальным именем (например, projectIDprojectId).

КодСтатусЗначение
invalid_api_key401Отсутствует/некорректен заголовок Authorization, либо ключ неизвестен, отозван или истёк (все три случая выглядят одинаково — намеренно)
insufficient_scope403У ключа нет скоупа, требуемого этим эндпоинтом
tier_not_eligible403Организация на бесплатном тарифе
feature_disabled403Администратор вашей организации отключил публичный API. Ключ остаётся действительным, смена тарифа не поможет — попросите включить обратно
insufficient_balance402Включённые в тариф минуты за этот цикл израсходованы, а баланс кредитов пуст. Запись не создана — пополните баланс в «Настройки → Биллинг» и отправьте запрос заново
project_not_found404projectId не существует или принадлежит другой организации
project_not_accepting_records409Проект существует, но его статус paused или archived — администратор организации должен снова его активировать, прежде чем проект сможет принимать записи
record_not_found404Id записи не существует или принадлежит другой организации
analysis_not_found404Запись существует, но анализа нет — опрашивайте, пока details.analysisExpected = true, и прекратите, когда false
not_found404Такого маршрута под /api/public/v1 не существует
rate_limited429Более 200 запросов в минуту на этот ключ
payload_too_large413См. Лимиты выше
unsupported_media_type415Загруженный/скачанный контент — не аудио и не видео
invalid_request400Тело запроса, форма или строка запроса не прошли валидацию
fetch_failed400Не удалось скачать файл по fileUrl
resolution_unavailable503Aelo сейчас не смогла проверить адрес назначения fileUrl — временно, повторите (заголовок Retry-After)
service_unavailable503Хранилище анализов временно недоступно — временно, повторите (заголовок Retry-After)
internal_error500Непредвиденный сбой на стороне сервера

Ответ 503 всегда содержит заголовок Retry-After (в секундах) — не считайте его окончательным отказом, повторите запрос спустя это время.

Aelo — это API аналитики звонков?

Section titled “Aelo — это API аналитики звонков?”

Да. Публичный API Aelo — REST API аналитики звонков (call analytics API) на https://api.aelo.cloud/api/public/v1: Bearer-ключи организации (aelo_sk_…), скоупы records:write / records:read, 200 запросов в минуту на ключ. Доступен на тарифах Starter и выше.

Как загрузить записи звонков на анализ?

Section titled “Как загрузить записи звонков на анализ?”

Два способа: POST /records/upload принимает сам аудиофайл (multipart, до 25 МБ); POST /records принимает fileUrl, откуда Aelo скачает запись (до 100 МБ). Чаты отправляются через POST /records как textContent. Повторные отправки дедуплицируются по externalId: передайте свой идентификатор, и повторный запрос вернёт исходную запись, а не создаст вторую. Оба эндпоинта описаны в разделе Загрузка звонков и чатов.

Bitrix24 он обычно не нужен: нативная интеграция анализирует звонки вообще без кода. Публичный API — для всего остального: собственной телефонии, дата-пайплайна или CRM, с которой у Aelo пока нет интеграции.

  • Загрузка звонков и чатов — поля запроса, лимиты размера, идемпотентность и предупреждения для обоих эндпоинтов загрузки
  • Цены — публичный API включён в тарифы Starter и выше