
## Attach a transcription

`POST /v1/calls/:callId/transcription`

Attaches a text transcription of the conversation to a finished call in Bitrix24. The call must first be finished via [`POST /v1/calls/:callId/finish`](./finish.md).

## Parameters

| Parameter | In | Type | Required | Description |
|----------|---|-----|:-----:|---------|
| `callId` | path | string | yes | `callId` from the [`POST /v1/calls/register`](./register.md) response |

## Request fields (body)

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|---------|
| `messages` | array | yes | — | Array of conversation turns. Each item: `{side, startTime, stopTime, message}`. The array cannot be empty |
| `messages[].side` | string | yes | — | Side of the conversation: `"User"` — operator, `"Client"` — customer |
| `messages[].startTime` | number | yes | — | Turn start time in seconds from the beginning of the recording (≥ 0) |
| `messages[].stopTime` | number | yes | — | Turn end time in seconds (> 0) |
| `messages[].message` | string | yes | — | Turn text (non-empty string) |
| `cost` | number | no | — | Recognition cost |
| `costCurrency` | string | no | — | Cost currency (e.g. `"USD"`) |

## Examples

### curl — personal key

```bash
curl -X POST https://vibecode.bitrix24.com/v1/calls/CALL_ID/transcription \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"side": "User", "startTime": 0, "stopTime": 3, "message": "Hello, how can I help you?"},
      {"side": "Client", "startTime": 4, "stopTime": 9, "message": "Hello, I wanted to check my order status"}
    ]
  }'
```

### curl — OAuth application

```bash
curl -X POST https://vibecode.bitrix24.com/v1/calls/CALL_ID/transcription \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"side": "User", "startTime": 0, "stopTime": 3, "message": "Hello, how can I help you?"},
      {"side": "Client", "startTime": 4, "stopTime": 9, "message": "Hello, I wanted to check my order status"}
    ]
  }'
```

### JavaScript — personal key

```javascript
const callId = 'externalCall.00b1e735843c558431be668e3687a58b.1777974304'

const res = await fetch(`https://vibecode.bitrix24.com/v1/calls/${callId}/transcription`, {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    messages: [
      { side: 'User', startTime: 0, stopTime: 3, message: 'Hello, how can I help you?' },
      { side: 'Client', startTime: 4, stopTime: 9, message: 'Hello, I wanted to check my order status' },
    ],
  }),
})

const { success, data } = await res.json()
console.log('Transcription ID:', data.transcriptId)
```

### JavaScript — OAuth application

```javascript
const callId = 'externalCall.00b1e735843c558431be668e3687a58b.1777974304'

const res = await fetch(`https://vibecode.bitrix24.com/v1/calls/${callId}/transcription`, {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    messages: [
      { side: 'User', startTime: 0, stopTime: 3, message: 'Hello, how can I help you?' },
      { side: 'Client', startTime: 4, stopTime: 9, message: 'Hello, I wanted to check my order status' },
    ],
  }),
})

const { success, data } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `transcriptId` | number | Internal transcription ID in the Bitrix24 account |

## Response example

HTTP 200 — the transcription is attached:

```json
{
  "success": true,
  "data": {
    "transcriptId": 3
  }
}
```

## Error response example

400 — the `messages` array is missing:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_PARAMS",
    "message": "Required: messages (non-empty array of {side, startTime, stopTime, message})"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `MISSING_PARAMS` | `messages` is missing, is not an array, or the array is empty |
| 400 | `INVALID_MESSAGE_SHAPE` | Invalid structure of a `messages[i]` item: wrong `side`, wrong type or range of `startTime`/`stopTime`, empty `message`. The error text contains the index of the invalid item and the violated field |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | Invalid API key |
| 401 | `TOKEN_MISSING` | The API key has no Bitrix24 tokens configured |
| 401 | `KEY_INACTIVE` | The API key is inactive or revoked |
| 403 | `SCOPE_DENIED` | The key is missing the `telephony` scope |
| 422 | `BITRIX_ERROR` | Bitrix24 returned an error (text in `error.message`) |
| 429 | `RATE_LIMITED` | Request limit exceeded |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable |

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

## Known specifics

**On an unfinished call, Bitrix24 returns an error.** Operation order: `register` → `finish` → `transcription`.

**Vibecode validates the `messages` structure locally.** Each item is checked before being sent to Bitrix24. The `INVALID_MESSAGE_SHAPE` error contains the index of the invalid item and an exact description of the violated constraint — this lets you fix the specific item without resending the whole array.

**`transcriptId` is used only inside the Bitrix24 account.** There are no external endpoints for reading transcriptions by this ID.

## See also

- [Finish a call](./finish.md) — a mandatory step before attaching a transcription
- [Register a call](./register.md)
- [Call statistics](/docs/telephony/analytics/statistics) — viewing records of finished calls
