Сценарий в списке зелёный, GET /api/v1/workflows/{id} возвращает "active": true, в Schedule Trigger задан корректный cron, ошибок в разделе Executions нет — но и самих выполнений нет. Ручной запуск работает. Вебхуки в том же сценарии работают. Не работает только расписание.
#Что происходит на самом деле
Когда сценарий обновляют программно, самый простой вариант кажется очевидным: выключить, залить новую версию, включить обратно. Примерно так:
curl -X POST "$BASE/api/v1/workflows/$ID/deactivate" -H "X-N8N-API-KEY: $KEY"
curl -X PUT "$BASE/api/v1/workflows/$ID" -H "X-N8N-API-KEY: $KEY" \
-H 'Content-Type: application/json' --data @workflow.json
curl -X POST "$BASE/api/v1/workflows/$ID/activate" -H "X-N8N-API-KEY: $KEY"Все три запроса возвращают 200. Последний возвращает объект сценария с "active": true. С точки зрения API операция выполнена.
Но триггер расписания в n8n — это не флаг в базе данных, а зарегистрированная задача в планировщике процесса. Активация через публичный API выставляет флаг, но не всегда восстанавливает эту регистрацию. Состояние в базе и состояние в планировщике расходятся, и снаружи это расхождение не видно нигде: ни в списке сценариев, ни в ответе API, ни в логах.
#Как обновлять сценарий правильно
Заливайте новую версию одним запросом PUT прямо в активный сценарий, ничего не выключая:
curl -X PUT "$BASE/api/v1/workflows/$ID" \
-H "X-N8N-API-KEY: $KEY" \
-H 'Content-Type: application/json' \
--data @workflow.jsonВот почему это работает. В публичном API поле active доступно только для чтения — оно не входит в тело запроса PUT, и запрос его не меняет. Значит, обновление активного сценария не сбрасывает его состояние: он остаётся активным. Изменение расписания планировщик подхватывает сам.
Мы это проверили: залили в активный сценарий новое расписание и дождались срабатывания в назначенную минуту, без деактивации.
#Как проверить, что расписание зарегистрировано
Флаг active ничего не подтверждает. Единственное подтверждение — факт выполнения. Самая простая проверка — поставить расписание на ближайшую минуту, дождаться её и посмотреть список выполнений:
# ближайшая минута в cron Schedule Trigger, залить PUT-ом, подождать,
# потом проверить, появилось ли выполнение типа trigger
curl -s "$BASE/api/v1/executions?workflowId=$ID&limit=5" \
-H "X-N8N-API-KEY: $KEY" \
| jq -r '.data[] | "\(.id) \(.mode) \(.status) \(.startedAt)"'Смотреть нужно именно на поле mode. Ручной запуск даёт manual, вебхук — webhook, и только расписание даёт trigger. Если после обновления в списке есть только manual, расписание не зарегистрировано — сколько бы раз API ни отвечал active: true.
#Что делать, если расписание уже не работает
Состояние планировщика восстанавливает переключатель Active в интерфейсе: выключите его вручную и включите обратно. Это ломает идею автоматической заливки, но как разовая процедура работает. После этого переходите на PUT без деактивации, и ситуация больше не повторится.
Перезапуск самого процесса n8n тоже восстанавливает регистрацию: при старте n8n заново читает расписания из базы данных. Если у вас Docker и перезапуск обходится дёшево, это быстрее, чем искать нужный сценарий в списке.
#Почему PUT удобен для сгенерированных сценариев
Запрос PUT заменяет сценарий целиком, вместе с идентификаторами нод. Если вы генерируете JSON скриптом и id нод каждый раз случайные, каждая заливка перестраивает связи и показывает изменения там, где ничего не менялось.
Чтобы этого не произошло, id ноды делают детерминированным — хешем от названия. Тогда повторная заливка не рвёт связи и показывает только настоящие изменения. Как это устроено, разобрано отдельно: n8n-сценарии в коде.
Вместе это даёт рабочий цикл: правка в генераторе → PUT → проверка выполнений. Без деактивации и без ручных действий в интерфейсе.
#Выводы
- Последовательность
deactivate+activateчерез публичный API возвращает200иactive: true, но расписание после этого может остаться незарегистрированным. - Обновляйте активный сценарий одним запросом
PUT— полеactiveв публичном API всё равно доступно только для чтения. - Проверяйте не флаг, а наличие выполнения с
mode: trigger. - Регистрацию восстанавливают переключателем Active в интерфейсе или перезапуском процесса.
- Детерминированные id нод делают повторную заливку безопасной.
#Частые вопросы
#Можно ли обновлять активный сценарий через API без деактивации?
Да. Поле active в публичном API доступно только для чтения, поэтому запрос PUT не меняет состояние сценария. Он остаётся активным, а планировщик подхватывает новое значение расписания сам.
#Почему API возвращает active: true, если расписание не работает?
Флаг active хранится в базе данных, а за расписание отвечает зарегистрированная задача в планировщике процесса. Это два разных состояния, и после активации через API они могут разойтись. Ответ API показывает только первое из них.
#Как быстро проверить, что триггер зарегистрирован?
Поставьте расписание на ближайшую минуту, дождитесь её и посмотрите GET /api/v1/executions. Если выполнение с mode: trigger не появилось, триггер не зарегистрирован.
#Источники
- n8n Public API — Workflow — описание методов и полей, в том числе того, что
activeне редактируется через API - n8n Docs — Schedule Trigger — как устроен триггер расписания
- Из собственного опыта