How to Mass Terminate Workflows with Date Filtering
Scope:
bizprocWho can execute methods: administrator
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.
During the operation of Bitrix24, you may accumulate stuck workflows or processes that remain in the "In Progress" status for too long and become irrelevant.
To mass terminate old workflows, we will sequentially execute two methods:
- bizproc.workflow.instances — retrieve a filtered list of processes
- bizproc.workflow.kill — terminate workflows with data deletion. If you need to preserve the fact that the workflow was initiated, use the bizproc.workflow.terminate method. Both methods are called in the same way.
1. Retrieve the List of Processes
We will use the bizproc.workflow.instances method with a filter:
<STARTED— specify the start date with the prefix<, only processes that were started before this date will be selected.
How to Use Examples in Documentation
BX24.callMethod(
'bizproc.workflow.instances',
{
filter: {
'<STARTED': '2025-01-01T00:00:00Z'
}
},
);
require_once('crest.php');
$result = CRest::call(
'bizproc.workflow.instances',
[
'filter' => [
'<STARTED' => '2025-01-01T00:00:00Z'
]
]
);
from b24pysdk import BitrixWebhook, Client
from b24pysdk.errors import BitrixAPIError
client = Client(
BitrixWebhook(
domain="your-domain.bitrix24.com",
auth_token="your-webhook-token",
)
)
response = client.bizproc.workflow.instances(
filter={
"<STARTED": "2025-01-01T00:00:00Z",
}
).response
As a result, we will obtain the ID of all active workflows that were initiated before the specified date.
{
"result": [
{
"ID": "660e559f34af10.95144732",
"MODIFIED": "2024-12-04T10:04:24+03:00",
"OWNED_UNTIL": null
},
{
"ID": "6639c7b59e9eb5.40607056",
"MODIFIED": "2024-12-04T09:52:40+03:00",
"OWNED_UNTIL": null
},
{
"ID": "66ea9200131729.26195442",
"MODIFIED": "2024-09-18T11:42:28+03:00",
"OWNED_UNTIL": null
},
{
"ID": "65ef0868368978.47049110",
"MODIFIED": "2024-03-11T16:34:32+03:00",
"OWNED_UNTIL": null
}
],
"total": 4
}
2. Terminate Workflows
We will use the bizproc.workflow.kill method with the parameter:
ID— the identifier of the process, we pass theIDobtained in step 1.
BX24.callMethod(
'bizproc.workflow.kill',
{
ID: '660e559f34af10.95144732',
},
);
require_once('crest.php');
$result = CRest::call(
'bizproc.workflow.kill',
[
'ID' => '660e559f34af10.95144732'
]
);
response = client.bizproc.workflow.kill(
bitrix_id="660e559f34af10.95144732",
).response
As a result, we will receive true, indicating that the process was successfully deleted. If you encounter an error, refer to the documentation for possible errors in the bizproc.workflow.kill method.
{
"result": true
}
Code Example
In this example, all found processes are deleted in a loop. When deleting a large volume of data, there may be limitations on request execution. To optimize the code for your workload, refer to the Performance section.
// Function to convert date from dd.mm.yyyy format to ISO format
function convertDateToISO(dateString) {
const [day, month, year] = dateString.split('.');
return `${year}-${month}-${day}T00:00:00Z`;
}
// Request date from user
const userDateInput = prompt("Enter the date in dd.mm.yyyy format:");
const isoDate = convertDateToISO(userDateInput);
// Call the bizproc.workflow.instances method with date filter
BX24.callMethod(
'bizproc.workflow.instances',
{
filter: {
'<STARTED': isoDate
}
},
function(result) {
if (result.error()) {
console.error(result.error());
} else {
const instances = result.data();
instances.forEach(instance => {
const instanceId = instance.ID;
// Call the bizproc.workflow.kill method for each ID
BX24.callMethod(
'bizproc.workflow.kill',
{
ID: instanceId
},
function(killResult) {
if (killResult.error()) {
console.error(`Error deleting process ${instanceId}:`, killResult.error());
} else {
console.log(`Process ${instanceId} successfully deleted.`);
}
}
);
});
if (result.more()) {
result.next();
}
}
}
);
require_once('crest.php');
// Function to convert date from dd.mm.yyyy format to ISO format
function convertDateToISO($dateString) {
list($day, $month, $year) = explode('.', $dateString);
return "{$year}-{$month}-{$day}T00:00:00Z";
}
// Request date from user
$userDateInput = readline("Enter the date in dd.mm.yyyy format: ");
$isoDate = convertDateToISO($userDateInput);
// Call the bizproc.workflow.instances method with date filter
$result = CRest::call(
'bizproc.workflow.instances',
[
'filter' => [
'<STARTED' => $isoDate
]
]
);
if (!empty($result['error'])) {
echo "Error: " . $result['error_description'];
} else {
$instances = $result['result'];
foreach ($instances as $instance) {
$instanceId = $instance['ID'];
// Call the bizproc.workflow.kill method for each ID
$killResult = CRest::call(
'bizproc.workflow.kill',
[
'ID' => $instanceId
]
);
if (!empty($killResult['error'])) {
echo "Error deleting process {$instanceId}: " . $killResult['error_description'] . "\n";
} else {
echo "Process {$instanceId} successfully deleted.\n";
}
}
// Check for additional data
while (!empty($result['next'])) {
$result = CRest::call(
'bizproc.workflow.instances',
[
'filter' => [
'<STARTED' => $isoDate
],
'start' => $result['next']
]
);
$instances = $result['result'];
foreach ($instances as $instance) {
$instanceId = $instance['ID'];
// Call the bizproc.workflow.kill method for each ID
$killResult = CRest::call(
'bizproc.workflow.kill',
[
'ID' => $instanceId
]
);
if (!empty($killResult['error'])) {
echo "Error deleting process {$instanceId}: " . $killResult['error_description'] . "\n";
} else {
echo "Process {$instanceId} successfully deleted.\n";
}
}
}
}
from b24pysdk import BitrixWebhook, Client
user_date_input = input("Enter the date in dd.mm.yyyy format: ")
day, month, year = user_date_input.split(".")
iso_date = f"{year}-{month}-{day}T00:00:00Z"
client = Client(
BitrixWebhook(
domain="your-domain.bitrix24.com",
auth_token="your-webhook-token",
)
)
start = None
while True:
kwargs = {"filter": {"<STARTED": iso_date}}
if start is not None:
kwargs["start"] = start
response = client.bizproc.workflow.instances(**kwargs).response
instances = response.result or []
for instance in instances:
instance_id = instance["ID"]
try:
client.bizproc.workflow.kill(bitrix_id=instance_id).response
except BitrixAPIError as error:
print(f"Error deleting process {instance_id}: {error}")
else:
print(f"Process {instance_id} successfully deleted.")
if response.next is None:
break
start = response.next