For AI agents: markdown of this page — /docs-content-en/stage-history.md documentation index — /llms.txt
Stage history
GET /v1/stage-history
Returns the history of CRM record transitions across stages and statuses — when a record reached each pipeline stage. Used for reports on the velocity of deals and leads and for conversion analysis across pipelines.
Bitrix24 API: crm.stagehistory.list
Scope: crm
Parameters
The set of stage filter fields depends on the record type. For the stage-based types deal and invoice, stageId, stageSemanticId, categoryId are available. For the status-based type lead, statusId, statusSemanticId are available. A field that does not belong to the type returns 400 INVALID_FILTER_FIELD.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
entityType (query) |
string | no | deal |
CRM record type: deal, lead, invoice |
ownerId (query) |
number | no | — | Identifier of the record whose transition history to return. Depends on entityType. Sources: GET /v1/deals, GET /v1/leads, GET /v1/invoices |
typeId (query) |
number | no | — | Transition type: 1 — record creation, 2 — move to an intermediate stage, 3 — move to a final stage, 5 — pipeline change |
createdAfter (query) |
string | no | — | Transitions from the specified moment, inclusive (ISO 8601) |
createdBefore (query) |
string | no | — | Transitions up to the specified moment, inclusive (ISO 8601) |
stageId (query) |
string | no | — | deal, invoice only. Filter by stage. List: GET /v1/statuses?filter[entityId]=DEAL_STAGE |
stageSemanticId (query) |
string | no | — | deal, invoice only. Stage semantics: P — intermediate, S — successful, F — failed |
categoryId (query) |
number | no | — | deal, invoice only. Pipeline identifier. List: GET /v1/deal-categories |
statusId (query) |
string | no | — | lead only. Filter by status. List: GET /v1/statuses?filter[entityId]=STATUS |
statusSemanticId (query) |
string | no | — | lead only. Status semantics: P — intermediate, S — successful, F — failed |
limit (query) |
number | no | 50 |
Number of records per call. Maximum 5000 |
offset (query) |
number | no | 0 |
Selection offset. Rounded down to a multiple of 50 |
For limit > 50, Vibecode automatically paginates the request on the server side. Maximum — 5000 records per call. The meta.hasMore field shows whether there are records beyond the current selection.
Examples
curl — personal key
curl "https://vibecode.bitrix24.com/v1/stage-history?entityType=deal&limit=50" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl "https://vibecode.bitrix24.com/v1/stage-history?entityType=deal&limit=50" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
const params = new URLSearchParams({ entityType: 'deal', limit: '50' })
const res = await fetch(`https://vibecode.bitrix24.com/v1/stage-history?${params}`, {
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { success, data, meta } = await res.json()
JavaScript — OAuth application
const params = new URLSearchParams({ entityType: 'deal', limit: '50' })
const res = await fetch(`https://vibecode.bitrix24.com/v1/stage-history?${params}`, {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { success, data, meta } = await res.json()
Response fields
The set of record fields depends on the type: the stage-based types deal and invoice return stageId, stageSemanticId, categoryId, while the status-based type lead returns statusId, statusSemanticId.
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on success |
data |
array | Array of history records, newest to oldest |
data[].id |
number | History record identifier |
data[].typeId |
number | Transition type: 1 — creation, 2 — intermediate stage, 3 — final stage, 5 — pipeline change |
data[].ownerId |
number | Identifier of the record in which the transition occurred |
data[].createdAt |
string | Moment of the transition to the stage (ISO 8601) |
data[].stageId |
string | Stage. deal, invoice only |
data[].stageSemanticId |
string | Stage semantics: P, S, F. deal, invoice only |
data[].categoryId |
number | Pipeline. deal, invoice only |
data[].statusId |
string | Status. lead only |
data[].statusSemanticId |
string | Status semantics: P, S, F. lead only |
meta.total |
number | Total number of records under the filter |
meta.hasMore |
boolean | Whether there are records beyond the current selection |
Response example
Deal (entityType=deal) — transitions across pipeline stages:
{
"success": true,
"data": [
{
"id": 12857,
"typeId": 1,
"ownerId": 7913,
"createdAt": "2026-06-24T00:03:50+00:00",
"categoryId": 9,
"stageSemanticId": "P",
"stageId": "C9:NEW"
},
{
"id": 12855,
"typeId": 1,
"ownerId": 7911,
"createdAt": "2026-06-23T00:02:34+00:00",
"categoryId": 9,
"stageSemanticId": "P",
"stageId": "C9:NEW"
}
],
"meta": {
"total": 2941,
"hasMore": true
}
}
Lead (entityType=lead) — transitions across statuses:
{
"success": true,
"data": [
{
"id": 3689,
"typeId": 1,
"ownerId": 1001083,
"createdAt": "2026-06-10T18:03:12+00:00",
"statusId": "NEW",
"statusSemanticId": "P"
}
],
"meta": {
"total": 296,
"hasMore": true
}
}
Error response example
400 — the filter field does not apply to the record type:
{
"success": false,
"error": {
"code": "INVALID_FILTER_FIELD",
"message": "\"statusId\" is not a valid filter for entityType \"deal\". entityType \"deal\" is stage-based — use stageId."
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_ENTITY_TYPE |
Unknown entityType. The message contains the list of supported values |
| 400 | INVALID_FILTER_FIELD |
The filter field does not apply to the specified entityType — for example statusId for deal |
| 403 | SCOPE_DENIED |
The key lacks the crm scope |
| 401 | TOKEN_MISSING |
The key has no access tokens configured |
| 401 | MISSING_API_KEY |
The X-Api-Key header was not provided |
Full list of common API errors — Errors.
Known specifics
Sorting is not configurable. The sort parameter is not accepted — the order of records cannot be changed.