How to Retrieve a List of Stages with Semantics for CRM Entities
Scope:
crm, user_briefWho can execute the method: any user with access to CRM
If you are developing integrations for Bitrix24 using AI tools (Codex, Claude Code, Cursor), connect to the MCP server so that the assistant can utilize the official REST documentation.
The semantics of a stage reflects the current state of a CRM entity: in progress, successfully completed, or unsuccessful. The system uses the semantic value in automation and reporting.
To create a table of CRM entity stages with semantics, we will use the method crm.status.list.
Retrieve a List of Stages with Semantics
The method crm.status.list returns a description of stages based on the stage code ENTITY_ID for the CRM entity.
-
Deals —
DEAL_STAGEfor the main deal direction andDEAL_STAGE_xxfor additional ones, where xx is the direction identifier. -
Leads —
STATUS. -
Invoices —
SMART_INVOICE_STAGE_xx, wherexxis the invoice direction identifier value. -
Quotes —
QUOTE_STATUS. -
Documents —
SMART_DOCUMENT_STAGE_xx, wherexxis theIDof the document direction. -
Smart Processes —
DYNAMIC_xx_STAGE_xx, where the firstxxis the smart processID, and the secondxxis the directionID.
Let's retrieve the description of stages with semantics for leads. To do this, we will specify in the filter filter the field ENTITY_ID with the value STATUS.
How to Use Examples in Documentation
BX24.callMethod(
"crm.status.list",
{
order: { SORT: "ASC" }, // sorting in ascending order based on the SORT field
filter: { ENTITY_ID: "STATUS" }, // retrieving stages for leads
},
function(result) {
if(result.error())
console.error(result.error());
else
console.dir(result.data());
}
);
require_once('crest.php');
$result = CRest::call(
'crm.status.list',
[
'order' => [ 'SORT' => 'ASC' ],
'filter' => [ 'ENTITY_ID' => 'STATUS' ]
]
);
As a result, we will receive an array of objects, where each object is a description of a stage.
{
"result": [
{
"ID": "1",
"ENTITY_ID": "STATUS",
"STATUS_ID": "NEW",
"NAME": "Not Processed",
"NAME_INIT": "Not Processed",
"SORT": "10",
"SYSTEM": "Y",
"CATEGORY_ID": null,
"COLOR": "#00FFFF",
"SEMANTICS": null,
"EXTRA": {
"SEMANTICS": "process",
"COLOR": "#00FFFF"
}
},
{
"ID": "3",
"ENTITY_ID": "STATUS",
"STATUS_ID": "ASSIGNED",
"NAME": "Responsible Assigned",
"NAME_INIT": "",
"SORT": "20",
"SYSTEM": "N",
"CATEGORY_ID": null,
"COLOR": "#FFF100",
"SEMANTICS": null,
"EXTRA": {
"SEMANTICS": "process",
"COLOR": "#FFF100"
}
},
...,
{
"ID": "15",
"ENTITY_ID": "STATUS",
"STATUS_ID": "CONVERTED",
"NAME": "Converted",
"NAME_INIT": "Converted",
"SORT": "50",
"SYSTEM": "Y",
"CATEGORY_ID": null,
"COLOR": "#37B44A",
"SEMANTICS": "S",
"EXTRA": {
"SEMANTICS": "success",
"COLOR": "#37B44A"
}
},
{
"ID": "17",
"ENTITY_ID": "STATUS",
"STATUS_ID": "JUNK",
"NAME": "Low-Quality Lead",
"NAME_INIT": "Low-Quality Lead",
"SORT": "60",
"SYSTEM": "Y",
"CATEGORY_ID": null,
"COLOR": "#F54819",
"SEMANTICS": "F",
"EXTRA": {
"SEMANTICS": "failure",
"COLOR": "#F54819"
}
}
],
"total": 6
}
The EXTRA.SEMANTICS object contains the semantics of the stages. Possible values include:
-
process— the CRM entity is in progress, -
success— the work with the CRM entity has been successfully completed, -
failure— the work with the CRM entity has been unsuccessfully completed.
Code Example
The code outputs tables with a list of stages for leads and quotes.
/**
* Loads all statuses for the given ENTITY_ID
* @param {string} entityId — entity code, e.g., 'STATUS' or 'QUOTE_STATUS'
* @returns {Promise<Array>} — array of all statuses
*/
function loadStatuses(entityId) {
return new Promise((resolve, reject) => {
BX24.callMethod('crm.status.list', {
filter: { ENTITY_ID: entityId },
select: ['STATUS_ID', 'NAME', 'EXTRA'],
order: { SORT: 'ASC' }
}, (result) => {
if (result.error()) {
reject(result.error());
return;
}
resolve(result.data());
});
});
}
/**
* Groups statuses by semantics
*/
function groupStatusesBySemantics(statuses) {
const groups = { success: [], process: [], failure: [] };
statuses.forEach(item => {
const semantics = item.EXTRA?.SEMANTICS || '';
const name = item.NAME || item.STATUS_ID;
if (semantics === 'success') {
groups.success.push(name);
} else if (semantics === 'failure') {
groups.failure.push(name);
} else {
groups.process.push(name);
}
});
return groups;
}
/**
* Formats groups for console.table
*/
function formatForConsoleTable(groups) {
const { success, process, failure } = groups;
const maxLen = Math.max(success.length, process.length, failure.length);
const pad = (arr, len) => [...arr, ...Array(len - arr.length).fill('')];
return Array(maxLen).fill().map((_, i) => ({
'✅ Success': pad(success, maxLen)[i],
'⚠️ In Progress': pad(process, maxLen)[i],
'❌ Failure': pad(failure, maxLen)[i]
}));
}
// Requesting statuses
Promise.all([
loadStatuses('STATUS').then(data => ({ type: 'Leads', data })),
loadStatuses('QUOTE_STATUS').then(data => ({ type: 'Quotes', data }))
]).then(results => {
results.forEach(({ type, data }) => {
console.group(`📊 ${type}`);
const groups = groupStatusesBySemantics(data);
console.table(formatForConsoleTable(groups));
console.groupEnd();
});
}).catch(err => {
console.error('Loading error:', err);
});
<?php
require_once 'crest.php';
/**
* Retrieves all statuses for the given ENTITY_ID
* @param string $entityId
* @return array
*/
function loadStatuses($entityId) {
$result = CRest::call('crm.status.list', [
'filter' => ['ENTITY_ID' => $entityId],
'select' => ['STATUS_ID', 'NAME', 'EXTRA'],
'order' => ['SORT' => 'ASC']
]);
if (!empty($result['error'])) {
throw new Exception("Error loading statuses for $entityId: " . $result['error_description']);
}
return $result['result'];
}
/**
* Groups statuses by semantics
*/
function groupStatusesBySemantics($statuses) {
$groups = ['success' => [], 'process' => [], 'failure' => []];
foreach ($statuses as $item) {
$semantics = $item['EXTRA']['SEMANTICS'] ?? '';
$name = $item['NAME'] ?? $item['STATUS_ID'];
if ($semantics === 'success') {
$groups['success'][] = $name;
} elseif ($semantics === 'failure') {
$groups['failure'][] = $name;
} else {
$groups['process'][] = $name;
}
}
return $groups;
}
/**
* Formats table rows
*/
function buildTableRows($groups) {
$success = $groups['success'];
$process = $groups['process'];
$failure = $groups['failure'];
$max = max(count($success), count($process), count($failure));
$success = array_pad($success, $max, '');
$process = array_pad($process, $max, '');
$failure = array_pad($failure, $max, '');
$rows = [];
for ($i = 0; $i < $max; $i++) {
$rows[] = [
htmlspecialchars($success[$i]),
htmlspecialchars($process[$i]),
htmlspecialchars($failure[$i])
];
}
return $rows;
}
$entities = [
['title' => 'Lead Statuses', 'entityId' => 'STATUS'],
['title' => 'Quote Statuses', 'entityId' => 'QUOTE_STATUS']
];
foreach ($entities as $entity) {
try {
$statuses = loadStatuses($entity['entityId']);
if (empty($statuses)) {
echo "<p>No statuses for " . htmlspecialchars($entity['title']) . "</p>\n";
continue;
}
$groups = groupStatusesBySemantics($statuses);
$rows = buildTableRows($groups);
echo "<h2>" . htmlspecialchars($entity['title']) . "</h2>\n";
echo "<table border=\"1\" style=\"border-collapse: collapse; width: 100%;\">\n";
echo "<thead><tr>
<th style=\"padding: 8px; background: #d4edda;\">✅ Success</th>
<th style=\"padding: 8px; background: #fff3cd;\">⚠️ In Progress</th>
<th style=\"padding: 8px; background: #f8d7da;\">❌ Failure</th>
</tr></thead>\n<tbody>";
foreach ($rows as $row) {
echo "<tr>
<td style=\"padding: 6px;\">{$row[0]}</td>
<td style=\"padding: 6px;\">{$row[1]}</td>
<td style=\"padding: 6px;\">{$row[2]}</td>
</tr>\n";
}
echo "</tbody></table><br>\n";
} catch (Exception $e) {
echo "<p style=\"color: red;\">Error: " . htmlspecialchars($e->getMessage()) . "</p>\n";
}
}