# Загрузить по ссылке Source: https://docs.aigenda.tech/api-reference/audio/by-url POST https://api.aigenda.tech/api/spaces/{space_id}/audio/by_url/ AiGenda сама скачает файл по прямой ссылке. Отвечает сразу, файл скачивается в фоне. ## Параметры пути Идентификатор пространства. ## Тело запроса Прямая ссылка на файл, до 255 символов, без авторизации. Название до 255 символов, заканчивается расширением файла. MIME-тип файла. ## Ответ Успешный ответ: `201`. После ответа дождитесь `is_uploaded: true` в [Статус загрузки](/api-reference/audio/info), затем [запустите обработку](/api-reference/processing/classify). Подробнее: [Загрузка по ссылке](/upload/url). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/spaces/1024/audio/by_url/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "url": "https://records.example.com/calls/client-call.mp3", "title": "Звонок с клиентом 17.10.mp3", "content_type": "audio/mpeg" }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/spaces/1024/audio/by_url/", headers={"Authorization": "Bearer "}, json={ "url": "https://records.example.com/calls/client-call.mp3", "title": "Звонок с клиентом 17.10.mp3", "content_type": "audio/mpeg", }, timeout=30, ) response.raise_for_status() print(response.status_code) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/by_url/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "url": "https://records.example.com/calls/client-call.mp3", "title": "Звонок с клиентом 17.10.mp3", "content_type": "audio/mpeg" }), }); console.log(response.status); ``` # Загрузить с YouTube Source: https://docs.aigenda.tech/api-reference/audio/by-youtube POST https://api.aigenda.tech/api/spaces/{space_id}/audio/by_youtube/ AiGenda скачает звуковую дорожку видео с YouTube. Отвечает сразу, видео скачивается в фоне. ## Параметры пути Идентификатор пространства. ## Тело запроса Ссылка на видео YouTube, до 2048 символов. ## Ответ Успешный ответ: `201`. После ответа дождитесь `is_uploaded: true` в [Статус загрузки](/api-reference/audio/info), затем [запустите обработку](/api-reference/processing/classify). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/spaces/1024/audio/by_youtube/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "url": "https://www.youtube.com/watch?v=VIDEO_ID" }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/spaces/1024/audio/by_youtube/", headers={"Authorization": "Bearer "}, json={ "url": "https://www.youtube.com/watch?v=VIDEO_ID", }, timeout=30, ) response.raise_for_status() print(response.status_code) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/by_youtube/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "url": "https://www.youtube.com/watch?v=VIDEO_ID" }), }); console.log(response.status); ``` # Завершить загрузку Source: https://docs.aigenda.tech/api-reference/audio/complete-upload POST https://api.aigenda.tech/api/spaces/{space_id}/audio/{audio_id}/complete_upload/ Сообщает AiGenda, что все части файла загружены в хранилище. ## Параметры пути Идентификатор пространства. Идентификатор записи. ## Тело запроса Части файла по порядку загрузки. Номер части, с единицы. Заголовок `ETag` из ответа хранилища, вместе с двойными кавычками. ## Ответ Успешный ответ: `200` с пустым телом. После ответа дождитесь `is_uploaded: true` в [Статус загрузки](/api-reference/audio/info). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/spaces/1024/audio/51234/complete_upload/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "PartNumber": 1, "ETag": "\"9b2cf535f27731c974343645a3985328\"" } ] }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/spaces/1024/audio/51234/complete_upload/", headers={"Authorization": "Bearer "}, json={ "parts": [ { "PartNumber": 1, "ETag": "\"9b2cf535f27731c974343645a3985328\"", }, ], }, timeout=30, ) response.raise_for_status() print(response.status_code) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/51234/complete_upload/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "parts": [ { "PartNumber": 1, "ETag": "\"9b2cf535f27731c974343645a3985328\"" } ] }), }); console.log(response.status); ``` ```text 200 theme={null} Пустое тело ответа ``` # Создать запись Source: https://docs.aigenda.tech/api-reference/audio/create POST https://api.aigenda.tech/api/spaces/{space_id}/audio/ Создаёт запись и выдаёт ссылки для загрузки файла в хранилище. Первый шаг загрузки файла. ## Параметры пути Идентификатор пространства. ## Тело запроса Название до 255 символов. **Заканчивается расширением файла**: `.mp3`, `.m4a`, `.wav`, `.ogg`, `.webm`, `.mp4`. Точный размер файла в байтах. MIME-тип файла. ## Ответ Идентификатор записи (`audio_id`). Ссылки для `PUT` частей файла, по одной на часть. Живут 5 часов. `false` до завершения загрузки. Каждый вызов создаёт новую запись. Не повторяйте его вслепую, если ответ потерялся: см. [Надёжная интеграция](/reference/best-practices). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/spaces/1024/audio/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "title": "Планёрка отдела продаж.mp3", "size": 18874368, "content_type": "audio/mpeg" }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/spaces/1024/audio/", headers={"Authorization": "Bearer "}, json={ "title": "Планёрка отдела продаж.mp3", "size": 18874368, "content_type": "audio/mpeg", }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "title": "Планёрка отдела продаж.mp3", "size": 18874368, "content_type": "audio/mpeg" }), }); const data = await response.json(); console.log(data); ``` ```json 201 theme={null} { "id": 51234, "title": "Планёрка отдела продаж.mp3", "created_at": "2026-10-17T09:30:00Z", "size": 18874368, "content_type": "audio/mpeg", "space_id": 1024, "is_active": true, "is_favorite": false, "is_uploaded": false, "was_classified": false, "result_is_ready": false, "url": [ "https://storage.yandexcloud.net/aigenda/3f6c1e0a.mp3?partNumber=1&uploadId=…&X-Amz-Signature=…" ], "duration": null } ``` ```json 400 theme={null} { "title": [ "This field is required." ] } ``` # Удалить записи Source: https://docs.aigenda.tech/api-reference/audio/delete POST https://api.aigenda.tech/api/spaces/{space_id}/audio/delete_list/ Перемещает записи в корзину пространства. ## Параметры пути Идентификатор пространства. ## Тело запроса Идентификаторы записей. ## Ответ Успешный ответ: `200` с пустым телом. Записи получают `is_active: false` и видны в [корзине](/api-reference/audio/trash). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/spaces/1024/audio/delete_list/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "audio_ids": [ 51234, 51235 ] }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/spaces/1024/audio/delete_list/", headers={"Authorization": "Bearer "}, json={ "audio_ids": [51234, 51235], }, timeout=30, ) response.raise_for_status() print(response.status_code) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/delete_list/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "audio_ids": [ 51234, 51235 ] }), }); console.log(response.status); ``` ```text 200 theme={null} Пустое тело ответа ``` # Статус загрузки Source: https://docs.aigenda.tech/api-reference/audio/info GET https://api.aigenda.tech/api/spaces/{space_id}/audio/{audio_id}/info/ Запись и её флаги: загружена ли, запускали ли обработку, готов ли результат. ## Параметры пути Идентификатор пространства. Идентификатор записи. ## Ответ Идентификатор записи (`audio_id`). Название записи с расширением файла. Временная ссылка на исходный файл в хранилище. Когда создана запись, ISO 8601 UTC. Длительность в секундах. `null`, пока AiGenda не прочитала файл. Размер файла в байтах. MIME-тип файла. Пространство, в котором лежит запись. `false`, если запись в корзине. Файл получен целиком. Обработку запускают только после `true`. Обработку запускали. Результат готов. ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/spaces/1024/audio/51234/info/" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/1024/audio/51234/info/", headers={"Authorization": "Bearer "}, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/51234/info/", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "id": 51234, "title": "Планёрка отдела продаж.mp3", "url": "https://storage.yandexcloud.net/aigenda/3f6c1e0a.mp3?X-Amz-Signature=…", "created_at": "2026-10-17T09:30:00Z", "duration": 1837, "size": 18874368, "content_type": "audio/mpeg", "space_id": 1024, "is_active": true, "is_favorite": false, "is_uploaded": true, "was_classified": true, "result_is_ready": true } ``` ```html 404 theme={null} … Not Found … ``` # Список записей Source: https://docs.aigenda.tech/api-reference/audio/list GET https://api.aigenda.tech/api/spaces/{space_id}/audio/ Записи пространства с поиском и сортировкой. ## Параметры пути Идентификатор пространства. ## Параметры запроса Поиск по названию. Сортировка. `-created_at`: новые сверху. Сколько элементов на странице. Сколько элементов пропустить. ## Ответ Всего записей по запросу. Записи, поля как в [Статус загрузки](/api-reference/audio/info). ```bash cURL theme={null} curl -G "https://api.aigenda.tech/api/spaces/1024/audio/" \ --data-urlencode "search=Планёрка" \ --data-urlencode "ordering=-created_at" \ --data-urlencode "limit=20" \ --data-urlencode "offset=0" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/1024/audio/", headers={"Authorization": "Bearer "}, params={ "search": "Планёрка", "ordering": "-created_at", "limit": 20, "offset": 0, }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const params = new URLSearchParams({ "search": "Планёрка", "ordering": "-created_at", "limit": "20", "offset": "0" }); const response = await fetch(`https://api.aigenda.tech/api/spaces/1024/audio/?${params}`, { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "count": 1, "next": null, "previous": null, "results": [ { "id": 51234, "title": "Планёрка отдела продаж.mp3", "url": "https://storage.yandexcloud.net/aigenda/3f6c1e0a.mp3?X-Amz-Signature=…", "created_at": "2026-10-17T09:30:00Z", "duration": 1837, "size": 18874368, "content_type": "audio/mpeg", "space_id": 1024, "is_active": true, "is_favorite": false, "is_uploaded": true, "was_classified": true, "result_is_ready": true } ] } ``` # Корзина Source: https://docs.aigenda.tech/api-reference/audio/trash GET https://api.aigenda.tech/api/spaces/{space_id}/audio/trash/ Записи пространства, перемещённые в корзину. ## Параметры пути Идентификатор пространства. ## Параметры запроса Сколько элементов на странице. Сколько элементов пропустить. ## Ответ Всего записей в корзине. Записи, поля как в [Статус загрузки](/api-reference/audio/info). ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/spaces/1024/audio/trash/?limit=20&offset=0" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/1024/audio/trash/", headers={"Authorization": "Bearer "}, params={ "limit": 20, "offset": 0, }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/trash/?limit=20&offset=0", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "count": 1, "next": null, "previous": null, "results": [ { "id": 51234, "title": "Планёрка отдела продаж.mp3", "url": "https://storage.yandexcloud.net/aigenda/3f6c1e0a.mp3?X-Amz-Signature=…", "created_at": "2026-10-17T09:30:00Z", "duration": 1837, "size": 18874368, "content_type": "audio/mpeg", "space_id": 1024, "is_active": false, "is_favorite": false, "is_uploaded": true, "was_classified": true, "result_is_ready": true } ] } ``` # Обновить токен Source: https://docs.aigenda.tech/api-reference/auth/refresh POST https://api.aigenda.tech/api/token/refresh/ Выдаёт новый access по refresh. Новый refresh не выдаётся. ## Тело запроса Токен `refresh` из ответа на вход. Действует 1 сутки. ## Ответ Новый токен доступа. Через сутки после входа `refresh` истекает. Тогда получите новую пару через [Получить токен](/api-reference/auth/token). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/token/refresh/" \ -H "Content-Type: application/json" \ -d '{ "refresh": "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCJ9.sig" }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/token/refresh/", json={ "refresh": "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCJ9.sig", }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/token/refresh/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "refresh": "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCJ9.sig" }), }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "access": "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIn0.sig" } ``` ```json 401 theme={null} { "detail": "Given token not valid for any token type", "code": "token_not_valid" } ``` # Получить токен Source: https://docs.aigenda.tech/api-reference/auth/token POST https://api.aigenda.tech/api/token/ Выдаёт пару JWT по почте и паролю аккаунта AiGenda. ## Тело запроса Почта аккаунта. Поле называется `username`, но в него кладётся почта. Пароль аккаунта. ## Ответ Токен для заголовка `Authorization: Bearer`. Живёт 30 дней. Токен для обновления `access`. Живёт 1 сутки. Подробнее о сроках и обновлении: [Авторизация](/authentication). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/token/" \ -H "Content-Type: application/json" \ -d '{ "username": "you@example.com", "password": "ваш-пароль" }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/token/", json={ "username": "you@example.com", "password": "ваш-пароль", }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/token/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "username": "you@example.com", "password": "ваш-пароль" }), }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "refresh": "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCJ9.sig", "access": "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIn0.sig" } ``` ```json 401 theme={null} { "detail": "No active account found with the given credentials" } ``` # Справочник API Source: https://docs.aigenda.tech/api-reference/introduction Все запросы API AiGenda с параметрами, ответами и примерами. Каждая страница справочника описывает один запрос: параметры, поля ответа, примеры на cURL, Python и JavaScript. Кнопка **Попробовать** отправляет запрос прямо со страницы. ## Основное | | | | - | - | | Базовый адрес | `https://api.aigenda.tech` | | Формат тела | `application/json`, UTF-8 | | Авторизация | `Authorization: Bearer `, кроме [получения](/api-reference/auth/token) и [обновления](/api-reference/auth/refresh) токена | | Идентификаторы | целые числа: `space_id`, `audio_id` | | Даты | ISO 8601, UTC: `2026-10-17T09:30:00Z` | | Длительность и минуты тарифа | секунды | | Списки | `limit` и `offset`, ответ `{count, next, previous, results}` | ## Как попробовать запрос 1. Получите токен на странице [Получить токен](/api-reference/auth/token): нажмите **Попробовать** и введите почту и пароль. 2. Скопируйте `access` из ответа. 3. На странице нужного запроса вставьте токен в поле авторизации и заполните параметры. Запросы из песочницы выполняются на рабочем API с вашим аккаунтом. Запуск обработки списывает минуты, а созданные записи появляются в вашем пространстве. ## Карта запросов | Задача | Запросы | | - | - | | Войти | [Получить токен](/api-reference/auth/token), [Обновить токен](/api-reference/auth/refresh) | | Выбрать пространство | [Список пространств](/api-reference/spaces/list), [Пространство](/api-reference/spaces/get), [Права](/api-reference/spaces/rights) | | Загрузить файл | [Создать запись](/api-reference/audio/create) → `PUT` в хранилище → [Завершить загрузку](/api-reference/audio/complete-upload) → [Статус загрузки](/api-reference/audio/info) | | Загрузить по ссылке | [По ссылке](/api-reference/audio/by-url), [С YouTube](/api-reference/audio/by-youtube) | | Записать встречу | [Отправить бота](/api-reference/meetings/create) | | Обработать | [Запустить обработку](/api-reference/processing/classify) или [Только расшифровка](/api-reference/processing/classify-transcription) → [Результат](/api-reference/processing/result) | | Навести порядок | [Список записей](/api-reference/audio/list), [Удалить](/api-reference/audio/delete), [Корзина](/api-reference/audio/trash) | # Отправить бота на встречу Source: https://docs.aigenda.tech/api-reference/meetings/create POST https://api.aigenda.tech/api/space/{space_id}/meeting/ Бот AiGenda подключится к встрече в Zoom, Google Meet или Яндекс Телемосте и запишет её в пространство. ## Параметры пути Идентификатор пространства. ## Тело запроса Ссылка-приглашение на встречу, до 255 символов. ## Ответ Успешный ответ: `201`. В адресе `space` в единственном числе. Что делать после встречи: [Бот на встречу](/upload/meeting-bot). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/space/1024/meeting/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "link": "https://telemost.yandex.ru/j/12345678901234" }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/space/1024/meeting/", headers={"Authorization": "Bearer "}, json={ "link": "https://telemost.yandex.ru/j/12345678901234", }, timeout=30, ) response.raise_for_status() print(response.status_code) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/space/1024/meeting/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "link": "https://telemost.yandex.ru/j/12345678901234" }), }); console.log(response.status); ``` # Запустить обработку Source: https://docs.aigenda.tech/api-reference/processing/classify POST https://api.aigenda.tech/api/audio/classify/ Запускает обработку записи: протокол, расшифровка, спикеры. Списывает минуты по длительности записи. ## Тело запроса Идентификатор записи с `is_uploaded: true`. ## Ответ Идентификатор задачи обработки. Хранить не обязательно. Статус проверяйте по [Результат обработки](/api-reference/processing/result). ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/audio/classify/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "audio_id": 51234 }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/audio/classify/", headers={"Authorization": "Bearer "}, json={ "audio_id": 51234, }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/audio/classify/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "audio_id": 51234 }), }); const data = await response.json(); console.log(data); ``` ```json 201 theme={null} { "request_id": "c0a8012e-7f3d-4b8e-9a51-2d6f0e4b9c17" } ``` # Только расшифровка Source: https://docs.aigenda.tech/api-reference/processing/classify-transcription POST https://api.aigenda.tech/api/audio/classify_only_transcription/ Запускает обработку без протокола: только расшифровка по репликам. ## Тело запроса Идентификатор записи с `is_uploaded: true`. ## Ответ Идентификатор задачи обработки. ```bash cURL theme={null} curl -X POST "https://api.aigenda.tech/api/audio/classify_only_transcription/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "audio_id": 51234 }' ``` ```python Python theme={null} import requests response = requests.post( "https://api.aigenda.tech/api/audio/classify_only_transcription/", headers={"Authorization": "Bearer "}, json={ "audio_id": 51234, }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/audio/classify_only_transcription/", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ "audio_id": 51234 }), }); const data = await response.json(); console.log(data); ``` ```json 201 theme={null} { "request_id": "c0a8012e-7f3d-4b8e-9a51-2d6f0e4b9c17" } ``` # Результат обработки Source: https://docs.aigenda.tech/api-reference/processing/result GET https://api.aigenda.tech/api/spaces/{space_id}/audio/{audio_id}/result/ Статус и результат обработки. Опрашивайте раз в 10–15 секунд до classified: true. ## Параметры пути Идентификатор пространства. Идентификатор записи. ## Ответ `true`, когда обработка закончена. `true`, если обработка прошла успешно. Протокол, реплики и спикеры. `null`, пока обработка идёт. Протокол в Markdown. Расшифровка по репликам. Идентификаторы спикеров и метки вида `SPEAKER_00`. Кто и когда говорил. Язык записи. Идентификатор записи. Название записи. Длительность в секундах. Открыт ли публичный доступ. | Ответ | Что значит | | - | - | | `404` | Обработку не запускали | | `200`, `classified: false` | Обработка идёт | | `200`, `classified: true` | Готово | | `500` дольше 3 минут | Обработка упала, минуты вернутся | Подробнее: [Статусы и ожидание](/processing/status) и [Структура результата](/processing/result). В примере ответа `result` сокращён. ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/spaces/1024/audio/51234/result/" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/1024/audio/51234/result/", headers={"Authorization": "Bearer "}, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/audio/51234/result/", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "classified": true, "success": true, "audio_id": 51234, "title": "Планёрка отдела продаж.mp3", "duration": 1837, "is_shared": false, "result": { "language": "ru", "protocol": "## Итоги встречи\n\nОбсудили план продаж на ноябрь…" } } ``` ```html 404 theme={null} … Not Found … ``` ```html 500 theme={null} … Server Error (500) … ``` # Пространство Source: https://docs.aigenda.tech/api-reference/spaces/get GET https://api.aigenda.tech/api/spaces/{space_id}/ Одно пространство со свежим остатком минут. Запрашивайте перед каждой загрузкой. ## Параметры пути Идентификатор пространства. ## Ответ Идентификатор пространства. Название. Тариф. Секунд на тарифе за период. Потрачено секунд. Осталось секунд. Подписка активна. Конец периода, ISO 8601. ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/spaces/1024/" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/1024/", headers={"Authorization": "Bearer "}, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "id": 1024, "name": "Личное пространство", "description": "Main space", "subscribe": { "offer": { "name": "PRO", "audio_limit": 72000 }, "usage_count": 5400, "available_usage_count": 66600, "is_active": true, "end_date": "2026-11-17T00:00:00Z" } } ``` ```json 403 theme={null} { "detail": "You do not have permission to perform this action." } ``` # Список пространств Source: https://docs.aigenda.tech/api-reference/spaces/list GET https://api.aigenda.tech/api/spaces/ Пространства, в которых вы состоите, с тарифом и остатком минут. Личное отмечено is_main_space: true. ## Параметры запроса Сколько элементов на странице. Сколько элементов пропустить. ## Ответ Всего пространств. Личное пространство аккаунта. `space_id` для остальных запросов. Название. Тариф и минуты, значения в секундах. См. [Пространства и минуты](/spaces). Ссылки `next` и `previous` приходят со схемой `http://`. Собирайте следующую страницу сами через `limit` и `offset`. ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/spaces/?limit=50&offset=0" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/", headers={"Authorization": "Bearer "}, params={ "limit": 50, "offset": 0, }, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/?limit=50&offset=0", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "count": 1, "next": null, "previous": null, "results": [ { "is_main_space": true, "space": { "id": 1024, "name": "Личное пространство", "description": "Main space", "subscribe": { "offer": { "name": "PRO", "audio_limit": 72000 }, "usage_count": 5400, "available_usage_count": 66600, "is_active": true, "end_date": "2026-11-17T00:00:00Z" } } } ] } ``` # Права в пространстве Source: https://docs.aigenda.tech/api-reference/spaces/rights GET https://api.aigenda.tech/api/spaces/{space_id}/my_rights/ Что вам можно в этом пространстве. Для загрузки нужно write_access: true. ## Параметры пути Идентификатор пространства. ## Ответ Можно загружать записи. Можно открывать публичный доступ к результатам. Можно приглашать участников. Можно добавлять пользователей. Можно создавать группы. Видны только свои записи. ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/spaces/1024/my_rights/" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/spaces/1024/my_rights/", headers={"Authorization": "Bearer "}, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/spaces/1024/my_rights/", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "write_access": true, "invite_access": true, "share_access": true, "create_another_group": true, "add_user": true, "view_only_own_records": false } ``` ```json 403 theme={null} { "detail": "You do not have permission to perform this action." } ``` # Текущий пользователь Source: https://docs.aigenda.tech/api-reference/users/me GET https://api.aigenda.tech/api/users/me/ Возвращает аккаунт, которому принадлежит токен. Удобно, чтобы проверить токен. ## Ответ Идентификатор пользователя. Логин. Почта. ```bash cURL theme={null} curl -X GET "https://api.aigenda.tech/api/users/me/" \ -H "Authorization: Bearer " ``` ```python Python theme={null} import requests response = requests.get( "https://api.aigenda.tech/api/users/me/", headers={"Authorization": "Bearer "}, timeout=30, ) response.raise_for_status() print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.aigenda.tech/api/users/me/", { method: "GET", headers: { Authorization: "Bearer " }, }); const data = await response.json(); console.log(data); ``` ```json 200 theme={null} { "id": 777, "username": "you@example.com", "email": "you@example.com" } ``` ```json 401 theme={null} { "detail": "Given token not valid for any token type", "code": "token_not_valid" } ``` # Авторизация Source: https://docs.aigenda.tech/authentication Как получить токен, сколько он живёт и что делать, когда он истёк. API принимает JWT. Вы получаете пару токенов по почте и паролю аккаунта AiGenda и передаёте `access` в каждом запросе. ## Получить токен ```bash theme={null} curl -X POST https://api.aigenda.tech/api/token/ \ -H "Content-Type: application/json" \ -d '{"username": "you@example.com", "password": "ваш-пароль"}' ``` ```json Ответ 200 theme={null} { "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCJ9.signature", "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIn0.signature" } ``` Поле называется `username`, но в него кладётся почта. ## Передать токен Добавьте заголовок ко всем запросам, кроме получения и обновления токена: ```http theme={null} Authorization: Bearer ``` ## Сколько живут токены | Токен | Срок | Как обновить | | - | - | - | | `access` | 30 дней | новый вход по почте и паролю или `refresh` | | `refresh` | 1 сутки | только новым входом | [Обновление](/api-reference/auth/refresh) по `refresh` возвращает новый `access`, но новый `refresh` не выдаёт. Через сутки после входа обновиться уже нельзя, поэтому проще всего так: 1. Храните `access` и время его истечения. Оно лежит в поле `exp` внутри токена (Unix-время в секундах). 2. Когда до `exp` осталось меньше суток или API ответил `401`, получите новую пару по почте и паролю. 3. Повторите исходный запрос один раз с новым токеном. ```python Срок действия токена theme={null} import base64, json def token_expires_at(access: str) -> int: payload = access.split(".")[1] payload += "=" * (-len(payload) % 4) return json.loads(base64.urlsafe_b64decode(payload))["exp"] ``` ## Ошибки | Ответ | Тело | Что делать | | - | - | - | | `401` при входе | `{"detail": "No active account found with the given credentials"}` | Проверьте почту и пароль | | `401` | `{"detail": "Authentication credentials were not provided."}` | Добавьте заголовок `Authorization` | | `401` | `{"detail": "Given token not valid for any token type", "code": "token_not_valid", ...}` | Токен истёк или испорчен: войдите заново | Не храните пароль в коде и репозитории. Передавайте его через переменные окружения или хранилище секретов вашей платформы. Входите в кабинет через Google? У такого аккаунта может не быть пароля. Задайте его на странице [восстановления пароля](https://personal.aigenda.tech/ru/recovery-password), и вход через API заработает. # Изменения Source: https://docs.aigenda.tech/changelog Что нового в API и документации AiGenda. Опубликована документация API: вход, пространства и минуты, четыре способа загрузки записи, обработка, статусы, структура результата и справочник запросов. # Документация API Source: https://docs.aigenda.tech/index Загружайте записи встреч и звонков из своей системы и получайте протокол и расшифровку. AiGenda превращает запись встречи в протокол: о чём договорились, кто за что отвечает, кто что сказал. API делает то же, что личный кабинет, только из вашей системы: вы загружаете запись, запускаете обработку и забираете результат. | | | | - | - | | Базовый адрес | `https://api.aigenda.tech` | | Формат | JSON, кодировка UTF-8 | | Авторизация | JWT в заголовке `Authorization: Bearer ` | | Время и длительность | даты в ISO 8601 (UTC), длительность и минуты тарифа в секундах | ## Как проходит запись
1
Токен
POST /api/token/
Получаете по почте и паролю аккаунта AiGenda
2
Пространство
GET /api/spaces/
Выбираете, где лежат записи и с какого тарифа списываются минуты
3
Загрузка
POST …/audio/
Файлом, по ссылке, с YouTube или ботом на встречу
4
Обработка
POST /api/audio/classify/
Запускаете и опрашиваете статус
5
Результат
GET …/result/
Протокол в Markdown, расшифровка по репликам, исходный файл
Первый протокол за шесть запросов curl. Файл, ссылка, YouTube или бот на встречу. Что лежит в протоколе и расшифровке. Скрипт на Python от входа до готового протокола. ## Что понадобится * **Аккаунт AiGenda с паролем.** Если вы входите в кабинет через Google, задайте пароль на странице [восстановления пароля](https://personal.aigenda.tech/ru/recovery-password). * **Минуты на тарифе.** Обработка списывает их по длительности записи. Остаток видно в кабинете и в API, см. [Пространства и минуты](/spaces). Заведите под интеграцию отдельный аккаунт и пригласите его в нужное пространство. Тогда интеграция не зависит от пароля конкретного сотрудника, а записи из API легко отличить в кабинете. Пишете интеграцию с помощью AI-агента? Дайте ему ссылку на [полную версию документации одним файлом](https://docs.aigenda.tech/llms-full.txt) и готовый промпт со страницы [Интеграция с AI-агентом](/reference/ai-agents). # Скачивание файлов Source: https://docs.aigenda.tech/processing/files Исходная запись, протокол и расшифровка в виде файлов. | Что | Откуда взять | Формат | | - | - | - | | Исходная запись | поле `url` в [`info/`](/api-reference/audio/info) | файл в исходном формате | | Протокол | `result.protocol` в [`result/`](/api-reference/processing/result) | Markdown | | Расшифровка | `result.dialog` в [`result/`](/api-reference/processing/result) | JSON | ## Исходная запись Поле `url` в ответе `info/` содержит временную ссылку на файл в хранилище. Запрашивайте `info/` прямо перед скачиванием, чтобы ссылка была свежей. ```bash theme={null} URL=$(curl -s "https://api.aigenda.tech/api/spaces/1024/audio/51234/info/" \ -H "Authorization: Bearer " | jq -r .url) curl -s -o "planerka.mp3" "$URL" ``` Заголовок `Authorization` для скачивания по ссылке не нужен. ## Протокол в Word или PDF API отдаёт протокол в Markdown. В DOCX или PDF его переводит [Pandoc](https://pandoc.org): ```bash theme={null} curl -s "https://api.aigenda.tech/api/spaces/1024/audio/51234/result/" \ -H "Authorization: Bearer " | jq -r .result.protocol > protocol.md pandoc protocol.md -o protocol.docx pandoc protocol.md -o protocol.pdf --pdf-engine=xelatex -V mainfont="DejaVu Sans" ``` Для PDF с кириллицей нужен шрифт с кириллическими глифами, поэтому в примере указан `mainfont`. Готовый PDF-конспект можно скачать в [личном кабинете](https://personal.aigenda.tech/ru) на тарифах Start и PRO. ## Расшифровка `result.dialog` содержит реплики по порядку: текст, таймкоды и спикер. Из них собирается текстовая расшифровка или субтитры в нужном вам формате. # Структура результата Source: https://docs.aigenda.tech/processing/result Что лежит в готовом результате: протокол, реплики, спикеры, язык. Готовый результат отдаёт [`GET /api/spaces/{space_id}/audio/{audio_id}/result/`](/api-reference/processing/result), когда в ответе `classified: true`. ## Верхний уровень | Поле | Тип | Что внутри | | - | - | - | | `classified` | boolean | `true`, когда обработка закончена | | `success` | boolean | `true`, если обработка прошла успешно | | `result` | object | Протокол, реплики и спикеры, см. ниже | | `audio_id` | integer | Идентификатор записи | | `title` | string | Название записи | | `duration` | integer | Длительность записи в секундах | | `url` | string | Временная ссылка на исходный файл | | `is_shared` | boolean | Открыт ли публичный доступ к результату | ## Объект result | Поле | Что внутри | | - | - | | `protocol` | Протокол встречи в Markdown: итоги, решения, задачи и ответственные | | `dialog` | Расшифровка по репликам: текст, таймкоды, спикер | | `speakers_map` | Соответствие идентификаторов спикеров и меток вида `SPEAKER_00` | | `speakers_timeline` | Кто и когда говорил по ходу записи | | `language` | Язык записи, например `ru` | ## Протокол `protocol` приходит готовым Markdown. Его можно сразу показать в интерфейсе или сохранить в файл. ```markdown Пример протокола theme={null} ## Итоги встречи Обсудили план продаж на ноябрь и запуск нового тарифа для малого бизнеса. ## Решения - Запускаем тариф «Старт+» 1 ноября. - Скидку для текущих клиентов оставляем до конца года. ## Задачи | Задача | Ответственный | Срок | |---|---|---| | Подготовить лендинг тарифа | {101} | 25 октября | | Обновить скрипт звонка | {102} | 28 октября | ``` Ответственные в протоколе подставлены как идентификаторы спикеров в фигурных скобках: `{101}`. Сопоставьте их по `speakers_map` и подставьте имена, если они у вас есть. ## Спикеры AiGenda сама разделяет голоса и нумерует спикеров. Спикеры принадлежат пространству: если переименовать голос в кабинете, AiGenda узнает его в следующих записях этого пространства. # Запуск обработки Source: https://docs.aigenda.tech/processing/start Протокол с расшифровкой или только расшифровка. Загрузка сама обработку не запускает. Когда в [`info/`](/api-reference/audio/info) пришло `is_uploaded: true`, вызовите один из двух запросов. | Запрос | Что получите | | - | - | | [`POST /api/audio/classify/`](/api-reference/processing/classify) | Протокол встречи, расшифровку по репликам, спикеров | | [`POST /api/audio/classify_only_transcription/`](/api-reference/processing/classify-transcription) | Только расшифровку, без протокола | ```bash theme={null} curl -X POST https://api.aigenda.tech/api/audio/classify/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"audio_id": 51234}' ``` ```json Ответ 201 theme={null} { "request_id": "c0a8012e-7f3d-4b8e-9a51-2d6f0e4b9c17" } ``` `space_id` в запросе не нужен: AiGenda знает, в каком пространстве лежит запись. `request_id` сохранять не обязательно, статус проверяется по `audio_id`. ## Минуты Минуты списываются в момент запуска `classify`: ровно длительность записи в целых секундах. Если обработка упадёт, минуты вернутся сами через пару минут. Перед запуском убедитесь, что [остатка хватает](/spaces). ## Параметры Язык AiGenda определяет сама и возвращает его в поле `result.language`. Других настроек у запуска нет. Не запускайте обработку одной записи второй раз, пока не получили результат или ошибку. Дождитесь итога по правилам со страницы [Статусы и ожидание](/processing/status). # Статусы и ожидание Source: https://docs.aigenda.tech/processing/status Как понять, что результат готов, что обработка ещё идёт или упала. Уведомлений о готовности у API нет, результат нужно опрашивать. Источник правды: ответ [`GET /api/spaces/{space_id}/audio/{audio_id}/result/`](/api-reference/processing/result). ## Состояния | Ответ `result/` | Поля в `info/` | Что значит | Что делать | | - | - | - | - | | `404`, HTML-страница | `was_classified: false` | Обработку не запускали | Вызовите [`classify`](/processing/start) | | `200`, `classified: false` | `was_classified: true` | Обработка идёт | Ждите, опрашивайте дальше | | `200`, `classified: true`, `success: true` | `result_is_ready: true` | Готово | Заберите [результат](/processing/result) | | `500`, HTML-страница, держится больше 3 минут | `was_classified: true`, `result_is_ready: false` | Обработка упала | См. ниже | Ошибки `404` и `500` приходят HTML-страницей, а не JSON. Проверяйте код ответа до разбора тела. ## Сколько ждать Короткая запись обрабатывается за 1–4 минуты. Длинные записи и очередь в часы нагрузки добавляют время. Опрашивайте раз в 10–15 секунд и закладывайте общий таймаут не меньше часа. ## Если обработка упала Сначала обработка идёт как обычно (`200`, `classified: false`), потом `result/` начинает отвечать `500`. Если `500` держится дольше 3 минут подряд, считайте обработку упавшей. Минуты вернутся сами. Частые причины: * в `title` нет расширения файла или оно не то, см. [Форматы](/upload/formats); * в файле нет длительности, см. [Длительность в файле](/upload/formats); * файл повреждён или в нём нет звука. Исправьте файл или название и загрузите запись заново. ## Готовый код ```python Python theme={null} import time import requests API = "https://api.aigenda.tech" def wait_for_result(token: str, space_id: int, audio_id: int, timeout: int = 3600) -> dict: """Ждёт результат обработки. Возвращает тело ответа result/ или бросает исключение.""" headers = {"Authorization": f"Bearer {token}"} url = f"{API}/api/spaces/{space_id}/audio/{audio_id}/result/" started = time.monotonic() not_found_since = None failing_since = None while time.monotonic() - started < timeout: r = requests.get(url, headers=headers, timeout=30) now = time.monotonic() if r.status_code == 200: not_found_since = failing_since = None body = r.json() if body.get("classified") and body.get("result"): return body elif r.status_code == 404: # сразу после classify статус может обновиться не мгновенно not_found_since = not_found_since or now if now - not_found_since > 60: raise RuntimeError("Обработка не запущена: вызовите classify") elif r.status_code >= 500: failing_since = failing_since or now if now - failing_since > 180: raise RuntimeError("Обработка упала, минуты вернутся автоматически") time.sleep(15) raise TimeoutError("Результат не готов за отведённое время") ``` # Быстрый старт Source: https://docs.aigenda.tech/quickstart От токена до готового протокола за шесть запросов. Пройдём весь путь на коротком файле `planerka.mp3`. Понадобятся `curl` и [`jq`](https://jqlang.org) для разбора JSON. Передайте почту и пароль аккаунта AiGenda. В ответе придёт пара токенов, для запросов нужен `access`. ```bash theme={null} export AIGENDA_EMAIL="you@example.com" export AIGENDA_PASSWORD="ваш-пароль" TOKEN=$(curl -s -X POST https://api.aigenda.tech/api/token/ \ -H "Content-Type: application/json" \ -d "{\"username\": \"$AIGENDA_EMAIL\", \"password\": \"$AIGENDA_PASSWORD\"}" \ | jq -r .access) ``` Поле называется `username`, но в него кладётся почта. Подробнее: [Авторизация](/authentication). Записи живут в пространствах. Возьмите своё личное пространство, у него `is_main_space: true`. ```bash theme={null} SPACE_ID=$(curl -s "https://api.aigenda.tech/api/spaces/?limit=50&offset=0" \ -H "Authorization: Bearer $TOKEN" \ | jq -r '.results[] | select(.is_main_space) | .space.id') ``` Сообщите название, точный размер файла в байтах и MIME-тип. Название обязательно заканчивается расширением файла. ```bash theme={null} FILE=planerka.mp3 SIZE=$(wc -c < "$FILE" | tr -d ' ') CREATED=$(curl -s -X POST "https://api.aigenda.tech/api/spaces/$SPACE_ID/audio/" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"title\": \"$FILE\", \"size\": $SIZE, \"content_type\": \"audio/mpeg\"}") AUDIO_ID=$(echo "$CREATED" | jq -r .id) UPLOAD_URL=$(echo "$CREATED" | jq -r '.url[0]') ``` В `url` приходит массив ссылок для загрузки, по одной на часть файла. Файлу меньше 1 ГБ хватает одной. Отправьте файл по ссылке методом `PUT` и сохраните заголовок `ETag` из ответа. Затем сообщите AiGenda, что загрузка закончена. ```bash theme={null} ETAG=$(curl -s -X PUT "$UPLOAD_URL" --upload-file "$FILE" -D - -o /dev/null \ | grep -i '^etag:' | cut -d' ' -f2 | tr -d '\r') curl -s -X POST "https://api.aigenda.tech/api/spaces/$SPACE_ID/audio/$AUDIO_ID/complete_upload/" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg etag "$ETAG" '{parts: [{PartNumber: 1, ETag: $etag}]}')" until curl -s "https://api.aigenda.tech/api/spaces/$SPACE_ID/audio/$AUDIO_ID/info/" \ -H "Authorization: Bearer $TOKEN" | jq -e .is_uploaded > /dev/null; do sleep 2; done ``` `ETag` приходит в двойных кавычках, их нужно передать как есть. Цикл в конце ждёт, пока AiGenda подтвердит файл (`is_uploaded: true`). ```bash theme={null} curl -s -X POST https://api.aigenda.tech/api/audio/classify/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"audio_id\": $AUDIO_ID}" ``` В этот момент с тарифа списываются минуты по длительности записи. Опрашивайте результат раз в 15 секунд, пока не придёт `classified: true`. ```bash theme={null} while true; do RESULT=$(curl -s "https://api.aigenda.tech/api/spaces/$SPACE_ID/audio/$AUDIO_ID/result/" \ -H "Authorization: Bearer $TOKEN") echo "$RESULT" | jq -e '.classified == true' > /dev/null 2>&1 && break sleep 15 done echo "$RESULT" | jq -r .result.protocol > protocol.md ``` Готово: протокол встречи лежит в `protocol.md`. Этот цикл не отличает упавшую обработку от идущей и будет ждать вечно. В рабочей интеграции обрабатывайте ошибки по правилам со страницы [Статусы и ожидание](/processing/status). ## Что дальше Файлы больше 1 ГБ, код на Python и JavaScript. Протокол, реплики, спикеры. # Интеграция с AI-агентом Source: https://docs.aigenda.tech/reference/ai-agents Как дать Claude, Cursor или другому агенту всё нужное, чтобы он написал интеграцию с AiGenda. Документация доступна агентам в машиночитаемом виде: | Что | Адрес | | - | - | | Вся документация одним файлом | [`https://docs.aigenda.tech/llms-full.txt`](https://docs.aigenda.tech/llms-full.txt) | | Оглавление со ссылками | [`https://docs.aigenda.tech/llms.txt`](https://docs.aigenda.tech/llms.txt) | | Любая страница в Markdown | добавьте `.md` к адресу страницы | Кнопка в шапке каждой страницы копирует её в Markdown или открывает в ChatGPT, Claude, Cursor и VS Code. ## MCP-сервер документации Подключите документацию к агенту как MCP-сервер: агент сам найдёт нужную страницу, пока пишет код. ```bash Claude Code theme={null} claude mcp add --transport http aigenda-docs https://docs.aigenda.tech/mcp ``` ```json Cursor (.cursor/mcp.json) theme={null} { "mcpServers": { "aigenda-docs": { "url": "https://docs.aigenda.tech/mcp" } } } ``` ```json VS Code (.vscode/mcp.json) theme={null} { "servers": { "aigenda-docs": { "type": "http", "url": "https://docs.aigenda.tech/mcp" } } } ``` Сервер только читает документацию. Доступа к вашему аккаунту AiGenda у него нет. ## Промпт Скопируйте и допишите под свою задачу: ```text Промпт для агента theme={null} Напиши интеграцию с API AiGenda: загрузка записи встречи, обработка, получение протокола. Документация: https://docs.aigenda.tech/llms-full.txt. Прочитай её целиком перед тем, как писать код. Где запись: <файл на диске / ссылка / YouTube / бот на встречу> Язык и стек: Куда положить результат: <файл protocol.md / наша база / ...> Обязательные правила из документации: 1. Токен: POST /api/token/ с полями username (почта) и password. Заголовок Authorization: Bearer . 2. title записи заканчивается расширением файла (.mp3, .m4a, .wav, .ogg, .webm, .mp4). 3. Файл грузится частями по ссылкам из массива url методом PUT; ETag каждой части передаётся в complete_upload с кавычками. 4. Перед classify дождаться is_uploaded: true в GET .../info/. 5. Результат опрашивать раз в 15 секунд: 200 + classified: true = готово; 500 дольше 3 минут = упало; 404 = обработку не запускали. 6. Не повторять вслепую POST создания записи: каждый вызов создаёт новую запись. 7. Почту и пароль брать из переменных окружения AIGENDA_EMAIL и AIGENDA_PASSWORD. Начни с плана, потом код, потом инструкцию по запуску. ``` ## С чего агенту начать Полный рабочий скрипт на Python лежит на странице [Полный пример](/reference/full-example). Агенту проще всего взять его за основу и переписать под ваш стек. # Надёжная интеграция Source: https://docs.aigenda.tech/reference/best-practices Таймауты, повторы, потерянные ответы и порядок проверок. ## Перед загрузкой 1. Получите свежий остаток минут: [`GET /api/spaces/{space_id}/`](/api-reference/spaces/get), поле `subscribe.available_usage_count`. 2. Убедитесь, что остатка хватает на запись с запасом 5 минут. 3. В командном пространстве проверьте `write_access` в [`my_rights/`](/api-reference/spaces/rights). ## Уникальные названия Добавляйте в `title` метку, по которой вы найдёте запись: дату, время, идентификатор из вашей системы. ```text theme={null} Звонок · Иван Петров · 2026-10-17 14:30 · crm-48213.mp3 ``` Расширение файла по-прежнему стоит в самом конце. ## Потерянный ответ на создание записи Если ответ на `POST …/audio/` (или `by_url/`, `by_youtube/`) не пришёл из-за таймаута или обрыва, запись могла создаться. Не повторяйте запрос вслепую: 1. Найдите запись по названию: `GET /api/spaces/{space_id}/audio/?search=&ordering=-created_at`. 2. Нашли с `is_uploaded: false`: создайте запись заново, а найденную пустую [удалите](/api-reference/audio/delete). 3. Не нашли: создайте запись заново. ## Таймауты | Запрос | Таймаут | | - | - | | Запросы к API | 30 секунд | | `PUT` части файла | по скорости канала: часть до 1 ГБ на 10 Мбит/с грузится около 15 минут | ## Ссылки для загрузки живут 5 часов Создавайте запись прямо перед загрузкой. Если между созданием и загрузкой прошло больше 5 часов, создайте запись заново, а старую удалите. ## Токен Получайте новый токен по почте и паролю, когда до истечения `access` осталось меньше суток или API ответил `401`. Подробнее: [Авторизация](/authentication). ## Ответ не в JSON Изредка API отвечает не JSON, а HTML-страницей ошибки. Проверяйте `Content-Type` перед разбором. Для безопасных запросов (`GET`, вход) повторите запрос через 1–2 секунды. ## Ожидание результата Опрашивайте `result/` раз в 10–15 секунд, не чаще. Считайте обработку упавшей, если `500` держится дольше 3 минут подряд. Подробнее: [Статусы и ожидание](/processing/status). # Ошибки Source: https://docs.aigenda.tech/reference/errors Коды ответов API и что с ними делать. Успешные ответы приходят в JSON. Ошибки `400`, `401` и `403` тоже в JSON, а `404` и `500` приходят HTML-страницей. Поэтому сначала проверяйте код ответа и заголовок `Content-Type`, а потом разбирайте тело. | Код | Когда | Тело | Что делать | | - | - | - | - | | `200`, `201` | Успех | JSON. У `complete_upload` и `delete_list` тело пустое | — | | `400` | Ошибка в данных запроса | `{"title": ["This field is required."]}`: поле и список ошибок | Исправьте поля из ответа | | `401` | Нет токена, он истёк или неверный | `{"detail": "…"}` | Получите новый токен, см. [Авторизация](/authentication) | | `403` | Нет прав на пространство или его не существует | `{"detail": "You do not have permission to perform this action."}` | Проверьте `space_id` и [права](/api-reference/spaces/rights) | | `404` | Нет такого адреса или записи. У `result/`: обработку не запускали | HTML | Проверьте адрес и `audio_id` | | `500` | Ошибка на стороне AiGenda. У `result/`: обработка упала | HTML | Повторите позже. Для `result/` см. [Статусы](/processing/status) | ## Повторы | Запрос | Повторять при сбое сети или `5xx`? | | - | - | | `GET` любой | Да, с паузой 2, 4, 8 секунд | | `POST /api/token/` | Да, 1–2 раза через 1–2 секунды | | `PUT` части файла | Да, по той же ссылке, пока она не истекла | | `POST …/complete_upload/` | Сначала проверьте `is_uploaded` в `info/`. Если `false`, повторите | | `POST …/audio/`, `by_url/`, `by_youtube/`, `meeting/` | **Нет.** Каждый вызов создаёт новую запись. Сначала проверьте, не создалась ли она, см. [Надёжная интеграция](/reference/best-practices) | | `POST /api/audio/classify/` | Нет. Сначала проверьте статус в `result/` | # Полный пример Source: https://docs.aigenda.tech/reference/full-example Скрипт на Python: вход, проверка минут, загрузка, обработка, протокол в файл. Скрипт загружает файл в личное пространство, ждёт обработку и сохраняет протокол рядом с файлом. Нужен Python 3.9+ и пакет `requests`. ```bash theme={null} pip install requests export AIGENDA_EMAIL="you@example.com" export AIGENDA_PASSWORD="ваш-пароль" python aigenda_upload.py "Планёрка отдела продаж.mp3" audio/mpeg ``` ```python aigenda_upload.py theme={null} """Загрузка записи в AiGenda и получение протокола. Использование: python aigenda_upload.py <файл> <content_type> """ import math import os import sys import time import requests API = "https://api.aigenda.tech" MIN_RESERVE_SECONDS = 5 * 60 # запас минут сверх длительности записи def login(email: str, password: str) -> str: for attempt in range(3): r = requests.post(f"{API}/api/token/", json={"username": email, "password": password}, timeout=30) if r.status_code == 401: raise SystemExit("Неверная почта или пароль") if r.ok and r.headers.get("Content-Type", "").startswith("application/json"): return r.json()["access"] time.sleep(1.5) r.raise_for_status() raise RuntimeError("Не удалось войти") def main_space(headers: dict) -> dict: r = requests.get(f"{API}/api/spaces/", params={"limit": 50, "offset": 0}, headers=headers, timeout=30) r.raise_for_status() return next(item["space"] for item in r.json()["results"] if item["is_main_space"]) def available_seconds(headers: dict, space_id: int) -> int: r = requests.get(f"{API}/api/spaces/{space_id}/", headers=headers, timeout=30) r.raise_for_status() return r.json()["subscribe"]["available_usage_count"] def upload_file(headers: dict, space_id: int, path: str, content_type: str) -> int: size = os.path.getsize(path) r = requests.post( f"{API}/api/spaces/{space_id}/audio/", headers=headers, json={"title": os.path.basename(path), "size": size, "content_type": content_type}, timeout=30, ) r.raise_for_status() audio = r.json() part_size = math.ceil(size / len(audio["url"])) parts = [] with open(path, "rb") as f: for number, url in enumerate(audio["url"], start=1): put = requests.put(url, data=f.read(part_size), timeout=900) put.raise_for_status() parts.append({"PartNumber": number, "ETag": put.headers["ETag"]}) r = requests.post( f"{API}/api/spaces/{space_id}/audio/{audio['id']}/complete_upload/", headers=headers, json={"parts": parts}, timeout=30, ) r.raise_for_status() for _ in range(60): info = requests.get(f"{API}/api/spaces/{space_id}/audio/{audio['id']}/info/", headers=headers, timeout=30) if info.ok and info.json().get("is_uploaded"): return audio["id"] time.sleep(2) raise TimeoutError("AiGenda не подтвердила файл за 2 минуты") def start_processing(headers: dict, audio_id: int) -> None: r = requests.post(f"{API}/api/audio/classify/", headers=headers, json={"audio_id": audio_id}, timeout=30) r.raise_for_status() def wait_for_result(headers: dict, space_id: int, audio_id: int, timeout: int = 3600) -> dict: url = f"{API}/api/spaces/{space_id}/audio/{audio_id}/result/" started = time.monotonic() not_found_since = failing_since = None while time.monotonic() - started < timeout: r = requests.get(url, headers=headers, timeout=30) now = time.monotonic() if r.status_code == 200: not_found_since = failing_since = None body = r.json() if body.get("classified") and body.get("result"): return body elif r.status_code == 404: not_found_since = not_found_since or now if now - not_found_since > 60: raise RuntimeError("Обработка не запущена") elif r.status_code >= 500: failing_since = failing_since or now if now - failing_since > 180: raise RuntimeError("Обработка упала, минуты вернутся автоматически") time.sleep(15) raise TimeoutError("Результат не готов за час") def main() -> None: path, content_type = sys.argv[1], sys.argv[2] token = login(os.environ["AIGENDA_EMAIL"], os.environ["AIGENDA_PASSWORD"]) headers = {"Authorization": f"Bearer {token}"} space = main_space(headers) left = available_seconds(headers, space["id"]) print(f"Пространство «{space['name']}», осталось {left // 60} мин") if left <= MIN_RESERVE_SECONDS: raise SystemExit("Минут на тарифе почти не осталось") audio_id = upload_file(headers, space["id"], path, content_type) print(f"Файл загружен, audio_id={audio_id}") start_processing(headers, audio_id) print("Обработка запущена, ждём результат…") result = wait_for_result(headers, space["id"], audio_id) out = os.path.splitext(path)[0] + ".protocol.md" with open(out, "w", encoding="utf-8") as f: f.write(result["result"]["protocol"]) print(f"Протокол сохранён: {out}") if __name__ == "__main__": main() ``` # Пространства и минуты Source: https://docs.aigenda.tech/spaces Где лежат записи, откуда списываются минуты и как проверить права. Пространство объединяет записи, участников и тариф. У каждого аккаунта есть личное пространство. Командные появляются, когда вас приглашают коллеги. Почти все запросы к записям содержат `space_id`. ## Найти space\_id ```bash theme={null} curl "https://api.aigenda.tech/api/spaces/?limit=50&offset=0" \ -H "Authorization: Bearer <access>" ``` ```json Ответ 200 (основные поля) theme={null} { "count": 2, "next": null, "previous": null, "results": [ { "is_main_space": true, "space": { "id": 1024, "name": "Личное пространство", "description": "Main space", "subscribe": { "offer": { "name": "PRO", "audio_limit": 72000 }, "usage_count": 5400, "available_usage_count": 66600, "is_active": true, "end_date": "2026-11-17T00:00:00Z" } } }, { "is_main_space": false, "space": { "id": 2048, "name": "Отдел продаж", "description": "Записи звонков с клиентами" } } ] } ``` Личное пространство отмечено `is_main_space: true`. Его `space.id` и есть `space_id`. ## Минуты Тариф и остаток лежат в `space.subscribe`. Все значения в **секундах**. | Поле | Что значит | | - | - | | `offer.name` | Название тарифа | | `offer.audio_limit` | Сколько секунд даёт тариф за период | | `usage_count` | Сколько уже потрачено | | `available_usage_count` | Сколько осталось | | `end_date` | Когда закончится период | Свежий остаток конкретного пространства отдаёт [`GET /api/spaces/{space_id}/`](/api-reference/spaces/get). **Когда списываются минуты.** В момент запуска обработки, ровно на длительность записи в целых секундах (запись 71,8 с спишет 71 с). Загрузка без обработки минут не тратит. Если обработка упала, минуты вернутся сами через пару минут. <Warning> Перед загрузкой проверьте, что остатка хватает на всю запись с запасом 5 минут. Запись длиннее остатка AiGenda не обработает. </Warning> ## Права В командном пространстве у вас может не быть права загружать записи. Проверьте его заранее: ```bash theme={null} curl "https://api.aigenda.tech/api/spaces/1024/my_rights/" \ -H "Authorization: Bearer <access>" ``` Загружать записи можно, если в ответе `write_access: true`. Полный список полей: [Права в пространстве](/api-reference/spaces/rights). ## Постраничный вывод Списки (пространства, записи, корзина) отдаются страницами. Управляйте ими параметрами `limit` и `offset`. Ссылки `next` и `previous` в ответе приходят со схемой `http://`, поэтому собирайте адрес следующей страницы сами: `offset = offset + limit`, пока `offset < count`. # Загрузка файла Source: https://docs.aigenda.tech/upload/file Файл любого размера: создаём запись, грузим части в хранилище, подтверждаем загрузку. Файл уходит не в API, а прямо в объектное хранилище по временным ссылкам. API выдаёт ссылки и принимает подтверждение. <div> <div> <div>Ваш сервис</div> <div>API AiGenda</div> <div>Хранилище</div> </div> <div> <div /> <div /> <div /> <div> <div><div>1</div></div> <div><div>POST /audio/</div><div>title, size, content\_type</div></div> <div> <div /> </div> </div> <div> <div><div>2</div></div> <div><div>id, url\[]</div><div>ссылки на части</div></div> <div> <div /> </div> </div> <div> <div><div>3</div></div> <div><div>PUT часть</div><div>по ссылке url\[i]</div></div> <div> <div /> </div> </div> <div> <div><div>4</div></div> <div><div>ETag</div><div>в заголовке ответа</div></div> <div> <div /> </div> </div> <div> <div><div>5</div></div> <div><div>POST /complete\_upload/</div><div>PartNumber и ETag</div></div> <div> <div /> </div> </div> <div> <div><div>6</div></div> <div><div>GET /info/</div><div>до is\_uploaded: true</div></div> <div> <div /> </div> </div> </div> </div> <div> <div> <div>1</div> <div> <div>Ваш сервис → API AiGenda</div> <div>POST /audio/</div> <div>title, size, content\_type</div> </div> </div> <div> <div>2</div> <div> <div>API AiGenda → Ваш сервис</div> <div>id, url\[]</div> <div>ссылки на части</div> </div> </div> <div> <div>3</div> <div> <div>Ваш сервис → Хранилище</div> <div>PUT часть</div> <div>по ссылке url\[i]</div> </div> </div> <div> <div>4</div> <div> <div>Хранилище → Ваш сервис</div> <div>ETag</div> <div>в заголовке ответа</div> </div> </div> <div> <div>5</div> <div> <div>Ваш сервис → API AiGenda</div> <div>POST /complete\_upload/</div> <div>PartNumber и ETag</div> </div> </div> <div> <div>6</div> <div> <div>Ваш сервис → API AiGenda</div> <div>GET /info/</div> <div>до is\_uploaded: true</div> </div> </div> </div> ## Шаги <Steps> <Step title="Создайте запись"> ```bash theme={null} curl -X POST https://api.aigenda.tech/api/spaces/1024/audio/ \ -H "Authorization: Bearer <access>" \ -H "Content-Type: application/json" \ -d '{"title": "Планёрка отдела продаж.mp3", "size": 18874368, "content_type": "audio/mpeg"}' ``` | Поле | Правило | | - | - | | `title` | До 255 символов. **Заканчивается расширением файла**: `.mp3`, `.m4a`, `.wav`, `.ogg`, `.webm`, `.mp4`. По расширению AiGenda определяет формат | | `size` | Точный размер файла в байтах | | `content_type` | MIME-тип: `audio/mpeg`, `audio/mp4`, `audio/wav`, `audio/ogg`, `audio/webm`, `video/mp4` | ```json Ответ 201 theme={null} { "id": 51234, "title": "Планёрка отдела продаж.mp3", "url": [ "https://storage.yandexcloud.net/aigenda/3f6c1e0a.mp3?partNumber=1&uploadId=…&X-Amz-Signature=…" ], "created_at": "2026-10-17T09:30:00Z", "duration": null, "size": 18874368, "content_type": "audio/mpeg", "space_id": 1024, "is_uploaded": false, "was_classified": false, "result_is_ready": false } ``` `url` всегда массив: по ссылке на каждую часть файла, примерно одна часть на 1 ГБ. </Step> <Step title="Загрузите части"> Разделите файл на столько частей, сколько пришло ссылок: * размер части: `ceil(size / len(url))` байт, последняя часть короче; * часть с номером `i` (с единицы) уходит на ссылку `url[i-1]`; * метод `PUT`, тело запроса: байты части, без JSON и multipart-формы; * из ответа хранилища сохраните заголовок `ETag` вместе с двойными кавычками: `"9b2cf535f27731c974343645a3985328"`. Ссылки живут **5 часов** с момента создания записи. Хранилище разрешает запросы из браузера (CORS открыт, `ETag` читается), так что грузить можно и с фронтенда. </Step> <Step title="Завершите загрузку"> Передайте номера частей и их `ETag` в том порядке, в котором грузили. ```bash theme={null} curl -X POST https://api.aigenda.tech/api/spaces/1024/audio/51234/complete_upload/ \ -H "Authorization: Bearer <access>" \ -H "Content-Type: application/json" \ -d '{"parts": [{"PartNumber": 1, "ETag": "\"9b2cf535f27731c974343645a3985328\""}]}' ``` Ответ: `200` с пустым телом. </Step> <Step title="Дождитесь подтверждения"> Опрашивайте [`info/`](/api-reference/audio/info) раз в 2 секунды, пока не придёт `is_uploaded: true`. Обычно это меньше секунды. После этого [запускайте обработку](/processing/start). </Step> </Steps> ## Готовый код <CodeGroup> ```python Python theme={null} import math import os import time import requests API = "https://api.aigenda.tech" def upload_file(token: str, space_id: int, path: str, content_type: str) -> int: """Загружает файл в пространство и возвращает audio_id, когда AiGenda подтвердила файл.""" headers = {"Authorization": f"Bearer {token}"} size = os.path.getsize(path) title = os.path.basename(path) # имя с расширением, например «Планёрка.mp3» r = requests.post( f"{API}/api/spaces/{space_id}/audio/", headers=headers, json={"title": title, "size": size, "content_type": content_type}, timeout=30, ) r.raise_for_status() audio = r.json() urls = audio["url"] part_size = math.ceil(size / len(urls)) parts = [] with open(path, "rb") as f: for number, url in enumerate(urls, start=1): chunk = f.read(part_size) put = requests.put(url, data=chunk, timeout=900) put.raise_for_status() parts.append({"PartNumber": number, "ETag": put.headers["ETag"]}) r = requests.post( f"{API}/api/spaces/{space_id}/audio/{audio['id']}/complete_upload/", headers=headers, json={"parts": parts}, timeout=30, ) r.raise_for_status() for _ in range(60): info = requests.get( f"{API}/api/spaces/{space_id}/audio/{audio['id']}/info/", headers=headers, timeout=30, ).json() if info.get("is_uploaded"): return audio["id"] time.sleep(2) raise TimeoutError("AiGenda не подтвердила файл за 2 минуты") ``` ```javascript JavaScript (Node.js 18+) theme={null} import { open, stat } from "node:fs/promises"; import { basename } from "node:path"; const API = "https://api.aigenda.tech"; // Загружает файл в пространство и возвращает audioId, когда AiGenda подтвердила файл. export async function uploadFile(token, spaceId, path, contentType) { const auth = { Authorization: `Bearer ${token}` }; const json = { ...auth, "Content-Type": "application/json" }; const { size } = await stat(path); const created = await fetch(`${API}/api/spaces/${spaceId}/audio/`, { method: "POST", headers: json, body: JSON.stringify({ title: basename(path), size, content_type: contentType }), }); if (!created.ok) throw new Error(`create: ${created.status}`); const audio = await created.json(); const partSize = Math.ceil(size / audio.url.length); const parts = []; const file = await open(path); try { for (let i = 0; i < audio.url.length; i++) { const length = Math.min(partSize, size - i * partSize); const chunk = Buffer.alloc(length); await file.read(chunk, 0, length, i * partSize); const put = await fetch(audio.url[i], { method: "PUT", body: chunk }); if (!put.ok) throw new Error(`part ${i + 1}: ${put.status}`); parts.push({ PartNumber: i + 1, ETag: put.headers.get("ETag") }); } } finally { await file.close(); } const done = await fetch(`${API}/api/spaces/${spaceId}/audio/${audio.id}/complete_upload/`, { method: "POST", headers: json, body: JSON.stringify({ parts }), }); if (!done.ok) throw new Error(`complete: ${done.status}`); for (let attempt = 0; attempt < 60; attempt++) { const res = await fetch(`${API}/api/spaces/${spaceId}/audio/${audio.id}/info/`, { headers: auth }); const info = await res.json(); if (info.is_uploaded) return audio.id; await new Promise((resolve) => setTimeout(resolve, 2000)); } throw new Error("AiGenda не подтвердила файл за 2 минуты"); } ``` </CodeGroup> ## Если что-то пошло не так | Ситуация | Что делать | | - | - | | Хранилище ответило `403` на `PUT` | Ссылки истекли (прошло больше 5 часов). Создайте запись заново, старую [удалите](/api-reference/audio/delete) | | Ответ на создание записи не пришёл (таймаут, обрыв) | Не создавайте запись вслепую второй раз: каждый вызов добавляет новую запись. Найдите её по названию, см. [Надёжная интеграция](/reference/best-practices) | | Часть не загрузилась | Повторите `PUT` этой части по той же ссылке, пока ссылки не истекли | # Форматы и ограничения Source: https://docs.aigenda.tech/upload/formats Какие файлы принимает AiGenda и какие правила действуют для названий, размера и длительности. ## Форматы AiGenda принимает распространённые форматы аудио и видео: **MP3, M4A, WAV, OGG, WebM, MP4**. Из видео берётся звуковая дорожка. | Формат | `content_type` | Расширение в `title` | | - | - | - | | MP3 | `audio/mpeg` | `.mp3` | | M4A (AAC) | `audio/mp4` | `.m4a` | | WAV | `audio/wav` | `.wav` | | OGG (Opus) | `audio/ogg` | `.ogg` | | WebM | `audio/webm` или `video/webm` | `.webm` | | MP4 | `video/mp4` | `.mp4` | ## Название записи **`title` обязан заканчиваться расширением файла.** Формат AiGenda определяет по расширению в названии, а не по `content_type`. Запись без расширения загрузится, но обработка упадёт. | `title` | Результат | | - | - | | `Планёрка 17.10.mp3` | Обработается | | `Планёрка 17.10` | Упадёт: AiGenda примет `.10` за расширение | Длина названия до 255 символов вместе с расширением. Слэши, двоеточия и точки внутри названия допустимы. ## Размер и длительность * `size` указывайте точно, в байтах. Хранилище выдаёт ссылки под этот размер. * Одна часть файла около 1 ГБ, частей может быть несколько. Подробнее: [Загрузка файла](/upload/file). * На тарифе должно оставаться больше минут, чем длится запись, с запасом 5 минут. * Одна запись длится не больше 2,5 часа. Более длинную встречу разделите на части. ## Длительность в файле AiGenda считает списание и строит таймкоды по длительности, записанной в файле. Обычные WebM обрабатываются, но WebM прямо из `MediaRecorder` в браузере часто сохраняется без длительности. Такой файл получает длительность 0 и не обрабатывается. Перепакуйте его перед загрузкой: ```bash theme={null} ffmpeg -i recording.webm -c:a libopus -b:a 48k recording.ogg ``` ## Моно или стерео AiGenda сводит звук в моно и разделяет спикеров сама. Стерео не улучшает результат, а файл получается больше. Для речи хватает моно Opus 32–48 кбит/с: час записи весит 15–22 МБ. # Бот на встречу Source: https://docs.aigenda.tech/upload/meeting-bot Отправьте ассистента AiGenda на встречу в Zoom, Google Meet или Телемосте. Бот подключается к встрече как участник, записывает её и кладёт запись в пространство. Файл загружать не нужно. ```bash theme={null} curl -X POST https://api.aigenda.tech/api/space/1024/meeting/ \ -H "Authorization: Bearer <access>" \ -H "Content-Type: application/json" \ -d '{"link": "https://telemost.yandex.ru/j/12345678901234"}' ``` <Note> В адресе `space` в единственном числе: `/api/space/{space_id}/meeting/`. У остальных запросов `spaces`. </Note> | Поле | Правило | | - | - | | `link` | Ссылка-приглашение на встречу в Zoom, Google Meet или Яндекс Телемосте, до 255 символов | ## После встречи Когда встреча закончится, запись появится в пространстве. Найдите её в [списке записей](/api-reference/audio/list) (новые сверху: `ordering=-created_at`) и проверьте [`info/`](/api-reference/audio/info): * `was_classified: false`: запустите [обработку](/processing/start) сами; * `was_classified: true`: обработка уже идёт, опрашивайте [результат](/processing/status). <Warning> Участники встречи видят бота в списке. Предупредите их о записи заранее. </Warning> <Tip> Если в кабинете включено подключение бота по календарю, не отправляйте его через API на ту же встречу: получится две записи одной встречи. </Tip> # Способы загрузки Source: https://docs.aigenda.tech/upload/overview Файл, ссылка, YouTube или бот на встречу: что выбрать. Любой способ создаёт запись в пространстве. Дальше обработка и результат одинаковые. | Способ | Когда подходит | Запрос | | - | - | - | | [Файл](/upload/file) | Файл у вас на диске или в памяти сервиса | `POST /api/spaces/{space_id}/audio/` и загрузка в хранилище | | [По ссылке](/upload/url) | Файл лежит по прямой ссылке: облако, телефония, CRM | `POST /api/spaces/{space_id}/audio/by_url/` | | [YouTube](/upload/youtube) | Видео опубликовано на YouTube | `POST /api/spaces/{space_id}/audio/by_youtube/` | | [Бот на встречу](/upload/meeting-bot) | Встреча в Zoom, Google Meet или Телемосте ещё идёт или скоро начнётся | `POST /api/space/{space_id}/meeting/` | ## После загрузки Для файла, ссылки и YouTube порядок одинаковый: 1. Дождитесь `is_uploaded: true` в [`GET …/audio/{audio_id}/info/`](/api-reference/audio/info). Для файла это меньше секунды. Ссылку и YouTube AiGenda скачивает сама, это занимает от нескольких секунд до минут. 2. Запустите [обработку](/processing/start). 3. Опрашивайте [результат](/processing/status). <Warning> Не запускайте обработку до `is_uploaded: true`. AiGenda ещё не получила файл целиком, и обработка упадёт. </Warning> Ограничения по форматам и названиям общие для всех способов: [Форматы и ограничения](/upload/formats). # Загрузка по ссылке Source: https://docs.aigenda.tech/upload/url AiGenda сама скачает файл по прямой ссылке. Подходит, когда запись уже лежит в облаке, в телефонии или в CRM. Вы передаёте ссылку, AiGenda скачивает файл в фоне. ```bash theme={null} curl -X POST https://api.aigenda.tech/api/spaces/1024/audio/by_url/ \ -H "Authorization: Bearer <access>" \ -H "Content-Type: application/json" \ -d '{ "url": "https://records.example.com/calls/2026-10-17/client-call.mp3", "title": "Звонок с клиентом 17.10.mp3", "content_type": "audio/mpeg" }' ``` | Поле | Правило | | - | - | | `url` | Прямая ссылка на файл, до 255 символов. Файл должен скачиваться по ней без авторизации, cookies и промежуточных страниц | | `title` | До 255 символов, **заканчивается расширением файла** | | `content_type` | MIME-тип файла, например `audio/mpeg` | ## Что дальше Запрос отвечает сразу, а файл AiGenda скачивает уже после ответа. Поэтому: 1. Возьмите `id` записи из ответа. 2. Опрашивайте [`info/`](/api-reference/audio/info) раз в 3–5 секунд, пока не придёт `is_uploaded: true`. 3. Запустите [обработку](/processing/start). <Warning> Загрузка по ссылке сама обработку не запускает. Без вызова `classify` запись так и останется необработанной. </Warning> <Tip> Ссылки из облачных хранилищ с подписью (S3, Яндекс Облако) бывают длиннее 255 символов. Если ссылка не помещается, скачайте файл у себя и загрузите его [файлом](/upload/file). </Tip> # Загрузка с YouTube Source: https://docs.aigenda.tech/upload/youtube Обработка видео с YouTube по ссылке. Передайте ссылку на видео, AiGenda скачает звуковую дорожку сама. ```bash theme={null} curl -X POST https://api.aigenda.tech/api/spaces/1024/audio/by_youtube/ \ -H "Authorization: Bearer <access>" \ -H "Content-Type: application/json" \ -d '{"url": "https://www.youtube.com/watch?v=VIDEO_ID"}' ``` | Поле | Правило | | - | - | | `url` | Ссылка на видео YouTube, до 2048 символов. Видео должно открываться без входа в аккаунт | ## Что дальше Как и при [загрузке по ссылке](/upload/url), файл скачивается после ответа: 1. Возьмите `id` записи из ответа. 2. Опрашивайте [`info/`](/api-reference/audio/info), пока не придёт `is_uploaded: true`. Длинное видео скачивается дольше. 3. Запустите [обработку](/processing/start).