For AI agents: markdown of this page — /docs-content-en/performan/manager-reviews.md documentation index — /llms.txt

Manager review cards

GET /v1/performan/review/manager/reviews

Returns the manager-stage cards of a campaign where the key owner is the reviewer: answers, status, final rate and scale. The card id from the response is the relationId of a write.

Parameters

Parameter Type Required Default Description
campaignId (query) number yes Campaign id. The campaign list — GET /v1/performan/review/campaigns
revieweeUserId (query) number no Narrow the listing to one reviewed employee. The employee list — GET /v1/users
limit (query) number no 50 Records per page, 200 at most
afterCursorId (query) number no The next-page cursor. The value comes from meta.nextCursor.id of the previous response. The first request omits it

Examples

curl — personal key

Terminal
curl "https://vibecode.bitrix24.com/v1/performan/review/manager/reviews?campaignId=1&revieweeUserId=42" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/performan/review/manager/reviews?campaignId=1&revieweeUserId=42" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/performan/review/manager/reviews?campaignId=1&revieweeUserId=42', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const body = await res.json()

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

for (const card of body.data) {
  // The card id is the relationId in the write body
  console.log(card.id, card.revieweeUserName, card.status, card.rate)
}

console.log(body.meta.nextCursor)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/performan/review/manager/reviews?campaignId=1&revieweeUserId=42', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const body = await res.json()

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

console.log(body.data, body.meta.nextCursor)

Response fields

Field Type Description
success boolean Always true on success
data array The manager review card array
data[].id number Card id. It is also the relationId in the body of a write — the method address does not carry it
data[].campaignId number The card's campaign. The list — GET /v1/performan/review/campaigns
data[].campaignStageId number The campaign stage the card belongs to
data[].stageType string Stage type. For this method — managersReview
data[].revieweeUserId number The employee being reviewed. Employee card — GET /v1/users/:id
data[].revieweeUserName string Name of the employee being reviewed
data[].reviewerUserId number The reviewing employee. On the manager stage it equals managerUserId
data[].reviewerUserName string Name of the reviewing employee
data[].managerUserId number The reviewee's manager. Employee card — GET /v1/users/:id
data[].managerUserName string Manager name
data[].status string Card state: new — not filled, completed — finished, rejected — rejected, published — published
data[].rate number The final rate from the rating question. 0 — no rate set
data[].comment string Card comment
data[].answers array Answers to the stage questions. On an unfilled card the array is empty
data[].answers[].questionId number Question id. The question list — GET /v1/performan/review/manager/questions
data[].answers[].questionTitle string Question wording
data[].answers[].questionDescription string Question note
data[].answers[].questionType string Question type as a string: 1 — single choice, 2 — multiple choice, 3 — text answer
data[].answers[].questionTypeLabel string Question type name in the portal language
data[].answers[].isRating boolean Whether the answer forms the card's final rate
data[].answers[].answerText string Answer text. Empty for a choice question
data[].answers[].selectedOptions array The chosen options. Empty for a text question
data[].answers[].selectedOptions[].id number Option id
data[].answers[].selectedOptions[].text string Option text
data[].answers[].selectedOptions[].value number Numeric option value, rate is computed from it
data[].ratingScale array The rating scale of the stage
data[].ratingScale[].value number Scale value
data[].ratingScale[].label string Value caption
meta.nextCursor object | null The next-page cursor. null — no more records
meta.nextCursor.id number The value for the afterCursorId parameter of the next request

Response example

A finished card: the text answers and the rating question are filled, and rate is derived from the value of the chosen option.

JSON
{
  "success": true,
  "data": [
    {
      "id": 4,
      "campaignId": 1,
      "campaignStageId": 5,
      "stageType": "managersReview",
      "revieweeUserId": 42,
      "revieweeUserName": "Mary Jones",
      "reviewerUserId": 7,
      "reviewerUserName": "John Smith",
      "managerUserId": 7,
      "managerUserName": "John Smith",
      "status": "completed",
      "rate": 4,
      "comment": "",
      "answers": [
        {
          "questionId": 15,
          "questionTitle": "Key results and goal delivery",
          "questionDescription": "",
          "questionType": "3",
          "questionTypeLabel": "Text answer",
          "isRating": false,
          "answerText": "Met the quarterly goals",
          "selectedOptions": []
        },
        {
          "questionId": 21,
          "questionTitle": "Final rate",
          "questionDescription": "",
          "questionType": "1",
          "questionTypeLabel": "Single choice",
          "isRating": true,
          "answerText": "",
          "selectedOptions": [
            { "id": 18, "text": "Above expectations", "value": 4 }
          ]
        }
      ],
      "ratingScale": [
        { "value": 1, "label": "Well below expectations" },
        { "value": 2, "label": "Below expectations" },
        { "value": 3, "label": "Meets expectations" },
        { "value": 4, "label": "Above expectations" },
        { "value": 5, "label": "Well above expectations" }
      ]
    }
  ],
  "meta": { "nextCursor": null }
}

Error response example

400 — a required parameter was not sent:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "campaignId is required and must be a positive integer"
  }
}

Errors

HTTP Code Description
400 INVALID_PARAMS campaignId was not sent, or the value of campaignId, revieweeUserId or afterCursorId is not a positive integer, or limit is outside the 1–200 range
401 MISSING_API_KEY The X-Api-Key header was not sent
401 TOKEN_MISSING The key has no portal tokens. An OAuth application key requires the Authorization: Bearer header
403 SCOPE_DENIED The key has no performan scope
404 ROUTE_NOT_FOUND The Performance Review section is not enabled for the account. The answer is indistinguishable from the answer to any address that does not exist
404 ENTITY_NOT_FOUND The section is enabled, but the account has no Performance Review module: Bitrix24 answers that the performan.review.* method was not found
409 PERFORMAN_SCOPE_JUST_GRANTED A Cowork key was granted the performan scope by this very request. Repeat it and it goes through
403 BITRIX_ACCESS_DENIED Bitrix24 denied access. The permissions the key uses to reach the portal do not include performan
422 BITRIX_ERROR Bitrix24 rejected the request. The cause is in error.message, the machine code from Bitrix24 in error.b24Code
429 RATE_LIMITED The request rate on the Bitrix24 side was exceeded
429 QUEUE_OVERFLOW, QUEUE_TIMEOUT The portal request queue is full or the request did not get through the queue in time. The Retry-After header suggests the delay
503 BITRIX_TIMEOUT Bitrix24 accepted the request but did not answer in time. A read is safe to retry
502 BITRIX_UNAVAILABLE Bitrix24 is unavailable

The full list of common API errors — Errors.

Known specifics

The listing is limited to the reviewer role. The method returns the cards where the key owner is recorded in reviewerUserId. The reviews given to them do not appear. An empty data array means there is nobody for them to review in this campaign.

The reviewee filter does not check that the employee exists. A revieweeUserId for which the key owner has no card gives 200 with an empty data, not a refusal.

The method does not return the card state hash. The expectedStateHash value for the optimistic lock comes only in a write response, so the first POST /v1/performan/review/manager/answers on a card goes without it.

A limit outside the 1–200 range is refused. The answer is 400 INVALID_PARAMS and the request never reaches Bitrix24; ask for a page of 200 records with an explicit limit=200.

See also