Для 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 — личный ключ
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-приложение
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 — личный ключ
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-приложение
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.
{
"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 — карточка изменилась с момента чтения:
{
"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 через проверку на наличие.