Массовое редактирование задач Битрикс24: постановка задачи
В наших проектах потребность массово править десятки, а то и сотни задач возникает регулярно: после запуска отдела продаж нужно сменить ответственного на всех активных задачах; в конце квартета продлить дедлайны по проектам; при внедрении новой системы тегов проставить их задним числом. Штатный интерфейс Битрикс24 — галочки, выпадающие меню, групповые действия — справляется с этим, но упирается в лимит в 50–100 задач за раз. Когда в портфеле 500 просроченных задач, кликать по ним пакетами по 50 штук, терять день. Кроме того, интерфейс не даёт гибких условий: «продлить дедлайн всем задачам, где ответственный, Иванов, а статус, «В работе»». Мы регулярно сталкиваемся с этим у клиентов с большим документооборотом и проектными отделами, и каждый раз приходим к одному выводу: массовое редактирование через REST API, единственный способ, который не заканчивается нервным срывом менеджера. Оно же комбинируется с автоматическими сценариями: например, агент раз в час проверяет просрочки и продлевает их, или вебхук из CRM триггерит смену ответственного.
Вот пять типовых сценариев, которые мы чаще всего автоматизируем:
- Смена ответственного, перевод всех задач сотрудника, уходящего в отпуск, на коллегу.
- Продление дедлайна, сдвиг дат на N дней для всех задач в проекте, который отстаёт от графика.
- Добавление тега, простановка метки «Аудит-2025» на задачи определённого направления.
- Изменение статуса, перевод группы задач из «В работе» в «На проверке» после завершения этапа.
- Массовое закрытие, завершение всех задач в проекте, который архивируется.
Как REST API решает эти задачи? Вместо того чтобы открывать каждую задачу в интерфейсе и ждать ответа сервера, мы шлём один HTTP-запрос на задачу, метод task.item.update с массивом полей. Для 200 задач это 200 запросов. Но у REST API Битрикс24 есть batch-пакет: команда batch, которая упаковывает до 50 вызовов в один HTTP-запрос. Сервер выполняет их последовательно, но мы экономим накладные расходы на установку соединения. Для сценария «сменить ответственного на 200 задачах» достаточно 4 batch-запросов по 50 штук, это несколько секунд работы скрипта. Методы семейства task.item.*, getdata, update, delete, работают через стандартный REST-интерфейс, принимают ID задачи и массив изменяемых полей. Как формировать batch-пакет, разберём в секции 3, а пока зафиксируем: массовое редактирование через REST, это не про «кнопку для всех», а про гибкость: условия, фильтры, автоматизацию по расписанию.
REST API задачи Битрикс24: обзор методов для редактирования
Самый частый запрос на эту тему — «как программно поменять ответственного в 50 задачах» или «сдвинуть сроки по всем просроченным делам отдела». REST API Битрикс24 даёт для этого четыре базовых метода: task.item.get (получить одну задачу), task.item.list (выбрать список с фильтрацией), task.item.update (изменить поля) и task.item.delete (удалить). На практике основная нагрузка ложится на task.item.update — через него мы меняем ответственного, статус, дедлайн и пользовательские поля. Метод принимает ID задачи и массив изменяемых полей, остальное оставляет нетронутым. В комбинации с task.item.list получается готовый конвейер: сначала фильтруем нужные задачи, потом прогоняем через обновление. Эту механику мы закладываем в скрипты массового редактирования у клиентов.
| Метод | Описание | Обязательные поля | Примечание |
|---|---|---|---|
task.item.get |
Получить одну задачу по ID | TASK_ID |
Возвращает все поля задачи |
task.item.list |
Выбрать список задач с фильтром | Обязателен хотя бы один фильтр | |
task.item.update |
Изменить поля существующей задачи | TASK_ID, fields |
Не перезаписывает неуказанные поля |
task.item.delete |
Удалить задачу | TASK_ID |
Безвозвратно |
Чтобы собрать задачи для массового редактирования, используем task.item.list с фильтром. В наших проектах мы чаще всего фильтруем по трём измерениям: дата (срок до определённого числа или просроченные), статус (например, «в работе» или «ждут контроля») и ответственному. Вот как это выглядит на практике: фильтр ['>=DEADLINE' => '2025-04-01', 'STATUS' => 3, 'RESPONSIBLE_ID' => 1] вернёт все задачи ответственного с ID 1, которые в статусе «выполняется» и с дедлайном не раньше первого апреля. Если нужно выбрать просроченные, меняем условие на
Важный момент: метод возвращает максимум 50 записей за один вызов. Для больших выборок придётся перебирать страницы через параметр start. Это стандартная пагинация REST API, к ней быстро привыкаешь.
Batch update tasks bitrix24: как объединить запросы в пакет
Как только количество задач, которые нужно обновить, переваливает за десяток, последовательные вызовы BX24.callMethod превращаются в узкое горлышко. Ограничение 2 запроса в секунду на одно приложение — не гипотетическая угроза, а рабочая реальность для любого активного портала. Если у вас 200 просроченных задач, на которые нужно перенести дедлайн, последовательные запросы займут больше минуты. Batch-пакет решает это кардинально: вы упаковываете до 50 операций в один HTTP-вызов, и Битрикс24 выполняет их на своей стороне практически мгновенно. В наших проектах с массовым переносом ответственных или сдвигом сроков мы используем batch как основной инструмент — без него автоматизация на 200+ задач просто не укладывается в разумное время выполнения скрипта.
BX24.callBatch({ task_update_1: { METHOD: 'tasks.task.update', params: { taskId: 101, fields: { DEADLINE: '2025-06-01' } } }, task_update_2: { METHOD: 'tasks.task.update', params: { taskId: 102, fields: { DEADLINE: '2025-06-01' } } } }, function(RESULT) { /* обработка */ });Ключевой элемент здесь, массив callBatch, где каждый ключ (task_update_1, task_update_2…), это произвольный идентификатор, который вы сами назначаете. Он нужен только для того, чтобы потом сопоставить ответ с запросом. Внутри каждого элемента, стандартная структура REST-вызова: method и params. Первый параметр taskId, ID задачи, второй, массив изменяемых полей. Формировать такой массив удобно в цикле по массиву ID задач: просто подставляете ID и нужные поля. callBatch возвращает ответ сразу по всем операциям, а не по одной, в этом суть пакетной обработки.
Обработка результатов batch
После вызова BX24.callBatch вы получаете объект, где каждый ключ соответствует вашему идентификатору из запроса. Внутри — стандартная структура ответа SDK с методами data() и error(). Ваша задача — пройтись по всем элементам и обработать каждый отдельно, так как один запрос в пакете может выполниться успешно, а другой — упасть с ошибкой. Мы проверяем result.error(), и если он возвращает данные, используем свойства error и error_description для логирования ID задачи и причины сбоя, чтобы обработать её отдельно.
BX24.callBatch(commands, function(result) {
for (var commandId in result) {
var res = result[commandId];
if (res.error()) {
console.error('Ошибка в ' + commandId, res.error());
// логируем и идём дальше
} else {
console.log('Успешно:', commandId, res.data());
}
}
});Важно: batch-запрос не гарантирует транзакционность. Если один из 50 запросов в пакете упадёт с ошибкой (например, задача уже удалена), остальные 49 всё равно выполнятся. Это значит, что вы не можете полагаться на «всё или ничего», partial success, это нормальное поведение. В наших проектах мы всегда добавляем логику повторной обработки только для тех задач, которые вернули ошибку, а не перезапускаем весь пакет целиком.
$batch = [
'task_1' => [
'method' => 'task.item.update',
'params' => [1, ['TITLE' => 'Новый заголовок 1']]
],
'task_2' => [
'method' => 'task.item.update',
'params' => [2, ['TITLE' => 'Новый заголовок 2']]
],
'task_3' => [
'method' => 'task.item.update',
'params' => [3, ['TITLE' => 'Новый заголовок 3']]
]
];
$result = BX24::callBatch($batch);foreach ($result as $taskId => $response) {
if ($response['status'] === true && !$response['error']) {
echo "Задача $taskId обновлена успешно\n";
} else {
$error = $response['error'] ?? 'неизвестная ошибка';
echo "Ошибка в задаче $taskId: $error\n";
// Здесь можно добавить задачу в отдельный список для повторной обработки
}
}task.item.update
$batch
task_1
task_2
method
params
task.item.update
BX24::callBatch
callBatch
status
result
error
status
true
error
BX24.callMethod задачи: когда использовать одиночные запросы
Типичный сценарий: вы написали скрипт массового обновления через batch, запустили — и на середине ловите ошибку в одной задаче из пятидесяти. Или только начинаете прототипировать логику, и оборачивать один тестовый вызов в пакетный массив — лишняя возня. В этих случаях batch не нужен или невозможен. Единичные правки, отладка, проверка ответа конкретного метода, здесь работает синхронный BX24.callMethod. Мы используем его как «скальпель»: точечно, когда не требуется массовость, а нужна быстрая обратная связь от API. Он не умеет объединять запросы, но даёт немедленный результат и упрощает разбор ошибок.
$taskId = 123; // ID задачи, которую нужно обновить
$fields = [
'UF_CRM_TASK' => 'CO_4567', // Привязка к конкретной сделке
'DEADLINE' => '2024-12-31T18:00:00+03:00' // Новый срок
];
$result = BX24::callMethod(
'task.item.update',
[
'TASKID' => $taskId,
'FIELDS' => $fields
]
);
if (empty($result['error'])) {
echo "Задача #{$taskId} успешно обновлена.";
} else {
echo "Ошибка: " . $result['error_description'];
}Ключевое в этом коде — прямая передача параметров в метод REST API без дополнительной обёртки. При использовании BX24.callMethod ответ приходит в объект результата, который позволяет сразу проверить наличие ошибки. Именно здесь, а не в batch, мы ловим проблему на конкретном вызове и можем мгновенно получить её описание через метод error(). В пакетном режиме ошибка одной команды не прерывает весь batch, и её приходится выискивать в общем массиве ответов. Сравнение по времени: одиночный запрос к API занимает те же 300–500 мс, что и один элемент batch, но без накладных расходов на формирование пакета. Если вам нужно обновить одну задачу, BX24.callMethod будет быстрее и проще в отладке.
Автоматизация задач Б24: типовые сценарии с кодом
Перейдём от теории к практике. У нас в проектах три сценария массового обновления задач через REST API возникают регулярно — настолько часто, что мы держим готовые шаблоны скриптов в репозитории. Первый — перевод просроченных задач на другого ответственного, когда менеджер уволился или отдел перегружен. Второй, простановка единого тега всем задачам проекта, например, для квартального аудита. Третий, пакетное закрытие однотипных задач по ID, скажем, после релиза или миграции данных. Каждый из этих сценариев решается за 30–50 строк кода. Ниже разберём их по порядку, с рабочими скриптами, которые можно скопировать в ваш init.php или локальный скрипт.
Сценарий 1: Смена ответственного у просроченных задач
Типичная ситуация: в отделе продаж накопилось 40 задач с дедлайном «вчера», а ответственный заболел. Менять каждую вручную — час работы. Решаем это пакетным методом: получаем просроченные задачи через tasks.task.list с фильтром по дате, затем обновляем RESPONSIBLE_ID. Ключевой момент — использование префикса в параметре filter[<=DEADLINE] с указанием текущей даты в формате ISO 8601. Такой фильтр корректно отсекает задачи, у которых дедлайн не задан, и они не попадут в выборку.
<?php
// Получаем просроченные задачи (статус < 5, дедлайн просрочен)
$tasks = [];
$start = 0;
do {
$result = tasks::getList([
'order' => ['ID' => 'ASC'],
'filter' => [
'<STATUS' => 5,
'<DEADLINE' => ConvertTimeStamp(time(), 'FULL'),
],
'select' => ['ID', 'RESPONSIBLE_ID'],
'start' => $start,
'limit' => 50,
]);
while ($task = $result->fetch()) {
$tasks[] = $task['ID'];
}
$start += 50;
} while ($result->fetch());
// Batch-обновление: меняем ответственного на ID = 123
$batch = [];
foreach ($tasks as $id) {
$batch['cmd[' . $id . ']'] = 'tasks.task.update?taskId=' . $id . '&fields[RESPONSIBLE_ID]=123';
}
$batchResult = tasks::executeBatch($batch);
// Проверка ошибок — смотрите секцию про batch updateСценарий 2: Простановка тега всем задачам проекта
Когда нужно отметить все задачи конкретной группы, например, пометить «Аудит Q3» для 60 задач проектного отдела, ручная работа отнимает целый день. Делаем это скриптом: получаем все задачи по GROUP_ID, затем через task.item.update добавляем тег в поле TAGS. Если у задачи уже есть теги, их нужно сохранить, иначе они затрутся. В коде ниже мы объединяем существующие теги с новым, проверяя дубликаты через array_unique.
<?php
$groupId = 42; // ID рабочей группы проекта
$newTag = 'Аудит Q3';
// Получаем все задачи группы
$tasks = tasks::getList([
'filter' => ['GROUP_ID' => $groupId, '<STATUS' => 5],
'select' => ['ID', 'TAGS'],
])->fetchAll();
$batch = [];
foreach ($tasks as $task) {
$currentTags = explode(',', $task['TAGS'] ?? '');
$allTags = array_unique(array_merge($currentTags, [$newTag]));
$batch['cmd[' . $task['ID'] . ']'] = 'tasks.task.update?taskId=' . $task['ID'] .
'&fields[TAGS]=' . urlencode(implode(',', $allTags));
}
tasks::executeBatch($batch);Сценарий 3: Массовое закрытие задач по списку ID
Бывает, что после завершения проекта нужно закрыть 30–50 задач, которые остались в статусе «В работе». Вместо того чтобы открывать каждую, передаём список ID в batch-запрос и устанавливаем STATUS = 5 (завершена). Скрипт ниже принимает массив ID и пакетно обновляет их, одна секунда вместо получаса ручного кликанья.
<?php
$taskIds = [101, 102, 103, 104, 105]; // ID задач для закрытия
$batch = [];
foreach ($taskIds as $id) {
$batch['cmd[' . $id . ']'] = 'tasks.task.update?taskId=' . $id .
'&fields[STATUS]=5&fields[CLOSED_DATE]=' . urlencode(date('Y-m-d H:i:s'));
}
$result = tasks::executeBatch($batch);Важно: при закрытии задачи проверяйте, что она находится в активном статусе и не имеет открытых подзадач. В таких случаях STATUS = 5 может примениться, но задача завершится некорректно, так как подзадачи не закроются автоматически. Добавьте проверку текущего состояния и отсутствия подзадач в фильтр перед выполнением массового закрытия.
Где разместить скрипт массового редактирования: cron, агенты или REST-хук
После того как скрипт массового обновления задач написан, встаёт вопрос: где его выполнять, чтобы он работал стабильно и не мешал повседневной работе. В наших проектах мы рассматриваем три варианта: cron на сервере, агенты Битрикс24 и внешний вызов по расписанию через REST-хук. У каждого подхода есть сильные и слабые стороны. Выбор зависит от того, как часто нужно запускать скрипт, есть ли доступ к shell и насколько критична задержка выполнения. Разберём их по порядку.
- Cron на сервере — самый надёжный вариант. Плюсы: точное время старта, полный контроль над окружением, нет лимита на время выполнения. Минусы: нужен SSH-доступ к серверу и права на редактирование crontab, сложнее отлаживать.
- Агенты Битрикс24 — встроенный механизм. Плюсы: не требует доступа к серверу, настраивается через админку, автоматически перезапускается при сбое. Минусы: жёсткое ограничение времени выполнения (обычно 30 секунд), привязан к хиту, если на сайте нет посетителей, агент не запустится.
- Внешний планировщик через REST-хук, гибкое решение. Плюсы: можно вызывать из любой системы (Jenkins, GitHub Actions, облачные scheduler'ы), легко менять расписание без доступа к серверу. Минусы: нужен внешний сервис, скрипт должен быть доступен по URL, дополнительная точка отказа.
Наша рекомендация исходит из практики. Для регулярных задач, которые должны выполняться в строго определённое время, например, ежедневное обновление ответственных по просроченным задачам, используйте cron с PHP-скриптом. Вызовите скрипт через /usr/bin/php /path/to/script.php в crontab. Для одноразовых или редких операций, например, массовое обновление сроков после смены регламента, удобнее агент: зарегистрируйте его через CAgent::AddAgent() с датой следующего запуска. Пример настройки cron:
# Каждый день в 3:00 ночи
0 3 * * * /usr/bin/php /home/bitrix/www/local/scripts/update_task_deadlines.phpОшибки и подводные камни массового редактирования через REST
Самый частый запрос на эту тему — «скрипт обновил 30 задач, а 20 остались без изменений, и никакой ошибки в логах». В девяти случаях из десяти проблема не в коде, а в том, что REST API Битрикс24 требует учета технических ограничений. Превышение лимитов — при слишком высокой интенсивности запросов API может ограничивать их обработку. Неверные поля, например, попытка передать в UF_AUTO_123 строку, когда поле ожидает ID из справочника. Права доступа — если у пользователя, чей токен или вебхук используется, нет прав на изменение конкретной задачи (например, в закрытой группе), API вернет ошибку ACCESS_DENIED. Параллельные изменения: в проектах с активной автоматизацией, когда разные скрипты одновременно пытаются обновить сроки, ответственных или чек-листы в одной задаче, могут возникать конфликты данных. В таких ситуациях важно обеспечивать последовательность запросов, чтобы изменения не перезаписывали друг друга в процессе работы.
| Ошибка | Причина | Решение |
|---|---|---|
QUERY_LIMIT_EXCEEDED |
Более 2 запросов/сек | Встроить sleep(0.5) или batch |
ACCESS_DENIED |
Недостаточно прав | Проверить токен и роли |
ENTITY_NOT_FOUND |
Задача удалена | Проверить id перед запросом |
| Пустой ответ без кода | Блокировка задачи | Повтор через 2-3 секунды |
| Поле не обновилось | Неверный UF_* код |
Сверяться со словарём полей |
Разберём каждую ошибку подробнее. Лимит запросов, самый коварный, потому что API не кидает исключение, а просто перестаёт отвечать на «лишние» вызовы. Отловить это можно только по таймауту: если ответ пуст или пришёл с задержкой менее 50 мс, значит, вы в троттлинге. В batch-режиме эту проблему решает сам API (он сам распределяет нагрузку), но в одиночных вызовах мы ставим sleep(0.5) между запросами. Права доступа, частая история, когда скрипт запускается от админа, а REST-хук создан от имени обычного менеджера. Проверяйте $USER->GetID() внутри обработчика, если есть сомнения. Блокировка задачи, внутренний механизм Битрикс24: если задача открыта в браузере, API возвращает ACCESS_DENIED даже с корректным токеном. Лечится повторным запросом через 2–3 секунды. Неверные поля, особенно актуально для пользовательских полей UF_*: если поле хранит идентификатор элемента справочника, передача строки вместо числа пройдёт тихо, но значение не запишется.
Частые вопросы
Можно ли массово обновлять пользовательские поля (UF) задач через batch, и есть ли ограничения на их количество в одном запросе?
Да, UF-поля обновляются стандартно через метод tasks.task.update, передавая их в параметре fields. В одном batch-запросе можно передать до 50 команд, но каждое поле должно быть явно указано — не пытайтесь передать массив UF-значений без ключа, иначе получите ошибку 'UF field not found'.
Что делать, если при массовом редактировании часть задач не обновилась из-за ошибки 'Task not found' или 'Access denied'?
В ответе batch-запроса проверяйте поле 'result' на наличие ошибок для каждой команды. Для пропущенных задач запустите повторный batch только по ним, предварительно убедившись, что у токена есть права на чтение и изменение этих задач (например, через tasks.task.get с фильтром по ID).
Чем отличается передача параметров через 'fields' в tasks.task.update от прямого указания полей в теле запроса при одиночном вызове?
Разницы нет: в обоих случаях все изменяемые поля должны быть вложены в объект 'fields'. При batch-запросе структура команды та же: {'method': 'tasks.task.update', 'params': {'taskId': 123, 'fields': {'TITLE': 'Новое название'}}}.
А если у меня более 50 задач для обновления — как обойти лимит batch-запроса?
Разбейте задачи на пачки по 50 штук и выполняйте несколько последовательных batch-запросов. Между ними добавьте небольшую задержку (например, 1 секунду), чтобы не превысить лимиты REST API по количеству запросов в минуту.
Можно ли использовать batch для одновременного обновления задач и их чек-листов (checklist) в одном пакете?
Да, но учтите, что tasks.task.update не обновляет чек-листы — для этого используется метод task.checklistitem.add. В одном batch можно комбинировать оба метода, указывая taskId и передавая ID задачи из предыдущего ответа через result-зависимости.