Schedule icon
If icon
Fail icon
ListTasks icon
Loop icon
DeleteTask icon
SlackIncomingWebhook icon

Supervised Deletion of Stale Todoist Tasks Older Than 90 Days

Delete stale Todoist tasks older than 90 days with Kestra. A confirm input gates the sweep, Loop deletes each task, and Slack gets the audit count.

Categories
Business

Every task list accumulates a guilt layer: items created a quarter ago that will never be done and only add noise. This blueprint performs list bankruptcy as a supervised, audited flow. A Todoist filter query matches tasks created more than 90 days ago, a Loop deletes each one through io.kestra.plugin.todoist.DeleteTask, and the whole thing is gated by a boolean confirm input: when it is false, the flow fails immediately with a message demanding explicit confirmation, and nothing is listed or deleted.

How it works

  1. require_confirmation (io.kestra.plugin.core.flow.If) checks the confirm input. When it is false, the nested io.kestra.plugin.core.execution.Fail task stops the execution with an instructive error before any Todoist call is made.
  2. list_stale (io.kestra.plugin.todoist.ListTasks) runs the Todoist filter query created before: -90 days with fetchType: FETCH. The matches are exposed as {{ outputs.list_stale.rows }} and the count as {{ outputs.list_stale.size }}. Adjust the window by editing the filter string.
  3. loop_tasks (io.kestra.plugin.core.flow.Loop) iterates over the rows, and delete_task removes each task by fromJson(item.value).id. Deletion is permanent, which is exactly why the guard exists.
  4. audit posts the deleted count to Slack, and the errors block reports both real failures and the intentional refusal when confirmation is missing.
  5. A disabled-by-default monthly Schedule runs on the first of the month. With the default confirm: false it fails at the guard on purpose, turning the schedule into a monthly reminder that a human must re-run with confirm: true.

What you get

  • A destructive operation that is impossible to run by accident: no confirmation, no deletion, no API calls.
  • A Todoist-native definition of stale through the created before: filter, tunable to any window.
  • Per-task deletions inside the Loop, so one failing delete does not hide how far the sweep got.
  • A Slack audit line for every sweep, building a paper trail of what was removed and when.

Who it's for

  • Long-time Todoist users whose list has become an archive of good intentions.
  • Ops teams enforcing a retention policy on shared task projects.
  • Anyone who wants periodic cleanup with a human sign-off rather than a silent cron job.

Why orchestrate this with Kestra

A cleanup script with a delete loop is one typo away from disaster and leaves no trace. Kestra adds the guard rail as a first-class flow structure, records every execution including refused ones, isolates each deletion, and posts an audit trail to Slack, all without writing a line of imperative code.

Prerequisites

  • A Todoist account and a personal API token.
  • A Slack incoming webhook for audit messages and failure alerts.
  • The created before: -90 days filter uses Todoist's filter query syntax; verify it returns what you expect in the Todoist app before enabling deletions.

Secrets

  • TODOIST_API_TOKEN: Todoist personal API token.
  • SLACK_WEBHOOK_URL: Slack incoming webhook URL.

Quick start

  1. Add the two secrets to your Kestra namespace.
  2. Test the filter created before: -90 days in Todoist to preview exactly what would be deleted.
  3. Execute the flow with confirm: false and watch it refuse, then re-run with confirm: true on a test account or narrow project.
  4. Check the Slack audit count, then set disabled: false on the monthly trigger if you want the monthly reminder behavior.

How to extend

  • Scope the sweep to one project by adding projectId to list_stale, a safer default for a first rollout.
  • Soften the bankruptcy: swap DeleteTask for io.kestra.plugin.todoist.UpdateTask and demote instead of delete.
  • Export {{ outputs.list_stale.rows }} to storage before deleting, creating a recoverable archive of what was swept.
  • Tighten or loosen the staleness window by editing the number of days in the filter.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.