## Follow-up for a single call

> ⚠️ **The method ships in the `call 26.600.0` update and is not yet available on all Bitrix24 accounts.** If the update has not reached your Bitrix24 account yet, the API returns `422 METHOD_NOT_YET_AVAILABLE` — this means the method has not been released on the account yet, not an integration error.

`GET /v1/calls/followups/:callId`

Returns the AI Follow-up of a single finished call.

## Parameters

| Parameter | Type | Req. | Description |
|----------|-----|:-----:|---------|
| `callId` (path) | integer | yes | Call identifier. A positive integer. Where to get it — [`POST /v1/calls/followups/list`](./list.md) |
| `select` (query) | string[] | no | Which fields to return. Pass it as a repeated parameter or as a comma-separated list. The set of values is the same as in the list method — see the "Select field" section of [Follow-up list](./list.md) |
| `mentionFormat` (query) | string | no | Format of `@`-mentions in text fields: `bb`, `html` or `none`. Default — `bb` |

## Select field

| `select` value | What comes back |
|---|---|
| Not passed | The full Follow-up object. All fields are present, missing data arrives as `null` |
| Empty array | Base metadata only: `callId`, `callType`, `initiatorId`, `startDate`, `endDate`, `durationSeconds` |
| List of fields | Only the listed fields and always `callId`. A requested but unfilled field arrives as `null` |

## Examples

A request without `select` returns the whole Follow-up. `mentionFormat: none` strips the mention markup, so the text is ready to pass to an AI model or to store in a task. To fetch only some of the blocks, add `select` — for example `?select=overview.actionItems&select=evaluation.efficiencyValue`.

### curl — personal key

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

### curl — OAuth application

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

### JavaScript — personal key

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

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

const body = await res.json()

if (!body.success) {
  // Handle the error explicitly: otherwise on 403 or 422 the code breaks when reading data
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

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

// Ready AI blocks are listed in outcomes, the ones that are not ready arrive as null
console.log(call.outcomes, `${call.durationSeconds} sec`)
console.log(call.overview?.topic ?? 'overview is not built yet')

for (const item of call.overview?.actionItems ?? []) {
  console.log('action item:', item.actionItem, '— quote:', item.quote)
}

// speakerAnalysis is absent if speaker analysis is unavailable on the account
for (const speaker of call.insights?.speakerAnalysis ?? []) {
  console.log(`speaker ${speaker.userId}: ${speaker.talkPercentage}% of the time, score ${speaker.efficiencyValue}`)
}

// Criteria are a map, the keys depend on the meeting type: iterate over the keys
for (const [code, criterion] of Object.entries(call.evaluation?.criteria ?? {})) {
  console.log(code, criterion.value ? 'met' : 'not met', '—', criterion.thoughts)
}
```

### JavaScript — OAuth application

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

const res = await fetch(`https://vibecode.bitrix24.com/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) {
  // Handle the error explicitly: otherwise on 403 or 422 the code breaks when reading data
  throw new Error(`${body.error.code}: ${body.error.message}`)
}

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

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data.item` | object | Call Follow-up. Its fields are in the table below |

Fields of the `item` object:

| Field | Type | Description |
|------|-----|---------|
| `item.callId` | number | Call identifier |
| `item.callType` | number | Call type: `1` — instant, `2` — conference, `3` — large room |
| `item.initiatorId` | number | Call initiator. Employee card — `GET /v1/users/:id` |
| `item.startDate` | string | Call start, ISO 8601 in UTC |
| `item.endDate` | string \| null | Call end, ISO 8601 in UTC |
| `item.durationSeconds` | number | Call duration in seconds |
| `item.uuid` | string | Call session identifier |
| `item.language` | string | Transcription language code |
| `item.version` | number | AI data schema version |
| `item.participants` | object[] | Call participants |
| `item.outcomes` | string[] | Ready AI blocks of this call |
| `item.createdAt` | string | Time of the last AI record |
| `item.tracks` | object[] | Call recordings |
| `item.transcription` | object \| null | Conversation transcript |
| `item.overview` | object \| null | Meeting overview |
| `item.summary` | object \| null | Summary by segments |
| `item.evaluation` | object \| null | Meeting efficiency evaluation |
| `item.insights` | object \| null | Analytical conclusions and speaker analysis |

### Participants — `participants[]`

| Field | Type | Description |
|------|-----|---------|
| `userId` | number | Employee identifier |
| `name` | string | Employee name |
| `avatar` | string | Avatar link |
| `workPosition` | string | Job position |
| `talkedSeconds` | number | How many seconds the participant spoke |

### Call recordings — `tracks[]`

| Field | Type | Description |
|------|-----|---------|
| `trackId` | number | Recording identifier |
| `type` | string | Track type, for example `mixed_audio` |
| `duration` | number | Recording duration in seconds |
| `fileName` | string | File name |
| `mimeType` | string | File MIME type |
| `url` | string | Download link |
| `dateCreate` | string | When the recording was created, ISO 8601 |

### Transcription — `transcription`

| Field | Type | Description |
|------|-----|---------|
| `language` | string | Transcript language code |
| `segments[]` | object[] | Utterances in chronological order |
| `segments[].userId` | number | Who speaks |
| `segments[].userName` | string | Speaker name |
| `segments[].start` | number | Utterance start, seconds from the call start |
| `segments[].end` | number | Utterance end, seconds from the call start |
| `segments[].text` | string | Utterance text |

### Meeting overview — `overview`

| Field | Type | Description |
|------|-----|---------|
| `topic` | string | Meeting topic |
| `detailedTakeaways` | string | Detailed takeaways |
| `meetingType` | object | Meeting type: `typeTag` — code, `title` — name, `explanation` — rationale |
| `agenda` | object | Agenda: `explanation` — wording, `quote` — quote from the conversation |
| `agreements[]` | object[] | Agreements: `agreement` — wording, `quote` — quote |
| `actionItems[]` | object[] | Action items: `actionItem` — wording, `quote` — quote |
| `meetings[]` | object[] | Scheduled meetings: `meeting` — wording, `quote` — quote |

### Summary — `summary`

| Field | Type | Description |
|------|-----|---------|
| `segments[]` | object[] | Conversation segments |
| `segments[].start` | number | Segment start, seconds |
| `segments[].end` | number | Segment end, seconds |
| `segments[].title` | string | Segment title |
| `segments[].summary` | string | Segment summary |

### Insights — `insights`

| Field | Type | Description |
|------|-----|---------|
| `speakerEvaluationAvailable` | boolean | Whether speaker analysis is available on the Bitrix24 account |
| `speakerAnalysis[]` | object[] | Speaker analysis, in descending order of `talkPercentage` |
| `speakerAnalysis[].userId` | number | Employee identifier. Card — `GET /v1/users/:id` |
| `speakerAnalysis[].detailedInsight` | string | Conclusion about the participant |
| `speakerAnalysis[].efficiencyValue` | number | Participant efficiency score, from 0 to 100 |
| `speakerAnalysis[].evaluationCriteria` | string | The criterion the score is based on |
| `speakerAnalysis[].talkPercentage` | number | Share of time the participant spoke, in percent |
| `speakerAnalysis[].duration` | number | How many seconds the participant spoke |
| `speakerAnalysis[].durationFormat` | string | The same time as `MM:SS` |
| `meetingStrengths[]` | object[] | Strengths: `strengthTitle` and `strengthExplanation` |
| `meetingWeaknesses[]` | object[] | Weaknesses: `weaknessTitle` and `weaknessExplanation` |
| `speechStyleInfluence` | string | How the speech style affected the meeting |
| `engagementLevel` | string | Participant engagement |
| `areasOfResponsibility` | string | Who is responsible for what as a result |
| `finalRecommendations` | string | Recommendations for the next meeting |

### Efficiency score — `evaluation`

| Field | Type | Description |
|------|-----|---------|
| `efficiencyValue` | number | Overall meeting efficiency, from 0 to 100 |
| `calendar.overhead` | boolean | Whether the meeting took more time than needed |
| `criteria` | object | Map of criteria. The key is the criterion code, the value is an object with the fields below |
| `criteria.<code>.value` | boolean | Whether the criterion is met |
| `criteria.<code>.title` | string | Criterion name |
| `criteria.<code>.criteria` | string | Criterion wording |
| `criteria.<code>.thoughts` | string | Rationale for the score |

## Response example

```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": "en",
      "version": 3,
      "participants": [
        { "userId": 7, "name": "John Smith", "workPosition": "Project manager", "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.com/disk/call_12345.wav", "dateCreate": "2026-01-15T11:00:00+00:00" }
      ],
      "transcription": {
        "language": "en",
        "segments": [
          { "userId": 7, "userName": "John Smith", "start": 12, "end": 25, "text": "Let's fix the sprint scope. What do we take into work?" },
          { "userId": 42, "userName": "Mary Jones", "start": 26, "end": 48, "text": "I suggest we keep only the catalog import, we won't have time for the rest." },
          { "userId": 7, "userName": "John Smith", "start": 49, "end": 70, "text": "Agreed. Then we show the prototype on Friday." }
        ]
      },
      "overview": {
        "topic": "Sprint planning",
        "detailedTakeaways": "The team reduced the sprint scope to the catalog import and agreed to show the prototype on Friday.",
        "meetingType": {
          "typeTag": "planning",
          "title": "Planning",
          "explanation": "The participants distributed tasks and deadlines for the next iteration."
        },
        "agenda": {
          "explanation": "Define the sprint scope and the demo deadline.",
          "quote": "Let's fix the sprint scope."
        },
        "agreements": [
          { "agreement": "Only the catalog import goes into the sprint", "quote": "I suggest we keep only the catalog import, we won't have time for the rest." }
        ],
        "actionItems": [
          { "actionItem": "Prepare the prototype by Friday", "quote": "Then we show the prototype on Friday." }
        ],
        "meetings": [
          { "meeting": "Prototype demo on Friday", "quote": "Then we show the prototype on Friday." }
        ]
      },
      "summary": {
        "segments": [
          { "start": 0, "end": 600, "title": "Sprint scope", "summary": "Discussed what the team can deliver and reduced the task set to the catalog import." },
          { "start": 601, "end": 2520, "title": "Deadlines and demo", "summary": "Agreed to show the prototype on Friday and to return to the other tasks in the next sprint." }
        ]
      },
      "insights": {
        "speakerEvaluationAvailable": true,
        "speakerAnalysis": [
          {
            "userId": 42,
            "detailedInsight": "The participant proposed reducing the scope and backed it with a deadline estimate.",
            "efficiencyValue": 82,
            "evaluationCriteria": "Constructiveness of proposals",
            "talkPercentage": 66,
            "duration": 1200,
            "durationFormat": "20:00"
          },
          {
            "userId": 7,
            "detailedInsight": "The participant ran the meeting and recorded the agreements.",
            "efficiencyValue": 74,
            "evaluationCriteria": "Discussion management",
            "talkPercentage": 34,
            "duration": 600,
            "durationFormat": "10:00"
          }
        ],
        "meetingStrengths": [
          { "strengthTitle": "Clear outcome", "strengthExplanation": "The meeting ended with a recorded decision and a deadline." }
        ],
        "meetingWeaknesses": [
          { "weaknessTitle": "Unequal participation", "weaknessExplanation": "One participant spoke for two thirds of the time." }
        ],
        "speechStyleInfluence": "The calm pace of speech helped reach a decision quickly.",
        "engagementLevel": "High engagement of both participants.",
        "areasOfResponsibility": "The catalog import is assigned to Mary Jones.",
        "finalRecommendations": "Send the agenda in advance to shorten the scope discussion."
      },
      "evaluation": {
        "efficiencyValue": 75,
        "calendar": { "overhead": false },
        "criteria": {
          "agenda_defined": {
            "value": true,
            "criteria": "The agenda is stated at the start of the meeting",
            "title": "Agenda",
            "thoughts": "The host stated the goal in the first utterance."
          },
          "decisions_made": {
            "value": true,
            "criteria": "Decisions are made on the questions discussed",
            "title": "Decisions",
            "thoughts": "The sprint scope and the demo deadline are recorded."
          },
          "all_participants_involved": {
            "value": false,
            "criteria": "All participants are involved in the discussion",
            "title": "Engagement",
            "thoughts": "The split of utterances is 66 to 34 percent."
          }
        }
      }
    }
  }
}
```

The keys in `evaluation.criteria` are criterion codes. Their set depends on the meeting type, so iterate over the map by keys instead of a fixed list.

## Error response example

422 — the call is not found or its Follow-up is unavailable:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "No access to the Follow-up data"
  }
}
```

The `error.message` text comes from Bitrix24, so its wording and language depend on the Bitrix24 account language. Branch on `error.code`, not on the message text.

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | `callId` in the path is not a positive integer. Checked before the request to Bitrix24 |
| 400 | `INVALID_PARAMS` | A query parameter value is outside the allowed list — for example `mentionFormat`. If Bitrix24 rejected the value on a specific field, the response also contains an `error.validation` array with the field name |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 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 `call` scope |
| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied access: the key's webhook has no `call` permission on the portal side. Reconnect the key with the required permission |
| 422 | `METHOD_NOT_YET_AVAILABLE` | Update `call 26.600.0` has not been released on the portal yet. The response contains an `error.release` field with the target version |
| 422 | `BITRIX_ERROR` | The request was rejected by Bitrix24. There is no call with this `callId`, or its Follow-up is not accessible — the message is "No access to the Follow-up data". The reason for the specific denial is in `error.message` |
| 429 | `RATE_LIMITED` | The request rate on the Bitrix24 side is 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 before a repeat request |
| 503 | `BITRIX_TIMEOUT` | Bitrix24 accepted the request but did not answer within 15 seconds. A repeat request is safe for reads |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

**A non-existent call cannot be distinguished from an access denial by the response.** Both cases come back with the same response. [Follow-up list](./list.md) does not answer this either: it contains only calls with a ready Follow-up and only those the employee has access to — a call missing from the list does not mean the call does not exist.

**Calls without AI processing.** If a call is finished but no Follow-up has been built for it, the method returns an object with metadata: the AI blocks arrive as `null` and `outcomes` as an empty array.

**Speaker analysis is not available on every Bitrix24 account.** If it is unavailable on the account, the `insights` block arrives with `speakerEvaluationAvailable: false` and an empty speaker analysis. This is not a request error — the response structure does not change.

**Access is limited by employee permissions.** The Follow-up is available to whoever took part in the call or is a member of the linked chat — including someone added to the chat after the conversation. The Bitrix24 account administrator sees the Follow-up of any call on the account.

## See also

- [Follow-up list](/docs/calls/followup/list)
- [Call follow-up](/docs/calls/followup)
- [Calls](/docs/calls)
- [Errors](/docs/errors)
