Follow-up по одному звонку

⚠️ Метод выходит в обновлении call 26.600.0 и доступен пока не на всех порталах Битрикс24. Если обновление на ваш портал ещё не пришло, API вернёт 422 METHOD_NOT_YET_AVAILABLE — это признак того, что метод на портале ещё не выпущен, а не ошибка интеграции.

GET /v1/calls/followups/:callId

Возвращает AI Follow-up одного завершённого звонка.

Параметры

Параметр Тип Обяз. Описание
callId (path) integer да Идентификатор звонка. Положительное целое. Где взять — POST /v1/calls/followups/list
select (query) string[] нет Какие поля вернуть. Передаётся повторяющимся параметром или списком через запятую. Словарь значений общий со списком — раздел «Поле select» страницы Список Follow-up
mentionFormat (query) string нет Формат @-упоминаний в текстовых полях: bb, html или none. По умолчанию — bb

Поле select

Значение select Что в ответе
Не указан Полный объект Follow-up. Присутствуют все поля, отсутствующие данные приходят как null
Пустой массив Только базовые метаданные: callId, callType, initiatorId, startDate, endDate, durationSeconds
Список полей Только перечисленные поля и всегда callId. Запрошенное, но незаполненное поле приходит как null

Примеры

Запрос без select — возвращается весь Follow-up целиком. mentionFormat: none убирает разметку упоминаний, поэтому текст готов к передаче в нейросеть или к сохранению в задачу. Чтобы забрать только часть блоков, добавьте select — например ?select=overview.actionItems&select=evaluation.efficiencyValue.

curl — личный ключ

Terminal
curl "https://vibecode.bitrix24.tech/v1/calls/followups/12345?mentionFormat=none" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth-приложение

Terminal
curl "https://vibecode.bitrix24.tech/v1/calls/followups/12345?mentionFormat=none" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — личный ключ

javascript
const params = new URLSearchParams({ mentionFormat: 'none' })

const res = await fetch(`https://vibecode.bitrix24.tech/v1/calls/followups/12345?${params}`, {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const body = await res.json()

if (!body.success) {
  // Ошибку разбираем явно: иначе на 403 или 422 код упадёт на обращении к data
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

const { data } = body
const call = data.item

// Готовые AI-блоки перечислены в outcomes, неготовые приходят как null
console.log(call.outcomes, `${call.durationSeconds} сек`)
console.log(call.overview?.topic ?? 'обзор ещё не сформирован')

for (const item of call.overview?.actionItems ?? []) {
  console.log('задача:', item.actionItem, '— цитата:', item.quote)
}

// speakerAnalysis отсутствует, если разбор участников на портале недоступен
for (const speaker of call.insights?.speakerAnalysis ?? []) {
  console.log(`участник ${speaker.userId}: ${speaker.talkPercentage}% времени, оценка ${speaker.efficiencyValue}`)
}

// Критерии — карта, ключи зависят от типа встречи: обходим по ключам
for (const [code, criterion] of Object.entries(call.evaluation?.criteria ?? {})) {
  console.log(code, criterion.value ? 'выполнен' : 'не выполнен', '—', criterion.thoughts)
}

JavaScript — OAuth-приложение

javascript
const params = new URLSearchParams({ mentionFormat: 'none' })

const res = await fetch(`https://vibecode.bitrix24.tech/v1/calls/followups/12345?${params}`, {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const body = await res.json()

if (!body.success) {
  // Ошибку разбираем явно: иначе на 403 или 422 код упадёт на обращении к data
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

const { data } = body
console.log(data.item)

Поля ответа

Поле Тип Описание
success boolean Всегда true при успехе
data.item object Follow-up звонка. Поля — в таблице ниже

Поля объекта item:

Поле Тип Описание
item.callId number Идентификатор звонка
item.callType number Вид звонка: 1 — мгновенный, 2 — конференция, 3 — большая комната
item.initiatorId number Инициатор звонка. Карточка сотрудника — GET /v1/users/:id
item.startDate string Начало звонка, ISO 8601 в UTC
item.endDate string | null Окончание звонка, ISO 8601 в UTC
item.durationSeconds number Длительность звонка в секундах
item.uuid string Идентификатор сессии звонка
item.language string Код языка транскрипции
item.version number Версия схемы AI-данных
item.participants object[] Участники звонка
item.outcomes string[] Готовые AI-блоки этого звонка
item.createdAt string Время последней AI-записи
item.tracks object[] Записи звонка
item.transcription object | null Транскрипция разговора
item.overview object | null Обзор встречи
item.summary object | null Краткое изложение по фрагментам
item.evaluation object | null Оценка эффективности встречи
item.insights object | null Аналитические выводы и разбор участников

Участники — `participants[]`

Поле Тип Описание
userId number Идентификатор сотрудника
name string Имя сотрудника
avatar string Ссылка на аватар
workPosition string Должность
talkedSeconds number Сколько секунд участник говорил

Записи звонка — `tracks[]`

Поле Тип Описание
trackId number Идентификатор записи
type string Вид дорожки, например mixed_audio
duration number Длительность записи в секундах
fileName string Имя файла
mimeType string MIME-тип файла
url string Ссылка на скачивание
dateCreate string Когда запись создана, ISO 8601

Транскрипция — `transcription`

Поле Тип Описание
language string Код языка расшифровки
segments[] object[] Реплики в хронологическом порядке
segments[].userId number Кто говорит
segments[].userName string Имя говорящего
segments[].start number Начало реплики, секунды от начала звонка
segments[].end number Конец реплики, секунды от начала звонка
segments[].text string Текст реплики

Обзор встречи — `overview`

Поле Тип Описание
topic string Тема встречи
detailedTakeaways string Развёрнутые выводы
meetingType object Тип встречи: typeTag — код, title — название, explanation — обоснование
agenda object Повестка: explanation — формулировка, quote — цитата из разговора
agreements[] object[] Договорённости: agreement — формулировка, quote — цитата
actionItems[] object[] Задачи: actionItem — формулировка, quote — цитата
meetings[] object[] Назначенные встречи: meeting — формулировка, quote — цитата

Краткое изложение — `summary`

Поле Тип Описание
segments[] object[] Фрагменты разговора
segments[].start number Начало фрагмента, секунды
segments[].end number Конец фрагмента, секунды
segments[].title string Заголовок фрагмента
segments[].summary string Изложение фрагмента

Аналитические выводы — `insights`

Поле Тип Описание
speakerEvaluationAvailable boolean Доступен ли разбор участников на портале
speakerAnalysis[] object[] Разбор участников, по убыванию talkPercentage
speakerAnalysis[].userId number Идентификатор сотрудника. Карточка — GET /v1/users/:id
speakerAnalysis[].detailedInsight string Вывод по участнику
speakerAnalysis[].efficiencyValue number Оценка эффективности участника, от 0 до 100
speakerAnalysis[].evaluationCriteria string Критерий, по которому дана оценка
speakerAnalysis[].talkPercentage number Доля времени, которую участник говорил, в процентах
speakerAnalysis[].duration number Сколько секунд участник говорил
speakerAnalysis[].durationFormat string То же время в виде ММ:СС
meetingStrengths[] object[] Сильные стороны: strengthTitle и strengthExplanation
meetingWeaknesses[] object[] Слабые стороны: weaknessTitle и weaknessExplanation
speechStyleInfluence string Как манера речи повлияла на встречу
engagementLevel string Вовлечённость участников
areasOfResponsibility string Кто за что отвечает по итогам
finalRecommendations string Рекомендации к следующей встрече

Оценка эффективности — `evaluation`

Поле Тип Описание
efficiencyValue number Общая эффективность встречи, от 0 до 100
calendar.overhead boolean Была ли встреча избыточной по времени
criteria object Карта критериев. Ключ — код критерия, значение — объект с полями ниже
criteria.<код>.value boolean Выполнен ли критерий
criteria.<код>.title string Название критерия
criteria.<код>.criteria string Формулировка критерия
criteria.<код>.thoughts string Обоснование оценки

Пример ответа

JSON
{
  "success": true,
  "data": {
    "item": {
      "callId": 12345,
      "callType": 1,
      "initiatorId": 7,
      "startDate": "2026-01-15T10:00:00+00:00",
      "endDate": "2026-01-15T10:42:00+00:00",
      "durationSeconds": 2520,
      "uuid": "bb085e5d-5160-4a63-9ac4-152248046c39",
      "language": "ru",
      "version": 3,
      "participants": [
        { "userId": 7, "name": "Иван Петров", "workPosition": "Руководитель проекта", "talkedSeconds": 600 }
      ],
      "outcomes": ["transcription", "overview", "summary", "insights", "evaluation"],
      "createdAt": "2026-01-15T11:05:00+00:00",
      "tracks": [
        { "trackId": 100, "type": "mixed_audio", "duration": 2520, "fileName": "call_12345.wav", "mimeType": "audio/wav", "url": "https://example.bitrix24.ru/disk/call_12345.wav", "dateCreate": "2026-01-15T11:00:00+00:00" }
      ],
      "transcription": {
        "language": "ru",
        "segments": [
          { "userId": 7, "userName": "Иван Петров", "start": 12, "end": 25, "text": "Давайте зафиксируем объём спринта. Что берём в работу?" },
          { "userId": 42, "userName": "Мария Иванова", "start": 26, "end": 48, "text": "Предлагаю оставить только импорт каталога, остальное не успеем." },
          { "userId": 7, "userName": "Иван Петров", "start": 49, "end": 70, "text": "Согласен. Тогда прототип показываем в пятницу." }
        ]
      },
      "overview": {
        "topic": "Планирование спринта",
        "detailedTakeaways": "Команда сократила объём спринта до импорта каталога и договорилась показать прототип в пятницу.",
        "meetingType": {
          "typeTag": "planning",
          "title": "Планирование",
          "explanation": "Участники распределяли задачи и сроки на ближайшую итерацию."
        },
        "agenda": {
          "explanation": "Определить объём спринта и сроки демонстрации.",
          "quote": "Давайте зафиксируем объём спринта."
        },
        "agreements": [
          { "agreement": "В спринт берём только импорт каталога", "quote": "Предлагаю оставить только импорт каталога, остальное не успеем." }
        ],
        "actionItems": [
          { "actionItem": "Подготовить прототип к пятнице", "quote": "Тогда прототип показываем в пятницу." }
        ],
        "meetings": [
          { "meeting": "Демонстрация прототипа в пятницу", "quote": "Тогда прототип показываем в пятницу." }
        ]
      },
      "summary": {
        "segments": [
          { "start": 0, "end": 600, "title": "Объём спринта", "summary": "Обсудили, что успеет команда, и сократили набор задач до импорта каталога." },
          { "start": 601, "end": 2520, "title": "Сроки и демонстрация", "summary": "Договорились показать прототип в пятницу и вернуться к остальным задачам в следующем спринте." }
        ]
      },
      "insights": {
        "speakerEvaluationAvailable": true,
        "speakerAnalysis": [
          {
            "userId": 42,
            "detailedInsight": "Участник предложил сократить объём и обосновал это оценкой сроков.",
            "efficiencyValue": 82,
            "evaluationCriteria": "Конструктивность предложений",
            "talkPercentage": 66,
            "duration": 1200,
            "durationFormat": "20:00"
          },
          {
            "userId": 7,
            "detailedInsight": "Участник вёл встречу и зафиксировал договорённости.",
            "efficiencyValue": 74,
            "evaluationCriteria": "Управление обсуждением",
            "talkPercentage": 34,
            "duration": 600,
            "durationFormat": "10:00"
          }
        ],
        "meetingStrengths": [
          { "strengthTitle": "Чёткий итог", "strengthExplanation": "Встреча завершилась зафиксированным решением и сроком." }
        ],
        "meetingWeaknesses": [
          { "weaknessTitle": "Неравное участие", "weaknessExplanation": "Две трети времени говорил один участник." }
        ],
        "speechStyleInfluence": "Спокойный темп речи помог быстро прийти к решению.",
        "engagementLevel": "Высокая вовлечённость обоих участников.",
        "areasOfResponsibility": "Импорт каталога закреплён за Марией Ивановой.",
        "finalRecommendations": "Заранее рассылать повестку, чтобы сократить обсуждение объёма."
      },
      "evaluation": {
        "efficiencyValue": 75,
        "calendar": { "overhead": false },
        "criteria": {
          "agenda_defined": {
            "value": true,
            "criteria": "Повестка обозначена в начале встречи",
            "title": "Повестка",
            "thoughts": "Ведущий сформулировал цель первой репликой."
          },
          "decisions_made": {
            "value": true,
            "criteria": "Приняты решения по обсуждаемым вопросам",
            "title": "Решения",
            "thoughts": "Объём спринта и срок демонстрации зафиксированы."
          },
          "all_participants_involved": {
            "value": false,
            "criteria": "Все участники вовлечены в обсуждение",
            "title": "Вовлечённость",
            "thoughts": "Распределение реплик — 66 на 34 процента."
          }
        }
      }
    }
  }
}

Ключи в evaluation.criteria — коды критериев. Их набор зависит от типа встречи, поэтому обходите карту по ключам, а не по фиксированному списку.

Пример ответа при ошибке

422 — звонок не найден или его Follow-up недоступен:

JSON
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Нет доступа к данным Follow-up"
  }
}

Текст error.message приходит от Битрикс24, поэтому его формулировка и язык зависят от языка портала. Ветвитесь по error.code, а не по тексту сообщения.

Ошибки

HTTP Код Описание
400 INVALID_PARAMS callId в пути — не положительное целое число. Проверяется до обращения к Битрикс24
400 INVALID_PARAMS Значение query-параметра вне списка допустимых — например mentionFormat. Если Битрикс24 отклонил значение по полю, ответ дополнительно содержит массив error.validation с именем поля
401 MISSING_API_KEY Не передан заголовок X-Api-Key
401 TOKEN_MISSING У ключа нет токенов портала. Ключ OAuth-приложения требует заголовок Authorization: Bearer
403 SCOPE_DENIED У ключа нет скоупа call
403 BITRIX_ACCESS_DENIED Битрикс24 отказал в доступе: у веб-хука ключа нет права call на стороне портала. Переподключите ключ с нужным правом
422 METHOD_NOT_YET_AVAILABLE Обновление call 26.600.0 на портале ещё не выпущено. Ответ содержит поле error.release с целевой версией
422 BITRIX_ERROR Запрос отклонён Битрикс24. Звонка с таким callId нет либо к его Follow-up нет доступа — сообщение «Нет доступа к данным Follow-up». Причина конкретного отказа — в error.message
429 RATE_LIMITED Превышена частота запросов на стороне Битрикс24
429 QUEUE_OVERFLOW, QUEUE_TIMEOUT Очередь запросов портала переполнена или запрос не дождался очереди. Заголовок Retry-After подсказывает задержку перед повтором
503 BITRIX_TIMEOUT Битрикс24 принял запрос, но не ответил за 15 секунд. Для чтения повтор безопасен
502 BITRIX_UNAVAILABLE Битрикс24 недоступен

Полный список общих ошибок API — Ошибки.

Известные особенности

Отличить несуществующий звонок от отказа в доступе по ответу нельзя. Оба случая приходят одинаковым ответом. Список Follow-up тоже не даёт ответа: в него попадают только звонки с готовым Follow-up и только те, к которым у сотрудника есть доступ, — отсутствие звонка в списке не означает, что звонка нет.

Звонки без AI-обработки. Если звонок завершён, но Follow-up по нему не сформирован, метод возвращает объект с метаданными: AI-блоки приходят как null, а outcomes — пустым массивом.

Разбор участников доступен не на каждом портале. Если на портале он недоступен, блок insights приходит с speakerEvaluationAvailable: false и пустым разбором участников. Это не ошибка запроса — структура ответа не меняется.

Доступ ограничен правами сотрудника. Follow-up доступен тому, кто участвовал в звонке или состоит в связанном чате — в том числе если его добавили в чат уже после разговора. Администратор портала видит Follow-up любого звонка портала.

Смотрите также