[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-calls\u002Ffollowup\u002Fget":3,"docs-tabs-calls\u002Ffollowup\u002Fget":6},{"content":4,"lastmod":5},"## Follow-up по одному звонку\n\n> ⚠️ **Метод выходит в обновлении `call 26.600.0` и доступен пока не на всех порталах Битрикс24.** Если обновление на ваш портал ещё не пришло, API вернёт `422 METHOD_NOT_YET_AVAILABLE` — это признак того, что метод на портале ещё не выпущен, а не ошибка интеграции.\n\n`GET \u002Fv1\u002Fcalls\u002Ffollowups\u002F:callId`\n\nВозвращает AI Follow-up одного завершённого звонка.\n\n## Параметры\n\n| Параметр | Тип | Обяз. | Описание |\n|----------|-----|:-----:|---------|\n| `callId` (path) | integer | да | Идентификатор звонка. Положительное целое. Где взять — [`POST \u002Fv1\u002Fcalls\u002Ffollowups\u002Flist`](.\u002Flist.md) |\n| `select` (query) | string[] | нет | Какие поля вернуть. Передаётся повторяющимся параметром или списком через запятую. Словарь значений общий со списком — раздел «Поле select» страницы [Список Follow-up](.\u002Flist.md) |\n| `mentionFormat` (query) | string | нет | Формат `@`-упоминаний в текстовых полях: `bb`, `html` или `none`. По умолчанию — `bb` |\n\n## Поле select\n\n| Значение `select` | Что в ответе |\n|---|---|\n| Не указан | Полный объект Follow-up. Присутствуют все поля, отсутствующие данные приходят как `null` |\n| Пустой массив | Только базовые метаданные: `callId`, `callType`, `initiatorId`, `startDate`, `endDate`, `durationSeconds` |\n| Список полей | Только перечисленные поля и всегда `callId`. Запрошенное, но незаполненное поле приходит как `null` |\n\n## Примеры\n\nЗапрос без `select` — возвращается весь Follow-up целиком. `mentionFormat: none` убирает разметку упоминаний, поэтому текст готов к передаче в нейросеть или к сохранению в задачу. Чтобы забрать только часть блоков, добавьте `select` — например `?select=overview.actionItems&select=evaluation.efficiencyValue`.\n\n### curl — личный ключ\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fcalls\u002Ffollowups\u002F12345?mentionFormat=none\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fcalls\u002Ffollowups\u002F12345?mentionFormat=none\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst params = new URLSearchParams({ mentionFormat: 'none' })\n\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fcalls\u002Ffollowups\u002F12345?${params}`, {\n  headers: { 'X-Api-Key': 'YOUR_API_KEY' },\n})\n\nconst body = await res.json()\n\nif (!body.success) {\n  \u002F\u002F Ошибку разбираем явно: иначе на 403 или 422 код упадёт на обращении к data\n  throw new Error(`${body.error.code}: ${body.error.message}`)\n}\n\nconst { data } = body\nconst call = data.item\n\n\u002F\u002F Готовые AI-блоки перечислены в outcomes, неготовые приходят как null\nconsole.log(call.outcomes, `${call.durationSeconds} сек`)\nconsole.log(call.overview?.topic ?? 'обзор ещё не сформирован')\n\nfor (const item of call.overview?.actionItems ?? []) {\n  console.log('задача:', item.actionItem, '— цитата:', item.quote)\n}\n\n\u002F\u002F speakerAnalysis отсутствует, если разбор участников на портале недоступен\nfor (const speaker of call.insights?.speakerAnalysis ?? []) {\n  console.log(`участник ${speaker.userId}: ${speaker.talkPercentage}% времени, оценка ${speaker.efficiencyValue}`)\n}\n\n\u002F\u002F Критерии — карта, ключи зависят от типа встречи: обходим по ключам\nfor (const [code, criterion] of Object.entries(call.evaluation?.criteria ?? {})) {\n  console.log(code, criterion.value ? 'выполнен' : 'не выполнен', '—', criterion.thoughts)\n}\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst params = new URLSearchParams({ mentionFormat: 'none' })\n\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fcalls\u002Ffollowups\u002F12345?${params}`, {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst body = await res.json()\n\nif (!body.success) {\n  \u002F\u002F Ошибку разбираем явно: иначе на 403 или 422 код упадёт на обращении к data\n  throw new Error(`${body.error.code}: ${body.error.message}`)\n}\n\nconst { data } = body\nconsole.log(data.item)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data.item` | object | Follow-up звонка. Поля — в таблице ниже |\n\nПоля объекта `item`:\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `item.callId` | number | Идентификатор звонка |\n| `item.callType` | number | Вид звонка: `1` — мгновенный, `2` — конференция, `3` — большая комната |\n| `item.initiatorId` | number | Инициатор звонка. Карточка сотрудника — `GET \u002Fv1\u002Fusers\u002F:id` |\n| `item.startDate` | string | Начало звонка, ISO 8601 в UTC |\n| `item.endDate` | string \\| null | Окончание звонка, ISO 8601 в UTC |\n| `item.durationSeconds` | number | Длительность звонка в секундах |\n| `item.uuid` | string | Идентификатор сессии звонка |\n| `item.language` | string | Код языка транскрипции |\n| `item.version` | number | Версия схемы AI-данных |\n| `item.participants` | object[] | Участники звонка |\n| `item.outcomes` | string[] | Готовые AI-блоки этого звонка |\n| `item.createdAt` | string | Время последней AI-записи |\n| `item.tracks` | object[] | Записи звонка |\n| `item.transcription` | object \\| null | Транскрипция разговора |\n| `item.overview` | object \\| null | Обзор встречи |\n| `item.summary` | object \\| null | Краткое изложение по фрагментам |\n| `item.evaluation` | object \\| null | Оценка эффективности встречи |\n| `item.insights` | object \\| null | Аналитические выводы и разбор участников |\n\n### Участники — `participants[]`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `userId` | number | Идентификатор сотрудника |\n| `name` | string | Имя сотрудника |\n| `avatar` | string | Ссылка на аватар |\n| `workPosition` | string | Должность |\n| `talkedSeconds` | number | Сколько секунд участник говорил |\n\n### Записи звонка — `tracks[]`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `trackId` | number | Идентификатор записи |\n| `type` | string | Вид дорожки, например `mixed_audio` |\n| `duration` | number | Длительность записи в секундах |\n| `fileName` | string | Имя файла |\n| `mimeType` | string | MIME-тип файла |\n| `url` | string | Ссылка на скачивание |\n| `dateCreate` | string | Когда запись создана, ISO 8601 |\n\n### Транскрипция — `transcription`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `language` | string | Код языка расшифровки |\n| `segments[]` | object[] | Реплики в хронологическом порядке |\n| `segments[].userId` | number | Кто говорит |\n| `segments[].userName` | string | Имя говорящего |\n| `segments[].start` | number | Начало реплики, секунды от начала звонка |\n| `segments[].end` | number | Конец реплики, секунды от начала звонка |\n| `segments[].text` | string | Текст реплики |\n\n### Обзор встречи — `overview`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `topic` | string | Тема встречи |\n| `detailedTakeaways` | string | Развёрнутые выводы |\n| `meetingType` | object | Тип встречи: `typeTag` — код, `title` — название, `explanation` — обоснование |\n| `agenda` | object | Повестка: `explanation` — формулировка, `quote` — цитата из разговора |\n| `agreements[]` | object[] | Договорённости: `agreement` — формулировка, `quote` — цитата |\n| `actionItems[]` | object[] | Задачи: `actionItem` — формулировка, `quote` — цитата |\n| `meetings[]` | object[] | Назначенные встречи: `meeting` — формулировка, `quote` — цитата |\n\n### Краткое изложение — `summary`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `segments[]` | object[] | Фрагменты разговора |\n| `segments[].start` | number | Начало фрагмента, секунды |\n| `segments[].end` | number | Конец фрагмента, секунды |\n| `segments[].title` | string | Заголовок фрагмента |\n| `segments[].summary` | string | Изложение фрагмента |\n\n### Аналитические выводы — `insights`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `speakerEvaluationAvailable` | boolean | Доступен ли разбор участников на портале |\n| `speakerAnalysis[]` | object[] | Разбор участников, по убыванию `talkPercentage` |\n| `speakerAnalysis[].userId` | number | Идентификатор сотрудника. Карточка — `GET \u002Fv1\u002Fusers\u002F:id` |\n| `speakerAnalysis[].detailedInsight` | string | Вывод по участнику |\n| `speakerAnalysis[].efficiencyValue` | number | Оценка эффективности участника, от 0 до 100 |\n| `speakerAnalysis[].evaluationCriteria` | string | Критерий, по которому дана оценка |\n| `speakerAnalysis[].talkPercentage` | number | Доля времени, которую участник говорил, в процентах |\n| `speakerAnalysis[].duration` | number | Сколько секунд участник говорил |\n| `speakerAnalysis[].durationFormat` | string | То же время в виде `ММ:СС` |\n| `meetingStrengths[]` | object[] | Сильные стороны: `strengthTitle` и `strengthExplanation` |\n| `meetingWeaknesses[]` | object[] | Слабые стороны: `weaknessTitle` и `weaknessExplanation` |\n| `speechStyleInfluence` | string | Как манера речи повлияла на встречу |\n| `engagementLevel` | string | Вовлечённость участников |\n| `areasOfResponsibility` | string | Кто за что отвечает по итогам |\n| `finalRecommendations` | string | Рекомендации к следующей встрече |\n\n### Оценка эффективности — `evaluation`\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `efficiencyValue` | number | Общая эффективность встречи, от 0 до 100 |\n| `calendar.overhead` | boolean | Была ли встреча избыточной по времени |\n| `criteria` | object | Карта критериев. Ключ — код критерия, значение — объект с полями ниже |\n| `criteria.\u003Cкод>.value` | boolean | Выполнен ли критерий |\n| `criteria.\u003Cкод>.title` | string | Название критерия |\n| `criteria.\u003Cкод>.criteria` | string | Формулировка критерия |\n| `criteria.\u003Cкод>.thoughts` | string | Обоснование оценки |\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"item\": {\n      \"callId\": 12345,\n      \"callType\": 1,\n      \"initiatorId\": 7,\n      \"startDate\": \"2026-01-15T10:00:00+00:00\",\n      \"endDate\": \"2026-01-15T10:42:00+00:00\",\n      \"durationSeconds\": 2520,\n      \"uuid\": \"bb085e5d-5160-4a63-9ac4-152248046c39\",\n      \"language\": \"ru\",\n      \"version\": 3,\n      \"participants\": [\n        { \"userId\": 7, \"name\": \"Иван Петров\", \"workPosition\": \"Руководитель проекта\", \"talkedSeconds\": 600 }\n      ],\n      \"outcomes\": [\"transcription\", \"overview\", \"summary\", \"insights\", \"evaluation\"],\n      \"createdAt\": \"2026-01-15T11:05:00+00:00\",\n      \"tracks\": [\n        { \"trackId\": 100, \"type\": \"mixed_audio\", \"duration\": 2520, \"fileName\": \"call_12345.wav\", \"mimeType\": \"audio\u002Fwav\", \"url\": \"https:\u002F\u002Fexample.bitrix24.ru\u002Fdisk\u002Fcall_12345.wav\", \"dateCreate\": \"2026-01-15T11:00:00+00:00\" }\n      ],\n      \"transcription\": {\n        \"language\": \"ru\",\n        \"segments\": [\n          { \"userId\": 7, \"userName\": \"Иван Петров\", \"start\": 12, \"end\": 25, \"text\": \"Давайте зафиксируем объём спринта. Что берём в работу?\" },\n          { \"userId\": 42, \"userName\": \"Мария Иванова\", \"start\": 26, \"end\": 48, \"text\": \"Предлагаю оставить только импорт каталога, остальное не успеем.\" },\n          { \"userId\": 7, \"userName\": \"Иван Петров\", \"start\": 49, \"end\": 70, \"text\": \"Согласен. Тогда прототип показываем в пятницу.\" }\n        ]\n      },\n      \"overview\": {\n        \"topic\": \"Планирование спринта\",\n        \"detailedTakeaways\": \"Команда сократила объём спринта до импорта каталога и договорилась показать прототип в пятницу.\",\n        \"meetingType\": {\n          \"typeTag\": \"planning\",\n          \"title\": \"Планирование\",\n          \"explanation\": \"Участники распределяли задачи и сроки на ближайшую итерацию.\"\n        },\n        \"agenda\": {\n          \"explanation\": \"Определить объём спринта и сроки демонстрации.\",\n          \"quote\": \"Давайте зафиксируем объём спринта.\"\n        },\n        \"agreements\": [\n          { \"agreement\": \"В спринт берём только импорт каталога\", \"quote\": \"Предлагаю оставить только импорт каталога, остальное не успеем.\" }\n        ],\n        \"actionItems\": [\n          { \"actionItem\": \"Подготовить прототип к пятнице\", \"quote\": \"Тогда прототип показываем в пятницу.\" }\n        ],\n        \"meetings\": [\n          { \"meeting\": \"Демонстрация прототипа в пятницу\", \"quote\": \"Тогда прототип показываем в пятницу.\" }\n        ]\n      },\n      \"summary\": {\n        \"segments\": [\n          { \"start\": 0, \"end\": 600, \"title\": \"Объём спринта\", \"summary\": \"Обсудили, что успеет команда, и сократили набор задач до импорта каталога.\" },\n          { \"start\": 601, \"end\": 2520, \"title\": \"Сроки и демонстрация\", \"summary\": \"Договорились показать прототип в пятницу и вернуться к остальным задачам в следующем спринте.\" }\n        ]\n      },\n      \"insights\": {\n        \"speakerEvaluationAvailable\": true,\n        \"speakerAnalysis\": [\n          {\n            \"userId\": 42,\n            \"detailedInsight\": \"Участник предложил сократить объём и обосновал это оценкой сроков.\",\n            \"efficiencyValue\": 82,\n            \"evaluationCriteria\": \"Конструктивность предложений\",\n            \"talkPercentage\": 66,\n            \"duration\": 1200,\n            \"durationFormat\": \"20:00\"\n          },\n          {\n            \"userId\": 7,\n            \"detailedInsight\": \"Участник вёл встречу и зафиксировал договорённости.\",\n            \"efficiencyValue\": 74,\n            \"evaluationCriteria\": \"Управление обсуждением\",\n            \"talkPercentage\": 34,\n            \"duration\": 600,\n            \"durationFormat\": \"10:00\"\n          }\n        ],\n        \"meetingStrengths\": [\n          { \"strengthTitle\": \"Чёткий итог\", \"strengthExplanation\": \"Встреча завершилась зафиксированным решением и сроком.\" }\n        ],\n        \"meetingWeaknesses\": [\n          { \"weaknessTitle\": \"Неравное участие\", \"weaknessExplanation\": \"Две трети времени говорил один участник.\" }\n        ],\n        \"speechStyleInfluence\": \"Спокойный темп речи помог быстро прийти к решению.\",\n        \"engagementLevel\": \"Высокая вовлечённость обоих участников.\",\n        \"areasOfResponsibility\": \"Импорт каталога закреплён за Марией Ивановой.\",\n        \"finalRecommendations\": \"Заранее рассылать повестку, чтобы сократить обсуждение объёма.\"\n      },\n      \"evaluation\": {\n        \"efficiencyValue\": 75,\n        \"calendar\": { \"overhead\": false },\n        \"criteria\": {\n          \"agenda_defined\": {\n            \"value\": true,\n            \"criteria\": \"Повестка обозначена в начале встречи\",\n            \"title\": \"Повестка\",\n            \"thoughts\": \"Ведущий сформулировал цель первой репликой.\"\n          },\n          \"decisions_made\": {\n            \"value\": true,\n            \"criteria\": \"Приняты решения по обсуждаемым вопросам\",\n            \"title\": \"Решения\",\n            \"thoughts\": \"Объём спринта и срок демонстрации зафиксированы.\"\n          },\n          \"all_participants_involved\": {\n            \"value\": false,\n            \"criteria\": \"Все участники вовлечены в обсуждение\",\n            \"title\": \"Вовлечённость\",\n            \"thoughts\": \"Распределение реплик — 66 на 34 процента.\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nКлючи в `evaluation.criteria` — коды критериев. Их набор зависит от типа встречи, поэтому обходите карту по ключам, а не по фиксированному списку.\n\n## Пример ответа при ошибке\n\n422 — звонок не найден или его Follow-up недоступен:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"BITRIX_ERROR\",\n    \"message\": \"Нет доступа к данным Follow-up\"\n  }\n}\n```\n\nТекст `error.message` приходит от Битрикс24, поэтому его формулировка и язык зависят от языка портала. Ветвитесь по `error.code`, а не по тексту сообщения.\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 400 | `INVALID_PARAMS` | `callId` в пути — не положительное целое число. Проверяется до обращения к Битрикс24 |\n| 400 | `INVALID_PARAMS` | Значение query-параметра вне списка допустимых — например `mentionFormat`. Если Битрикс24 отклонил значение по полю, ответ дополнительно содержит массив `error.validation` с именем поля |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `TOKEN_MISSING` | У ключа нет токенов портала. Ключ OAuth-приложения требует заголовок `Authorization: Bearer` |\n| 403 | `SCOPE_DENIED` | У ключа нет скоупа `call` |\n| 403 | `BITRIX_ACCESS_DENIED` | Битрикс24 отказал в доступе: у веб-хука ключа нет права `call` на стороне портала. Переподключите ключ с нужным правом |\n| 422 | `METHOD_NOT_YET_AVAILABLE` | Обновление `call 26.600.0` на портале ещё не выпущено. Ответ содержит поле `error.release` с целевой версией |\n| 422 | `BITRIX_ERROR` | Запрос отклонён Битрикс24. Звонка с таким `callId` нет либо к его Follow-up нет доступа — сообщение «Нет доступа к данным Follow-up». Причина конкретного отказа — в `error.message` |\n| 429 | `RATE_LIMITED` | Превышена частота запросов на стороне Битрикс24 |\n| 429 | `QUEUE_OVERFLOW`, `QUEUE_TIMEOUT` | Очередь запросов портала переполнена или запрос не дождался очереди. Заголовок `Retry-After` подсказывает задержку перед повтором |\n| 503 | `BITRIX_TIMEOUT` | Битрикс24 принял запрос, но не ответил за 15 секунд. Для чтения повтор безопасен |\n| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 недоступен |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Отличить несуществующий звонок от отказа в доступе по ответу нельзя.** Оба случая приходят одинаковым ответом. [Список Follow-up](.\u002Flist.md) тоже не даёт ответа: в него попадают только звонки с готовым Follow-up и только те, к которым у сотрудника есть доступ, — отсутствие звонка в списке не означает, что звонка нет.\n\n**Звонки без AI-обработки.** Если звонок завершён, но Follow-up по нему не сформирован, метод возвращает объект с метаданными: AI-блоки приходят как `null`, а `outcomes` — пустым массивом.\n\n**Разбор участников доступен не на каждом портале.** Если на портале он недоступен, блок `insights` приходит с `speakerEvaluationAvailable: false` и пустым разбором участников. Это не ошибка запроса — структура ответа не меняется.\n\n**Доступ ограничен правами сотрудника.** Follow-up доступен тому, кто участвовал в звонке или состоит в связанном чате — в том числе если его добавили в чат уже после разговора. Администратор портала видит Follow-up любого звонка портала.\n\n## Смотрите также\n\n- [Список Follow-up](\u002Fdocs\u002Fcalls\u002Ffollowup\u002Flist)\n- [Follow-up звонков](\u002Fdocs\u002Fcalls\u002Ffollowup)\n- [Звонки](\u002Fdocs\u002Fcalls)\n- [Ошибки](\u002Fdocs\u002Ferrors)\n","2026-07-13",{}]