لوكلاء AI: ملف markdown لهذه الصفحة — /docs-content-en/telephony/analytics.md فهرس التوثيق — /llms.txt
مقالات التوثيق متاحة حاليًا باللغة الإنجليزية فقط.
Analytics and reference data
Reading statistics of past calls with filtering by date, type, operator and other fields, and a reference of available voices for speech synthesis in automatic calls.
Bitrix24 API: voximplant.statistic.get, voximplant.tts.voices.get
Scope: telephony
Call statistics
GET /v1/calls/statistics
Returns a list of records of past calls with support for field filtering, sorting, and pagination with a fixed page of up to 50 records.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Parameterfilter (query) |
Typeobject | Default— | DescriptionFiltering by record fields (UPPER_SNAKE_CASE). The operators >, >=, <, <=, ! are supported as a prefix to the field name. Example: ?filter[CALL_TYPE]=1, ?filter[>CALL_START_DATE]=2026-01-01T00:00:00 Important: this endpoint accepts the BRACKET form only: ?filter[CALL_TYPE]=1. A JSON object (?filter={"CALL_TYPE":1}) is forwarded to Bitrix24 as a string and does not become a filter. Spell every condition once and no deeper than two levels: when a condition is lost while the query string is parsed, the request is refused with 400 INVALID_FILTER rather than half-applied. A lowercase filter carrying a value next to an uppercase FILTER is the same case: the lowercase one takes the parameter and the uppercase one silently disappears. An empty ?filter= next to FILTER[...] loses nothing and works. An empty ?filter= means "no filter". |
Parametersort (query) |
Typestring | Default— | DescriptionField to sort by, in UPPER_SNAKE_CASE. Example: CALL_START_DATE |
Parameterorder (query) |
Typestring | Default— | DescriptionSort direction: ASC or DESC |
Parameterlimit (query) |
Typenumber | Default50 |
DescriptionCompatibility parameter; use 50. The route returns one Bitrix24 page of up to 50 records |
Parameteroffset (query) |
Typenumber | Default0 |
DescriptionOffset for pagination |
A date range is set with two operators at once. Example: filter[>CALL_START_DATE]=2026-04-01T00:00:00&filter[<CALL_START_DATE]=2026-04-30T23:59:59.
Examples
curl — personal key
curl --globoff "https://vibecode.bitrix24.com/v1/calls/statistics?limit=50&sort=CALL_START_DATE&order=DESC&filter[CALL_TYPE]=1" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl --globoff "https://vibecode.bitrix24.com/v1/calls/statistics?limit=50&sort=CALL_START_DATE&order=DESC&filter[CALL_TYPE]=1" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
const params = new URLSearchParams({
limit: '50',
sort: 'CALL_START_DATE',
order: 'DESC',
'filter[CALL_TYPE]': '1',
})
const res = await fetch(`https://vibecode.bitrix24.com/v1/calls/statistics?${params}`, {
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { success, data, total } = await res.json()
console.log(`Calls found: ${total}`)
JavaScript — OAuth application
const params = new URLSearchParams({
limit: '50',
sort: 'CALL_START_DATE',
order: 'DESC',
'filter[CALL_TYPE]': '1',
})
const res = await fetch(`https://vibecode.bitrix24.com/v1/calls/statistics?${params}`, {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { success, data, total } = await res.json()
JavaScript — iterating through all pages
const pageSize = 50
let offset = 0
const allCalls = []
while (true) {
const params = new URLSearchParams({
limit: String(pageSize),
offset: String(offset),
sort: 'CALL_START_DATE',
order: 'DESC',
})
const res = await fetch(`https://vibecode.bitrix24.com/v1/calls/statistics?${params}`, {
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
// total is at the root of the response — total records under the filter
const { data, total } = await res.json()
allCalls.push(...data)
offset += data.length
// fetch the next page until all records are collected
if (offset >= total || data.length === 0) break
}
console.log(`Calls collected: ${allCalls.length}`)
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on success |
Fielddata |
Typearray | DescriptionArray of call records |
Fielddata[].id |
Typestring | DescriptionInternal record identifier |
Fielddata[].portalUserId |
Typestring | DescriptionOperator ID. List: GET /v1/users |
Fielddata[].portalNumber |
Typestring | DescriptionLine identifier: reg<id> — a rented Voximplant line, sip<id> — a SIP line, REST_APP:<id> — a line via a REST application |
Fielddata[].phoneNumber |
Typestring | DescriptionClient's phone number |
Fielddata[].callId |
Typestring | DescriptionCall identifier. Prefixes: externalCall. — from register, callback. — from a callback, infocall. — from an automatic call |
Fielddata[].externalCallId |
Typestring | null | DescriptionExternal identifier passed at registration |
Fielddata[].callCategory |
Typestring | DescriptionCategory: external for calls via the REST API |
Fielddata[].callLog |
Typestring | null | DescriptionURL of the Voximplant detailed log. null for calls via a REST application |
Fielddata[].callDuration |
Typestring | DescriptionCall duration in seconds (string) |
Fielddata[].callStartDate |
Typestring | DescriptionCall start date, ISO 8601 with the Bitrix24 account time zone |
Fielddata[].callRecordUrl |
Typestring | DescriptionURL of the call audio recording |
Fielddata[].callVote |
Typestring | null | DescriptionCall rating from 1 to 5 |
Fielddata[].cost |
Typestring | DescriptionCall cost (decimal string) |
Fielddata[].costCurrency |
Typestring | DescriptionCurrency code (USD and others) |
Fielddata[].callFailedCode |
Typestring | DescriptionResult code: 200 — success, 603-S — cancelled, 304 — missed, 500 — scenario error, 402 — insufficient funds, 403 — forbidden |
Fielddata[].callFailedReason |
Typestring | DescriptionText reason for the result |
Fielddata[].crmEntityType |
Typestring | DescriptionType of the linked CRM entity: LEAD, CONTACT or an empty string. Source: leads, contacts |
Fielddata[].crmEntityId |
Typestring | DescriptionID of the linked CRM entity |
Fielddata[].crmActivityId |
Typestring | DescriptionCRM activity ID. "0" — no activity created |
Fielddata[].restAppId |
Typestring | null | DescriptionID of the application that initiated the call |
Fielddata[].restAppName |
Typestring | null | DescriptionName of the application that initiated the call |
Fielddata[].transcriptId |
Typestring | null | DescriptionID of the attached transcription. Attach: POST /v1/calls/:callId/transcription |
Fielddata[].transcriptPending |
Typestring | DescriptionY — transcription is being processed, N — transcription is ready or absent |
Fielddata[].sessionId |
Typestring | DescriptionVoximplant session identifier |
Fielddata[].redialAttempt |
Typestring | null | DescriptionRedial attempt number |
Fielddata[].comment |
Typestring | null | DescriptionOperator comment |
Fielddata[].recordDuration |
Typestring | null | DescriptionConversation recording duration in seconds |
Fielddata[].recordFileId |
Typestring | null | DescriptionID of the recording file on the Drive |
Fielddata[].callType |
Typestring | DescriptionCall type: "1" — outbound, "2" — inbound, "3" — inbound with redirect, "4" — callback, "5" — informational (automatic call) |
Fieldtotal |
Typenumber | DescriptionTotal number of records matching the filter |
Response example
{
"success": true,
"data": [
{
"id": "1",
"portalUserId": "1",
"portalNumber": "reg133788",
"phoneNumber": "+12025550123",
"callId": "11018129443EB80D.1754478520.11438214",
"externalCallId": null,
"callCategory": "external",
"callLog": "https://storage-gw-ru-02.voximplant.com/voximplant-logs/2025/08/06/...",
"callDuration": "0",
"callStartDate": "2025-08-06T14:08:40+00:00",
"callRecordUrl": "",
"callVote": null,
"cost": "0.0000",
"costCurrency": "USD",
"callFailedCode": "603-S",
"callFailedReason": "Decline self",
"crmEntityType": "CONTACT",
"crmEntityId": "275",
"crmActivityId": "7739",
"restAppId": null,
"restAppName": null,
"transcriptId": null,
"transcriptPending": "N",
"sessionId": "3841557776",
"redialAttempt": null,
"comment": null,
"recordDuration": null,
"recordFileId": null,
"callType": "1"
}
],
"total": 30
}
Error response example
403 — no telephony scope:
{
"success": false,
"error": {
"code": "SCOPE_DENIED",
"message": "This endpoint requires 'telephony' scope"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header was not provided |
| HTTP401 | CodeINVALID_API_KEY |
DescriptionThe key is not recognized — no such key exists on the platform |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe key has no configured Bitrix24 tokens |
| HTTP401 | CodeKEY_INACTIVE |
DescriptionThe API key is inactive or revoked |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe key lacks the telephony scope |
| HTTP422 | CodeBITRIX_ERROR |
DescriptionBitrix24 returned an error (text in error.message) |
| HTTP429 | CodeRATE_LIMITED |
DescriptionRequest limit exceeded |
| HTTP502 | CodeBITRIX_UNAVAILABLE |
DescriptionBitrix24 is unavailable |
| HTTP400 | CodeINVALID_FILTER |
DescriptionAn ambiguous filter envelope: bracket and JSON forms mixed, or a bracket condition deeper than two levels. Pass the whole filter in a single form |
The full list of common API errors — Errors.
Known specifics
Field names in filter and sort are UPPER_SNAKE_CASE, but in the response they are camelCase. The filter and sort parameters accept the original Bitrix24 names (CALL_TYPE, CALL_START_DATE), while the response fields come back in camelCase (callType, callStartDate). A filter on a camelCase name is silently ignored — all records are returned.
total is at the root of the response. Unlike other Vibecode list endpoints, the total field is located directly at the root of the response, not in meta.total.
A filter on a nonexistent field does not return an error — an invalid field name is silently ignored and all records are returned.