Публичный API
Публичный API Aelo — это API аналитики звонков (call analytics API, conversation intelligence API): вы отправляете записи звонков или чатов из ваших собственных систем — CRM, платформы телефонии, кастомного пайплайна — и забираете записи и их анализ (оценки, резюме, возражения) после завершения обработки. API привязан к организации: каждый запрос действует от имени организации, выдавшей ключ, и каждый ответ ограничен данными этой организации.
Доступен на тарифах Starter и выше. Организации на бесплатном тарифе не могут ни выпускать, ни использовать публичные API-ключи.
Получение ключа
Section titled “Получение ключа”- Перейдите в Настройки → API ключи. Этот раздел видит только владелец
организации (роль
client) — администраторы, супервайзеры и агенты не могут управлять ключами. - Выберите имя, отметьте один или оба скоупа (
records:write,records:read) и при необходимости задайте дату истечения. - Ключ в открытом виде (
aelo_sk_…) показывается один раз, в момент создания. Сохраните его сами — Aelo хранит только его хеш и не сможет показать его повторно. Если ключ потерян, отзовите его и выпустите новый.
Организация может держать не более 10 активных ключей одновременно — отзывайте неиспользуемые, прежде чем выпускать новые.
Аутентификация
Section titled “Аутентификация”Каждый запрос передаёт ключ как 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, даже если сам ключ действителен.
Лимиты
Section titled “Лимиты”| Лимит | Значение |
|---|---|
| Запросов на ключ | 200 / минуту |
Размер multipart-загрузки (POST /records/upload) | 25 МБ |
Размер файла по fileUrl (POST /records) | 100 МБ, либо 25 МБ, если источник не сообщает Content-Length |
Таймаут загрузки по fileUrl | 30 секунд |
| Активных API-ключей на организацию | 10 |
| Размер страницы списка записей | 50 по умолчанию, максимум 100 (limit выше 100 молча уменьшается, а не отклоняется) |
Лимит для multipart ниже лимита для fileUrl, потому что multipart-тело нужно
полностью буферизовать в памяти перед тем, как Aelo сможет его прочитать, а
загрузка по fileUrl идёт потоком напрямую в хранилище — при условии, что
источник сообщает свой Content-Length. Источник, который его не сообщает,
потоком передать нельзя: он буферизуется в памяти, как multipart-тело, и
ограничен теми же 25 МБ. Если ваш аудиофайл
больше 25 МБ, загрузите его в хранилище, к которому у вас есть доступ, и
передайте fileUrl вместо самого файла — оба варианта подробно разобраны в
Загрузке звонков и чатов.
Эндпоинты
Section titled “Эндпоинты”| Метод и путь | Скоуп | Что делает |
|---|---|---|
POST /records | records:write | Создаёт запись из fileUrl (звонки) или textContent (чаты) |
POST /records/upload | records:write | Создаёт запись звонка из загруженного аудиофайла (multipart) |
GET /records | records:read | Список записей вашей организации |
GET /records/{recordId} | records:read | Получить одну запись |
GET /records/{recordId}/analysis | records:read | Получить последний анализ записи |
Оба эндпоинта загрузки, их поля запроса, поведение идемпотентности и возвращаемые предупреждения разобраны в Загрузке звонков и чатов. Остальные описаны ниже.
GET /records
Section titled “GET /records”Возвращает записи от новых к старым. Архивные записи исключены — и никак не
помечены: в ответе нет поля archived, поэтому архивная запись просто не
появляется в списке.
Параметры запроса:
| Параметр | По умолчанию | Примечание |
|---|---|---|
limit | 50 | Ограничен сверху значением 100 |
offset | 0 | |
createdAfter | — | ISO-8601. Включительно (createdAt >= createdAfter) |
createdBefore | — | ISO-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 }}GET /records/{recordId}
Section titled “GET /records/{recordId}”Возвращает одну запись в том же формате, что и список. Отвечает record_not_found
(404), если id не существует или принадлежит другой организации — эти два
случая неотличимы намеренно.
GET /records/{recordId}/analysis
Section titled “GET /records/{recordId}/analysis”Возвращает последний анализ записи.
{ "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в любом случае сообщает текущий статус записи.
Ошибки
Section titled “Ошибки”Любая ошибка возвращается в одном формате:
{ "error": { "code": "invalid_request", "message": "Human-readable description.", "details": { "field": "..." } }}details необязательно и, если присутствует, описывает только ваш собственный
запрос — никогда не внутреннее состояние. Нераспознанное поле в JSON-теле,
форме или строке запроса отвечает invalid_request и называет каждое
проблемное поле, а также подсказку didYouMean, если найдено близкое
совпадение с реальным именем (например, projectID → projectId).
| Код | Статус | Значение |
|---|---|---|
invalid_api_key | 401 | Отсутствует/некорректен заголовок Authorization, либо ключ неизвестен, отозван или истёк (все три случая выглядят одинаково — намеренно) |
insufficient_scope | 403 | У ключа нет скоупа, требуемого этим эндпоинтом |
tier_not_eligible | 403 | Организация на бесплатном тарифе |
feature_disabled | 403 | Администратор вашей организации отключил публичный API. Ключ остаётся действительным, смена тарифа не поможет — попросите включить обратно |
insufficient_balance | 402 | Включённые в тариф минуты за этот цикл израсходованы, а баланс кредитов пуст. Запись не создана — пополните баланс в «Настройки → Биллинг» и отправьте запрос заново |
project_not_found | 404 | projectId не существует или принадлежит другой организации |
project_not_accepting_records | 409 | Проект существует, но его статус paused или archived — администратор организации должен снова его активировать, прежде чем проект сможет принимать записи |
record_not_found | 404 | Id записи не существует или принадлежит другой организации |
analysis_not_found | 404 | Запись существует, но анализа нет — опрашивайте, пока details.analysisExpected = true, и прекратите, когда false |
not_found | 404 | Такого маршрута под /api/public/v1 не существует |
rate_limited | 429 | Более 200 запросов в минуту на этот ключ |
payload_too_large | 413 | См. Лимиты выше |
unsupported_media_type | 415 | Загруженный/скачанный контент — не аудио и не видео |
invalid_request | 400 | Тело запроса, форма или строка запроса не прошли валидацию |
fetch_failed | 400 | Не удалось скачать файл по fileUrl |
resolution_unavailable | 503 | Aelo сейчас не смогла проверить адрес назначения fileUrl — временно, повторите (заголовок Retry-After) |
service_unavailable | 503 | Хранилище анализов временно недоступно — временно, повторите (заголовок Retry-After) |
internal_error | 500 | Непредвиденный сбой на стороне сервера |
Ответ 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: передайте свой идентификатор, и
повторный запрос вернёт исходную запись, а не создаст вторую. Оба эндпоинта
описаны в разделе Загрузка звонков и чатов.
Работает ли API с Bitrix24?
Section titled “Работает ли API с Bitrix24?”Bitrix24 он обычно не нужен: нативная интеграция анализирует звонки вообще без кода. Публичный API — для всего остального: собственной телефонии, дата-пайплайна или CRM, с которой у Aelo пока нет интеграции.
Смотрите также
Section titled “Смотрите также”- Загрузка звонков и чатов — поля запроса, лимиты размера, идемпотентность и предупреждения для обоих эндпоинтов загрузки
- Цены — публичный API включён в тарифы Starter и выше