Intermediate~20 min setupCommunication & Project ManagementVerified April 2026
Slack logo
Todoist logo

How to Send Todoist Deadline Alerts to Slack with n8n

A scheduled n8n workflow checks Todoist every 15 minutes for tasks due today or overdue and posts formatted alerts to designated Slack channels.

Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.

Best for

Small to mid-sized project teams who track deadlines in Todoist and need automatic Slack nudges before tasks slip through the cracks.

Not ideal for

Teams managing hundreds of tasks per day — at that volume, digest-style daily summaries per channel work better than per-task pings.

Sync type

scheduled

Use case type

notification

Real-World Example

💡

A 12-person product team at a SaaS company uses this to post overdue sprint tasks into #product-ops every 15 minutes. Before the automation, the PM manually scanned Todoist each morning and missed same-day deadline slippage until standup. Now a Slack message fires within 15 minutes of a task going overdue, tagging the assignee by name.

What Will This Cost?

Drag the slider to your expected monthly volume.

/mo
505005K50K

Each platform counts differently — Zapier: 1 task per trigger. Make: 1 operation per module per record. n8n: 1 execution per run.

Prices shown for annual billing. Based on published pricing as of April 2026.

Estimated ROI

1000

min saved/mo

$583

labor value/mo

Free

no platform cost

Based on ~2 min manual effort per operation at $35/hr fully loaded labor cost.

Implementation

Skip the setup

Import this workflow directly into n8n

Copy the pre-built n8n blueprint and paste it straight into n8n. All modules, filters, and field mappings are already configured — you just need to connect your accounts.

Before You Start

Make sure you have everything ready.

Todoist account with at least one project containing tasks that have due dates set
Todoist API token — found under Todoist Settings > Integrations > Developer > API token
Slack workspace where you have permission to add apps and post to target channels
Slack OAuth scopes granted: chat:write, channels:read, and channels:join (or manual bot invite to private channels)
n8n instance — either self-hosted (Docker or npm) or an n8n Cloud account with sufficient execution quota for your chosen polling interval

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Task IDid
Task Namecontent
Due Datedue.date
5 optional fields▸ show
Project IDproject_id
Assignee IDassignee_id
Prioritypriority
Task URLurl
Descriptiondescription

Step-by-Step Setup

1

n8n Canvas > + New Workflow

Create a new n8n workflow

Open your n8n instance and click the orange 'New Workflow' button in the top right of the canvas. Give the workflow a name like 'Todoist Deadline → Slack'. You'll land on an empty canvas with a single gray trigger node placeholder. This is where you'll build the entire flow from left to right.

  1. 1Click '+ New Workflow' in the left sidebar or top navigation
  2. 2Click the pencil icon next to 'My Workflow' and rename it to 'Todoist Deadline → Slack'
  3. 3Click the gray trigger node placeholder in the center of the canvas
What you should see: You should see an empty canvas with your new workflow name displayed at the top and a node picker panel open on the right.
2

Canvas > Trigger Node > Schedule Trigger

Add a Schedule trigger

Search for 'Schedule' in the node picker and select the Schedule Trigger node. Set the interval to every 15 minutes. This is the heartbeat of your workflow — it wakes the workflow up at regular intervals to check Todoist for approaching or overdue deadlines. Avoid setting this below 5 minutes; Todoist's REST API enforces rate limits and unnecessary polling adds no value.

  1. 1Type 'Schedule' in the node search panel
  2. 2Click 'Schedule Trigger' from the results
  3. 3Set 'Trigger Interval' to 'Minutes'
  4. 4Set the interval value to '15'
  5. 5Click 'Back to Canvas'
What you should see: The trigger node on your canvas should now display 'Every 15 minutes' as the configured interval.
Common mistake — n8n Cloud free tier limits workflow executions. At 15-minute intervals, this workflow fires ~96 times per day. Check your plan's execution quota before going live.
n8n
+
click +
search apps
Slack
SL
Slack
Add a Schedule trigger
Slack
SL
module added
3

Canvas > + Node > Todoist > Credentials > Create New

Connect your Todoist account

Click the '+' button to the right of the Schedule Trigger to add the next node. Search for 'Todoist' and select the Todoist node. In the parameters panel, click 'Create New Credential'. You'll be prompted to enter a Todoist API token — find this under Todoist Settings > Integrations > Developer > API token. Copy the token and paste it into n8n, then click 'Save'.

  1. 1Click the '+' connector on the right edge of the Schedule Trigger
  2. 2Search 'Todoist' in the node picker
  3. 3Select 'Todoist' from the results
  4. 4Click 'Credential for Todoist API' dropdown and select 'Create New'
  5. 5Paste your Todoist API token into the 'API Token' field
  6. 6Click 'Save' to store the credential
What you should see: The credential dropdown should now show your saved Todoist credential name with a green dot, indicating a valid connection.
Common mistake — Todoist API tokens are account-scoped, not project-scoped. This credential will have read access to all projects in that Todoist account. Use a dedicated service account if this is a shared team workspace.
n8n settings
Connection
Choose a connection…Add
click Add
Slack
Log in to authorize
Authorize n8n
popup window
Connected
green checkmark
4

Todoist Node > Resource: Task > Operation: Get All > Filters

Configure Todoist to fetch tasks with due dates

With the Todoist node selected, set the Resource to 'Task' and the Operation to 'Get All'. Under Filters, add a filter for 'Filter' and enter the Todoist filter string: 'overdue | today'. This uses Todoist's native filter syntax to return all tasks that are due today or already past due. Leave the limit at 100 unless your team has unusually large projects.

  1. 1Set 'Resource' to 'Task'
  2. 2Set 'Operation' to 'Get All'
  3. 3Toggle on 'Additional Fields'
  4. 4In the 'Filter' field type: overdue | today
  5. 5Leave 'Limit' at 100
What you should see: When you click 'Test Step', the node should return a list of JSON task objects. Each item will have fields like id, content, due.date, project_id, and assignee_id.
Common mistake — The filter string 'overdue | today' is case-sensitive and uses Todoist's own filter syntax — not a regex. If you type it incorrectly, the API returns an empty array with no error message, which makes it look like there are no tasks due.
5

Canvas > + Node > Code

Add a Code node to calculate urgency and format messages

Add a Code node after the Todoist node. This is where you calculate whether each task is overdue or due today, assign urgency labels, and build the Slack message text. Paste the JavaScript below into the code editor. The code iterates over every returned task, computes the difference between today's date and the task's due date, and tags each task as OVERDUE or DUE TODAY before passing it downstream.

  1. 1Click the '+' connector on the Todoist node
  2. 2Search 'Code' in the node picker and select the Code node
  3. 3Set 'Language' to 'JavaScript'
  4. 4Set 'Mode' to 'Run Once for All Items'
  5. 5Paste the pro tip code into the code editor
  6. 6Click 'Test Step' to verify output
What you should see: The Code node output should show each task with added fields: urgency_label (OVERDUE or DUE TODAY), days_overdue (a number), and slack_message (a formatted string ready to post).
Common mistake — n8n's Code node runs in a sandboxed Node.js environment. The built-in Date object uses the server's timezone. If your n8n instance is in UTC but your team is in EST, a task due at 11:59 PM EST may not appear until the next UTC day. Set your n8n instance timezone under Settings > General.

Paste this into the first Code node (Step 5). It runs once for all items, computes urgency and days overdue, resolves assignee IDs to Slack usernames via a hardcoded map (replace with your team's IDs), and builds the full Slack message string. The second block handles deduplication using n8n's static workflow data — paste that into the second Code node (Step 6).

JavaScript — Code Node// ── CODE NODE 1: Urgency calculation + message formatting ──
▸ Show code
// ── CODE NODE 1: Urgency calculation + message formatting ──
// Mode: Run Once for All Items
const items = $input.all();

... expand to see full code

// ── CODE NODE 1: Urgency calculation + message formatting ──
// Mode: Run Once for All Items

const items = $input.all();
const today = new Date();
today.setHours(0, 0, 0, 0);

// Replace these with your actual Todoist assignee_id → Slack username mappings
const assigneeMap = {
  '38291047': '@sarah.chen',
  '38291055': '@marcus.okafor',
  '38291062': '@james.liu',
};

const priorityLabels = {
  4: 'Urgent',
  3: 'High',
  2: 'Normal',
  1: 'Low',
};

const results = [];

for (const item of items) {
  const task = item.json;

  // Skip tasks with no due date
  if (!task.due || !task.due.date) continue;

  const dueDate = new Date(task.due.date);
  dueDate.setHours(0, 0, 0, 0);

  const diffMs = today - dueDate;
  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));

  let urgencyLabel;
  let emoji;

  if (diffDays > 0) {
    urgencyLabel = `OVERDUE (${diffDays} day${diffDays === 1 ? '' : 's'})`;
    emoji = '⚠️';
  } else if (diffDays === 0) {
    urgencyLabel = 'DUE TODAY';
    emoji = task.priority === 4 ? '🔴' : '📌';
  } else {
    // Not due yet — skip (remove this block if you want upcoming tasks too)
    continue;
  }

  const assignee = assigneeMap[task.assignee_id] || 'Unassigned';
  const priority = priorityLabels[task.priority] || 'Normal';
  const formattedDue = dueDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });

  const slackMessage = [
    `${emoji} *${urgencyLabel}* — ${task.content}`,
    `📅 Due: ${formattedDue} | Priority: ${priority}`,
    `👤 Assignee: ${assignee}`,
    `🔗 ${task.url}`,
  ].join('\n');

  results.push({
    json: {
      task_id: task.id,
      task_name: task.content,
      due_date: task.due.date,
      days_overdue: diffDays,
      urgency_label: urgencyLabel,
      assignee_slack: assignee,
      slack_message: slackMessage,
    },
  });
}

return results;


// ── CODE NODE 2: Deduplication using static workflow data ──
// Mode: Run Once for All Items
// Paste this into the SECOND Code node

/*
const items = $input.all();
const staticData = $getWorkflowStaticData('global');

// Initialize the notified IDs store if it doesn't exist
if (!staticData.notifiedIds) {
  staticData.notifiedIds = [];
}

const newItems = [];
const newlyNotified = [];

for (const item of items) {
  const taskId = item.json.task_id;
  if (!staticData.notifiedIds.includes(taskId)) {
    newItems.push(item);
    newlyNotified.push(taskId);
  }
}

// Add newly notified IDs to the store
staticData.notifiedIds = [...staticData.notifiedIds, ...newlyNotified];

// Cap the store at 500 IDs to prevent unbounded growth
if (staticData.notifiedIds.length > 500) {
  staticData.notifiedIds = staticData.notifiedIds.slice(-500);
}

return newItems;
*/
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
6

Canvas > + Node > Code (second instance)

Add a deduplication check with n8n's Static Data

To avoid spamming Slack with the same task every 15 minutes, add a second Code node that uses n8n's $getWorkflowStaticData() to store IDs of tasks already notified. On each run, the node filters out tasks whose IDs are already in the static data store and only passes new ones downstream. It then updates the store with the newly notified IDs. Tasks are cleared from the store once they no longer appear in the Todoist filter (meaning they were completed or rescheduled).

  1. 1Click the '+' connector on the first Code node
  2. 2Add another Code node
  3. 3Set Mode to 'Run Once for All Items'
  4. 4Paste the deduplication logic from the pro tip code's second function
  5. 5Click 'Test Step' and verify only new task IDs pass through
What you should see: On the first run, all tasks pass through. On the second run with the same tasks, zero items should pass through — confirming deduplication is working.
Common mistake — Static data in n8n persists per workflow, not per execution. If you duplicate the workflow, both copies share nothing — each maintains its own static data store. This is the behavior you want.
7

Canvas > + Node > Slack > Credentials > OAuth2

Connect your Slack account

Add a Slack node after the deduplication Code node. Click 'Create New Credential' and select 'OAuth2'. n8n will open a pop-up to authorize your Slack workspace. Sign in and grant the requested permissions — you need chat:write and channels:read at minimum. If you want to post to private channels, also grant chat:write.customize and the bot must be invited to those channels manually.

  1. 1Click '+' after the deduplication Code node
  2. 2Search 'Slack' and select the Slack node
  3. 3Click 'Credential for Slack API' and choose 'Create New'
  4. 4Select 'OAuth2 (recommended)'
  5. 5Click 'Connect my account' and authorize in the Slack pop-up
  6. 6Select your workspace and click 'Allow'
What you should see: The credential field should display your Slack workspace name with a green connected indicator. You should now be able to select channels in the Slack node's configuration.
Common mistake — If your Slack workspace has an admin-approval requirement for OAuth apps, the authorization pop-up will show a 'Request Approval' screen instead of 'Allow'. You'll need a Slack admin to approve the n8n app before continuing.
8

Slack Node > Resource: Message > Operation: Send

Configure the Slack message node

With the Slack node selected, set Resource to 'Message' and Operation to 'Send'. For 'Channel', type the exact channel name including the '#' symbol (e.g. #project-deadlines). In the 'Text' field, click the expression toggle (the '{ }' icon) and reference the slack_message field from the Code node output: {{ $json.slack_message }}. This injects the formatted message text built in Step 5.

  1. 1Set 'Resource' to 'Message'
  2. 2Set 'Operation' to 'Send'
  3. 3Enter your target channel name in 'Channel' (e.g. #project-deadlines)
  4. 4Click the expression toggle '{ }' next to the 'Text' field
  5. 5Type: {{ $json.slack_message }}
  6. 6Optionally set 'Username' to 'Deadline Bot' for a cleaner display name
What you should see: When you click 'Test Step' with a task in the pipeline, you should see a message appear in your Slack channel within a few seconds.
Common mistake — Slack channel names are case-sensitive in the API. '#Project-Deadlines' and '#project-deadlines' are different channels. Always use lowercase exactly as it appears in Slack.
9

Todoist Node > ... menu > Add Error Output > connect to Slack (alerts channel)

Add error handling with a Stop and Error node

Click the three-dot menu on the Todoist node and select 'Add Error Output'. Connect the error output to a Slack node configured to post to a #workflow-alerts or #ops channel with the message 'Todoist Deadline workflow failed: {{ $json.message }}'. Do the same for the Slack node itself. This means if the Todoist API is down or your Slack token expires, you get notified instead of silently missing deadline alerts.

  1. 1Right-click the Todoist node and select 'Add Error Output'
  2. 2Connect the red error output connector to a new Slack node
  3. 3Configure that Slack node to post to your internal alerts channel
  4. 4Set the message text to: 'Deadline workflow error: {{ $json.message }}'
  5. 5Repeat for the main Slack node's error output
What you should see: Your canvas should now show two paths from the Todoist node — the green success path continuing to the Code node, and a red error path going to the alert Slack node.
10

Canvas > Test Workflow button (top right)

Test end-to-end with a real Todoist task

Create a test task in Todoist with today's date as the due date. Go back to n8n and click 'Test Workflow' (not 'Execute Workflow' — that saves first). Watch each node light up green as data flows through. Verify the Slack message appears in your channel with the correct task name, due date, and urgency label. Check that running the test a second time produces no duplicate Slack message, confirming deduplication works.

  1. 1Create a Todoist task titled 'TEST: Deadline check' due today
  2. 2Return to n8n and click the 'Test Workflow' button
  3. 3Watch each node turn green as execution proceeds
  4. 4Verify the message appears in Slack within 30 seconds
  5. 5Click 'Test Workflow' again and confirm no duplicate message is sent
What you should see: The Slack channel should show exactly one message for your test task after two test runs. Each node on the canvas should display a green checkmark and show the data that passed through it.
n8n
▶ Run once
executed
Slack
Todoist
Todoist
🔔 notification
received
11

Canvas > Active/Inactive toggle (top right)

Activate the workflow

Click the gray 'Inactive' toggle in the top right of the canvas to switch it to 'Active'. n8n will immediately schedule the first execution based on your 15-minute interval. The workflow will now run automatically without you needing to keep the browser open. Check the 'Executions' tab after 30 minutes to confirm the first scheduled run completed successfully.

  1. 1Click 'Save' to save the workflow
  2. 2Click the 'Inactive' toggle to flip it to 'Active'
  3. 3Confirm the toggle turns green and shows 'Active'
  4. 4Navigate to the 'Executions' tab in the left sidebar
  5. 5Wait 15 minutes and refresh — you should see a completed execution entry
What you should see: The workflow toggle should be green and labeled 'Active'. The Executions tab should show a new entry every 15 minutes with a green status icon.
Common mistake — Activating a workflow on n8n Cloud counts against your execution quota immediately. If you're on the Starter plan (2,500 executions/month), a 15-minute schedule consumes ~2,880 executions/month — over quota. Use a 30-minute interval instead, which costs ~1,440 executions/month.

Going live

Production Checklist

Before you turn this on for real, confirm each item.

Troubleshooting

Common errors and how to fix them.

Frequently Asked Questions

Common questions about this workflow.

Analysis

VerdictWhy n8n for this workflow

Use n8n for this if you self-host your stack, have tasks with complex routing logic (per-project channels, priority-based filtering, assignee tagging), or want zero per-execution cost. The code node gives you full control — you can compute days overdue, format messages exactly how your team wants, and handle Todoist's occasional null fields without workarounds. The one scenario where you'd skip n8n: if your team has no one comfortable reading 30 lines of JavaScript and you just want alerts firing in under 10 minutes. That's a Zapier job.

Cost

At a 15-minute polling interval, this workflow executes ~2,880 times per month. Each execution is a single workflow run regardless of how many tasks are returned. On n8n Cloud, the Starter plan caps at 2,500 executions/month ($20/month) and the Pro plan gives you 10,000 ($50/month). Self-hosted n8n is free — you pay only for server costs. Zapier charges per task, not per run: if 5 tasks fire in one check, that's 5 Zap tasks. At $19.99/month for 750 tasks, 5 overdue tasks per check × 96 checks/day × 30 days = 14,400 tasks/month, which requires Zapier's $49/month Professional plan. n8n Cloud Pro is $50/month and covers this volume with no task-count math.

Tradeoffs

Make handles this use case well with its built-in scheduler and Todoist + Slack modules — no code required, and the visual router handles per-project channel logic cleanly. Zapier is faster to set up (roughly 8 minutes) but hits task-count limits fast on active projects. Power Automate has a Todoist connector but it's limited to premium plans and the connector doesn't support Todoist's filter syntax, so you'd have to use HTTP requests anyway. Pipedream's Node.js environment is functionally equivalent to n8n's Code node but costs $0 for low-volume use — if you're self-hosting n8n purely for this one workflow, Pipedream is cheaper. n8n wins when this workflow is part of a larger self-hosted automation stack and you're already running the instance.

Three things you'll hit after setup. First: Todoist's filter API returns tasks based on the account's timezone setting, not UTC. If your n8n server is in UTC and your Todoist account timezone is set to US/Pacific, tasks due 'today' in Pacific time won't appear until 8 AM UTC — that's a 5-hour gap where overdue tasks don't fire. Fix it by setting both n8n's instance timezone and your Todoist account timezone to match. Second: the static data store that prevents duplicate notifications is tied to the workflow's activation state. If you deactivate and reactivate the workflow (e.g., during debugging), the store resets and every currently-overdue task fires again as if it's new. Expect a burst of duplicate Slack messages after any workflow reactivation. Third: Todoist's task URL field (url) is present in the v2 REST API but absent in older v1 endpoints. If you migrated an older Todoist integration, confirm you're hitting api.todoist.com/rest/v2/tasks — v1 URLs will return tasks without the url field and your Slack messages will have a broken link.

Ideas for what to build next

  • Add a daily digest instead of per-task pingsChange the Schedule Trigger to fire once per day at 8 AM and modify the Slack node to send a single aggregated message listing all overdue and due-today tasks in a numbered list. This reduces notification fatigue while keeping the team informed.
  • Route alerts to per-project Slack channelsAdd a Switch node between the Code node and the Slack node that checks task.project_id and routes each task to a different Slack channel based on which project it belongs to. Map your Todoist project IDs to channel names in a lookup object inside the Switch node.
  • Sync task completion back to a Slack threadAdd a second workflow that uses a Todoist webhook (via n8n's webhook trigger) to listen for task completion events and post a ✅ reply in the original Slack notification thread, giving the team a closed-loop confirmation without checking Todoist manually.

Related guides

Was this guide helpful?
Slack + Todoist overviewn8n profile →