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

How to Send Todoist Deadline Alerts to Slack with Pipedream

A scheduled Pipedream workflow that polls Todoist for tasks due today or overdue, then posts targeted Slack alerts to the right channel with task name, due date, and assignee.

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

Best for

Dev-adjacent teams who need deadline visibility in Slack and want full control over filtering logic, message format, and which channels get which alerts.

Not ideal for

Non-technical teams who want a point-and-click setup — Zapier or Make will get them live faster with no code required.

Sync type

scheduled

Use case type

notification

Real-World Example

💡

A 12-person product agency uses this to post overdue and same-day Todoist tasks into a #project-deadlines Slack channel every morning at 8am. Before the workflow, PMs had to manually scan Todoist each morning and DM teammates — tasks slipped because that check was skipped on busy days. Now every overdue item surfaces automatically with the assignee name and project label, and the team resolves most of them before standup.

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 Pipedream

Copy the pre-built Pipedream blueprint and paste it straight into Pipedream. 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 access — your account must have OAuth app permissions enabled (available on all plans including free)
Slack workspace where you have permission to install apps and post to the target channel
Pipedream account — free tier supports up to 10,000 credits/month which covers ~3,000 daily workflow runs

Optional

If using Todoist shared projects with multiple assignees, you need collaborator user IDs to map them to names in the code step

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Task Namecontent
Due Datedue.date
Slack Channel
7 optional fields▸ show
Due Datetimedue.datetime
Assignee IDassignee_id
Project IDproject_id
Prioritypriority
Task URLurl
Labelslabels
Descriptiondescription

Step-by-Step Setup

1

pipedream.com > Workflows > New Workflow

Create a new Pipedream workflow

Go to pipedream.com and click 'New Workflow' in the top-right corner of the Workflows dashboard. Give the workflow a clear name like 'Todoist Deadline Alerts to Slack'. This name appears in your workflow list and in error email subjects, so make it specific. You'll land on the workflow canvas where you'll add a trigger first.

  1. 1Click 'New Workflow' in the top right
  2. 2Type a name: 'Todoist Deadline Alerts to Slack'
  3. 3Click 'Create' to open the workflow canvas
What you should see: You see an empty workflow canvas with a prompt to add a trigger at the top.
2

Workflow Canvas > Add Trigger > Schedule

Add a Schedule trigger

Click 'Add Trigger' on the canvas and select 'Schedule' from the trigger list. This workflow runs on a cron schedule, not a webhook, because Todoist doesn't push deadline events — you have to go fetch them. Set the schedule to run once daily at a time that makes sense for your team, like 8:00am in your local timezone. Pipedream's Schedule trigger uses standard cron syntax if you want finer control.

  1. 1Click 'Add Trigger'
  2. 2Search for and select 'Schedule'
  3. 3Set the interval to 'Custom (CRON expression)'
  4. 4Enter: 0 8 * * 1-5 (weekdays at 8am UTC — adjust for your timezone)
  5. 5Click 'Save and continue'
What you should see: The trigger block shows your cron expression and a 'Next run' timestamp. You can see 'Schedule' labeled at the top of the canvas.
Common mistake — Pipedream's cron runs in UTC. A cron of '0 8 * * *' fires at 8am UTC — that's 3am EST. Add your UTC offset to the hour value or your alerts will arrive in the middle of the night.
Pipedream
+
click +
search apps
Slack
SL
Slack
Add a Schedule trigger
Slack
SL
module added
3

Workflow Canvas > Add Step > Todoist > Get Tasks

Connect your Todoist account

Click 'Add a step' below the trigger and search for 'Todoist'. Select the 'Get Tasks' action. In the step configuration panel on the right, click 'Connect Account' and authenticate with your Todoist credentials. Pipedream stores the token as a Connected Account — you won't need to paste it manually again in future steps or workflows.

  1. 1Click 'Add a step' below the trigger
  2. 2Search 'Todoist' in the app search bar
  3. 3Select the 'Get Tasks' action
  4. 4Click 'Connect Account' in the right panel
  5. 5Authorize Todoist in the OAuth popup that appears
What you should see: The step shows a green checkmark next to your Todoist account name, and the configuration fields for the action become editable.
Common mistake — The Todoist OAuth popup sometimes fails silently in Firefox. If the authorization window closes without a green checkmark, switch to Chrome for the auth step.
Pipedream settings
Connection
Choose a connection…Add
click Add
Slack
Log in to authorize
Authorize Pipedream
popup window
Connected
green checkmark
4

Workflow Canvas > Todoist Step > Filter Field

Configure the Todoist task filter

In the 'Get Tasks' step, find the Filter field. Todoist's API accepts filter strings using their built-in filter syntax. To catch overdue and today's tasks, enter: overdue | today. This fetches both categories in a single API call. You can also scope it to a specific project by appending: overdue | today & #ProjectName — replace ProjectName with your exact Todoist project name.

  1. 1In the Todoist step config, find the 'Filter' input field
  2. 2Type: overdue | today
  3. 3Optionally add project scope: overdue | today & #YourProjectName
  4. 4Leave 'Project ID' blank unless filtering by ID instead of filter string
  5. 5Click 'Test' to confirm the filter returns tasks
What you should see: The test run returns a JSON array of task objects. Each object includes id, content, due, assignee_id, project_id, and priority fields.
Common mistake — Todoist filter strings are case-sensitive for project names. '#marketing' won't match '#Marketing'. Check your exact project name in Todoist before saving the filter.
Slack
SL
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Todoist
TO
notified
5

Workflow Canvas > Add Step > Run Node.js code

Add a Node.js code step to format and filter tasks

Click 'Add a step' and select 'Run Node.js code'. This step processes the raw Todoist task array, separates overdue tasks from today's tasks, and builds the Slack message payload. Without this step, you'd post raw JSON to Slack or send one Slack message per task with no context — this step batches them into a single readable message. Paste the code from the Pro Tip section below into this step.

  1. 1Click 'Add a step' below the Todoist step
  2. 2Select 'Run Node.js code'
  3. 3Delete the default placeholder code
  4. 4Paste the formatting code from the Pro Tip section
  5. 5Click 'Test' to verify the output object
What you should see: The step returns a structured object with two arrays: overdueTasks and todayTasks, each containing formatted strings with task name, due date, and assignee. If no tasks match, both arrays are empty.
Common mistake — Todoist returns assignee_id as a numeric user ID, not a name. The code step handles this — but only if you've added the collaborator map. If you skip the map, all assignees will show as their user ID number in Slack.

Paste this into the Node.js code step (Step 5). It processes the raw Todoist task array from the previous step, separates overdue from today's tasks, resolves assignee IDs to names, applies priority emoji, and returns a single formatted Slack mrkdwn string ready to post.

JavaScript — Code Step// Step name in Pipedream: format_tasks
▸ Show code
// Step name in Pipedream: format_tasks
// Requires: steps.get_tasks.$return_value to be the Todoist task array
export default defineComponent({

... expand to see full code

// Step name in Pipedream: format_tasks
// Requires: steps.get_tasks.$return_value to be the Todoist task array

export default defineComponent({
  async run({ steps, $ }) {
    const tasks = steps.get_tasks.$return_value || [];
    const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD

    // Add your team's Todoist user IDs and names here
    const collaboratorMap = {
      '40182934': 'Marcus Reid',
      '40182967': 'Sarah Chen',
      '40182988': 'Priya Nair',
    };

    const priorityEmoji = (p) => {
      if (p === 4) return ' 🚨 Urgent';
      if (p === 3) return ' ⚠️ High';
      return '';
    };

    const formatTask = (task) => {
      const assignee = task.assignee_id
        ? collaboratorMap[task.assignee_id] || `User ${task.assignee_id}`
        : 'Unassigned';
      const dueLabel = task.due?.date || 'No date';
      const priority = priorityEmoji(task.priority);
      const link = task.url
        ? `<${task.url}|${task.content}>`
        : task.content;
      return `• ${link} — due ${dueLabel} — assigned to ${assignee}${priority}`;
    };

    // Separate overdue vs due today
    const overdueTasks = tasks
      .filter(t => t.due?.date && t.due.date < today)
      .map(formatTask);

    const todayTasks = tasks
      .filter(t => t.due?.date && t.due.date === today)
      .map(formatTask);

    // Build the Slack mrkdwn message
    const sections = [];

    if (overdueTasks.length > 0) {
      sections.push(`*🔴 Overdue Tasks (${overdueTasks.length})*\n${overdueTasks.join('\n')}`);
    }

    if (todayTasks.length > 0) {
      sections.push(`*📅 Due Today (${todayTasks.length})*\n${todayTasks.join('\n')}`);
    }

    const slackMessage = sections.join('\n\n');

    return {
      overdueTasks,
      todayTasks,
      slackMessage,
      totalCount: overdueTasks.length + todayTasks.length,
    };
  },
});
6

Workflow Canvas > Add Step > Run Node.js code

Add a filter step to skip empty runs

When no tasks are overdue or due today, you don't want Pipedream to post a 'nothing due' message to Slack every morning. Add another Node.js code step immediately after the formatting step. This step checks whether both task arrays are empty and throws an error to halt execution if so — Pipedream treats a thrown error as a workflow stop, so no Slack message gets sent.

  1. 1Click 'Add a step' after the formatting step
  2. 2Select 'Run Node.js code'
  3. 3Paste the early-exit guard: if (steps.format_tasks.$return_value.overdueTasks.length === 0 && steps.format_tasks.$return_value.todayTasks.length === 0) { $.flow.exit('No tasks due or overdue today') }
  4. 4Click 'Test' to verify the guard behaves correctly when task arrays are empty
What you should see: When task arrays are empty, the workflow shows 'Execution ended' in green — not an error. When tasks exist, execution continues to the Slack step.
Common mistake — $.flow.exit() is not the same as throwing an error. $.flow.exit() cleanly ends the run with a success status. Throwing an error will trigger your error notification settings and email you on every quiet day — use $.flow.exit() here.
7

Workflow Canvas > Add Step > Slack > Send Message to a Channel

Connect your Slack account

Click 'Add a step' and search for 'Slack'. Select the 'Send Message to a Channel' action. Click 'Connect Account' and authorize Pipedream to post to your Slack workspace. Pipedream will request the chat:write scope. You need to be a Slack workspace admin or have permission to install apps — if you see a 'requires admin approval' screen, your workspace has app install restrictions enabled.

  1. 1Click 'Add a step'
  2. 2Search 'Slack' and select the app
  3. 3Choose the 'Send Message to a Channel' action
  4. 4Click 'Connect Account'
  5. 5Authorize Pipedream in the Slack OAuth screen
What you should see: The Slack step shows your workspace name in green under 'Connected Account'. The Channel and Message fields are now editable.
8

Workflow Canvas > Slack Step > Channel + Text Fields

Configure the Slack message and channel

In the Slack step, set the Channel field to the target Slack channel — use the format #project-deadlines or paste the channel ID if you want to be precise. In the Text field, reference the formatted output from your Node.js step. Use Pipedream's double-brace expression syntax to insert the message string: {{steps.format_tasks.$return_value.slackMessage}}. Enable the 'Markdown' toggle so Slack renders bold text and bullet points correctly.

  1. 1In the Channel field, type or select your target channel (e.g. #project-deadlines)
  2. 2In the Text field, click the expression toggle ({{}})
  3. 3Reference your code step output: steps.format_tasks.$return_value.slackMessage
  4. 4Toggle 'Parse Markdown' or 'mrkdwn' to enabled
  5. 5Click 'Test' to send a real message to the channel
What you should see: A formatted Slack message appears in your target channel with overdue tasks listed under a bold header and today's tasks listed separately beneath it.
Common mistake — Pipedream's Slack action sends plain text by default. Without enabling mrkdwn, asterisks appear as literal characters (*Task Name*) instead of bold text. Toggle it on before testing.
9

Workflow Canvas > Run Now button (top right)

Test the full workflow end to end

Click 'Run Now' at the top of the canvas to trigger a manual test run. Pipedream will execute every step in order using live data. Watch each step turn green as it completes. If a step fails, click on it to see the full error log and the exact API response that caused the failure. Check your Slack channel for the message — verify the formatting, task names, and due dates look correct before deploying.

  1. 1Click 'Run Now' in the top right of the canvas
  2. 2Watch each step light up green as it runs
  3. 3Click any step to inspect its input and output data
  4. 4Open Slack and verify the message posted to the correct channel
  5. 5Confirm overdue tasks and today's tasks are separated correctly
What you should see: All steps show green checkmarks. Your Slack channel has a new message listing overdue tasks and tasks due today, formatted with headers and bullet points.
Pipedream
▶ Deploy & test
executed
Slack
Todoist
Todoist
🔔 notification
received
10

Workflow Canvas > Active/Paused toggle (top left)

Deploy the workflow

Click the toggle at the top of the canvas to switch the workflow from 'Paused' to 'Active'. Once active, Pipedream will run the workflow on your configured cron schedule automatically. You don't need to keep a browser tab open. Go to the workflow's 'Runs' tab to monitor execution history — each run logs inputs, outputs, and errors per step.

  1. 1Click the 'Paused' toggle at the top of the canvas
  2. 2Confirm activation in the dialog that appears
  3. 3Navigate to the 'Runs' tab to verify the next scheduled run time
  4. 4Optionally enable email error alerts under Settings > Notifications
What you should see: The toggle shows 'Active' in green. The Runs tab shows 'Next run at [your cron time]' and your test run in the history.

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 Pipedream for this if you need the Slack message format to be non-trivial. The task name alone isn't enough — you want priority emoji, clickable links, assignee names resolved from IDs, and overdue vs today separated into sections. That's 30 lines of JavaScript, and Pipedream runs it natively without any workaround. The second reason to pick Pipedream: the collaborator ID-to-name lookup. Todoist's API returns numeric user IDs, not names. Pipedream's Node.js step resolves them inline. The one scenario where you'd skip Pipedream: if your team has zero developer comfort and just needs task name plus due date in Slack with no formatting. Zapier handles that in 10 minutes with no code.

Cost

Pipedream's free tier gives you 10,000 credits per month. This workflow costs roughly 3 credits per run — one for the trigger, one for the Todoist step, one for the Slack step. Running once daily on weekdays = ~22 runs/month = 66 credits. That's well under the free limit even if you add a second daily run. Compare that to Zapier: this workflow is a multi-step Zap requiring a paid plan at $19.99/month minimum. Make's free tier allows 1,000 operations/month — at 3 ops per run this workflow costs 66 operations monthly, comfortably free. Pipedream and Make both run this for free. Zapier does not.

Tradeoffs

Make's biggest advantage here is the visual filter module — you can split overdue vs today tasks with a Router, no code needed, and each branch posts a differently formatted message. Zapier has a cleaner setup experience and gets non-technical PMs live in under 15 minutes if they don't care about message formatting. n8n lets you self-host, which matters if your Todoist data contains client-sensitive task names that shouldn't transit a cloud platform. Power Automate integrates directly with Microsoft Teams, which makes it irrelevant here — but if your team uses Teams instead of Slack, it's the right call. Pipedream is still the right pick for this specific combination because the Todoist assignee ID problem and the message formatting complexity both need code, and Pipedream's code step is the fastest way to write and deploy that code without managing infrastructure.

Three things you'll hit after setup. First: Todoist's filter API returns tasks based on your account's timezone setting, not UTC. If your Todoist account is set to Tokyo time and Pipedream runs at 8am UTC, you may get tomorrow's tasks or miss today's depending on the offset — check your Todoist timezone under Settings > General. Second: Slack's mrkdwn format requires the 'mrkdwn' field to be explicitly enabled in the API payload. Pipedream's pre-built Slack action has this as a toggle — if you miss it, asterisks render as literal characters. Third: if a task has no due date set in Todoist, the due field comes back as null, not a missing key. Your JavaScript must guard against this (t.due?.date) or you'll get a TypeError on the first dateless task and the entire workflow stops.

Ideas for what to build next

  • Route alerts by project to separate Slack channelsExtend the code step to map each task's project_id to a specific Slack channel, then call the Slack API once per channel instead of posting everything to one channel. A #marketing channel gets marketing project tasks, #engineering gets engineering tasks.
  • Add a weekly digest summary on FridaysCreate a second workflow on a Friday-only cron (0 9 * * 5) that fetches all tasks due in the next 7 days and posts a weekly preview to a #team-standup channel — gives the team a heads-up on the week ahead, not just the day.
  • Mark tasks complete from Slack using a buttonUpgrade the Slack message to use Block Kit with an interactive button, then add a second Pipedream workflow with an HTTP webhook trigger to receive the button click and call the Todoist API to close the task — no need to open Todoist at all.

Related guides

Was this guide helpful?
Slack + Todoist overviewPipedream profile →