Для AI-агентов: markdown этой страницы — /docs-content/performan/manager-answer.md индекс документации — /llms.txt

Ответ менеджера

POST /v1/performan/review/manager/answers

Сохраняет ответы менеджера по карточке ревью. По умолчанию это черновик — статус карточки остаётся прежним. Поле isAutosave со значением false завершает оценку, и отменить это нельзя.

Поля запроса (body)

Параметров в пути и в строке запроса у метода нет — карточку называет поле тела.

Поле Тип Обяз. Описание
relationId number да Идентификатор карточки менеджерского ревью. Берётся из поля id ответа GET /v1/performan/review/manager/reviews
answers array нет Ответы по вопросам этапа. Перечисляйте все ответы, которые должны остаться на карточке
answers[].questionId number да Идентификатор вопроса. Список — GET /v1/performan/review/manager/questions
answers[].answerText string нет Текст ответа для вопроса с типом 3
answers[].selectedOptions number[] нет Идентификаторы выбранных вариантов для вопроса с типом 1 или 2. Ограничение на их получение описано в «Известных особенностях»
answers[].selectedOptionsText object нет Дополнительный текст к выбранным вариантам. Ключ — идентификатор варианта, значение — строка
isAutosave boolean нет true — сохранить черновик, статус карточки не меняется. false — завершить оценку. По умолчанию true
expectedStateHash string нет Значение stateHash из ответа на предыдущую запись по этой карточке. При расхождении запрос отклоняется кодом 409

Кроме relationId обязательных полей нет. Поле answers доходит до Битрикс24 при каждой записи — тело без этого поля отправляет пустой набор ответов, поэтому перечисляйте в answers все ответы, которые должны остаться на карточке. Поля, не перечисленные в таблице, отбрасываются и до Битрикс24 не доходят.

Примеры

Черновик двух текстовых ответов с оптимистичной блокировкой по хэшу состояния.

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

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/performan/review/manager/answers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "relationId": 4,
    "answers": [
      { "questionId": 15, "answerText": "Закрыл цели квартала" },
      { "questionId": 16, "answerText": "Сильная инженерная база" }
    ],
    "isAutosave": true,
    "expectedStateHash": "23fb2c21af87e3f692789a9082d89b89be1333492c40ddb13245cb2d9d6ec790"
  }'

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

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/performan/review/manager/answers \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "relationId": 4,
    "answers": [
      { "questionId": 15, "answerText": "Закрыл цели квартала" },
      { "questionId": 16, "answerText": "Сильная инженерная база" }
    ],
    "isAutosave": true,
    "expectedStateHash": "23fb2c21af87e3f692789a9082d89b89be1333492c40ddb13245cb2d9d6ec790"
  }'

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

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/performan/review/manager/answers', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    relationId: 4,
    answers: [
      { questionId: 15, answerText: 'Закрыл цели квартала' },
      { questionId: 16, answerText: 'Сильная инженерная база' },
    ],
    isAutosave: true,
    expectedStateHash: '23fb2c21af87e3f692789a9082d89b89be1333492c40ddb13245cb2d9d6ec790',
  }),
})

const body = await res.json()

if (res.status === 409) {
  // Карточку изменили параллельно: перечитать и повторить со свежим хэшем
  throw new Error(body.error.message)
}

if (!body.success) {
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

// Хэш из ответа кладём в expectedStateHash следующей записи по этой карточке
console.log(body.data.status, body.data.stateHash)

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

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/performan/review/manager/answers', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    relationId: 4,
    answers: [
      { questionId: 15, answerText: 'Закрыл цели квартала' },
      { questionId: 16, answerText: 'Сильная инженерная база' },
    ],
    isAutosave: true,
    expectedStateHash: '23fb2c21af87e3f692789a9082d89b89be1333492c40ddb13245cb2d9d6ec790',
  }),
})

const body = await res.json()

if (!body.success) {
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

console.log(body.data.status, body.data.stateHash)

Поля ответа

Поле Тип Описание
success boolean Всегда true при успехе
data object Карточка после записи
data.id number Идентификатор карточки
data.campaignId number Кампания карточки
data.campaignStageId number Этап кампании, к которому относится карточка
data.stageType string Тип этапа. Здесь — managersReview
data.revieweeUserId number Оцениваемый сотрудник. Карточка сотрудника — GET /v1/users/:id
data.revieweeUserName string Имя оцениваемого сотрудника
data.reviewerUserId number Оценивающий сотрудник
data.reviewerUserName string Имя оценивающего сотрудника
data.managerUserId number Руководитель оцениваемого
data.managerUserName string Имя руководителя
data.status string Состояние карточки после записи: new — черновик сохранён, completed — оценка завершена
data.rate number Итоговая оценка. Выводится из значения выбранного варианта рейтингового вопроса
data.comment string Комментарий к карточке
data.answers array Ответы карточки после записи
data.answers[].questionId number Идентификатор вопроса
data.answers[].questionTitle string Формулировка вопроса
data.answers[].questionDescription string Пояснение к вопросу
data.answers[].questionType string Тип вопроса строкой: 1 — одиночный выбор, 2 — множественный выбор, 3 — текстовый ответ
data.answers[].questionTypeLabel string Название типа вопроса на языке портала
data.answers[].isRating boolean Формирует ли ответ итоговую оценку карточки
data.answers[].answerText string Текст ответа
data.answers[].selectedOptions array Выбранные варианты объектами. В запросе то же поле принимает массив чисел
data.answers[].selectedOptions[].id number Идентификатор варианта
data.answers[].selectedOptions[].text string Текст варианта
data.answers[].selectedOptions[].value number Числовое значение варианта
data.ratingScale array Шкала оценки этапа
data.ratingScale[].value number Значение шкалы
data.ratingScale[].label string Подпись значения
data.stateHash string Хэш состояния карточки. Передаётся в поле expectedStateHash следующей записи

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

Черновик сохранён, статус карточки остался new.

JSON
{
  "success": true,
  "data": {
    "id": 4,
    "campaignId": 1,
    "campaignStageId": 5,
    "stageType": "managersReview",
    "revieweeUserId": 42,
    "revieweeUserName": "Мария Иванова",
    "reviewerUserId": 7,
    "reviewerUserName": "Иван Петров",
    "managerUserId": 7,
    "managerUserName": "Иван Петров",
    "status": "new",
    "rate": 0,
    "comment": "",
    "answers": [
      {
        "questionId": 15,
        "questionTitle": "Ключевые результаты и выполнение целей",
        "questionDescription": "",
        "questionType": "3",
        "questionTypeLabel": "Текстовый ответ",
        "isRating": false,
        "answerText": "Закрыл цели квартала",
        "selectedOptions": []
      }
    ],
    "ratingScale": [
      { "value": 1, "label": "Значительно ниже ожиданий" },
      { "value": 2, "label": "Ниже ожиданий" },
      { "value": 3, "label": "Соответствует ожиданиям" },
      { "value": 4, "label": "Выше ожиданий" },
      { "value": 5, "label": "Значительно выше ожиданий" }
    ],
    "stateHash": "23fb2c21af87e3f692789a9082d89b89be1333492c40ddb13245cb2d9d6ec790"
  }
}

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

409 — карточка изменилась с момента чтения:

JSON
{
  "success": false,
  "error": {
    "code": "PERFORMAN_STATE_CONFLICT",
    "message": "The relation changed since your `expectedStateHash` — re-read it and retry with the fresh stateHash"
  }
}

Ошибки

HTTP Код Описание
400 INVALID_PARAMS relationId в теле отсутствует или не является положительным целым числом
400 INVALID_PARAMS Нарушена структура тела: answers не массив, элемент не объект, questionId не положительное целое, selectedOptions не массив идентификаторов, answerText не строка, selectedOptionsText не карта идентификатора в строку, isAutosave не логическое значение, expectedStateHash не строка либо пустая строка, в том числе из одних пробелов. Значение null в expectedStateHash равнозначно отсутствию поля
401 MISSING_API_KEY Не передан заголовок X-Api-Key
401 TOKEN_MISSING У ключа нет токенов портала. Ключ OAuth-приложения требует заголовок Authorization: Bearer
403 SCOPE_DENIED У ключа нет скоупа performan
404 ROUTE_NOT_FOUND Раздел «Перформанс ревью» порталу не включён. Ответ неотличим от ответа на любой несуществующий адрес
404 ENTITY_NOT_FOUND Раздел включён, но модуля «Перформанс ревью» на портале нет: Битрикс24 отвечает «Метод performan.review.* не найден»
403 WRITE_BLOCKED_READONLY_KEY Ключ в режиме только для чтения
403 BITRIX_ACCESS_DENIED Карточка принадлежит другому оценивающему либо карточки с таким relationId не существует. Битрикс24 отвечает на оба случая одинаково
409 PERFORMAN_SCOPE_JUST_GRANTED Ключу Коворка выдан скоуп performan этим же запросом. Повторите запрос — он пройдёт
409 PERFORMAN_STATE_CONFLICT Переданный expectedStateHash не совпадает с текущим состоянием карточки
422 BITRIX_ERROR Битрикс24 отклонил запрос: вопрос не принадлежит этапу карточки, при завершении оценки заполнены не все обязательные ответы. Разбор по полям — в массиве error.validation, машинный код Битрикс24 — в error.b24Code
429 RATE_LIMITED Превышена частота запросов на стороне Битрикс24
429 QUEUE_OVERFLOW, QUEUE_TIMEOUT Очередь запросов портала переполнена или запрос не дождался очереди. Заголовок Retry-After подсказывает задержку
503 BITRIX_TIMEOUT Битрикс24 принял запрос, но не ответил за отведённое время. Перед повтором перечитайте карточку — запись могла примениться
502 BITRIX_UNAVAILABLE Битрикс24 недоступен

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

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

По умолчанию сохраняется черновик, а не завершённая оценка. Запрос без поля isAutosave работает как isAutosave: true: статус карточки не меняется, побочные эффекты завершения не запускаются. Значение false переводит карточку в completed, отправляет уведомление и запускает следующие этапы кампании. Вернуть карточку в состояние черновика через API нельзя.

Ответить на вопрос с выбором варианта через API нельзя. Поле answers[].selectedOptions принимает идентификаторы вариантов, но получить их неоткуда: список вопросов приходит без вариантов, а в карточке в поле answers[].selectedOptions попадают только уже выбранные. Поэтому вызов с isAutosave: false на карточке, где обязательный рейтинговый вопрос не заполнен в интерфейсе Битрикс24, возвращает 422 BITRIX_ERROR с сообщением о незаполненных обязательных полях.

Элемент массива error.validation не всегда содержит поле field. Отказ по конкретному полю приходит с ключами message и field, а отказ на завершении оценки по незаполненным обязательным ответам — только с message. Читайте field через проверку на наличие.

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