

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
scheduledUse case type
notificationReal-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.
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
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.
Optional
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Task Name | content | |
| Due Date | due.date | |
| Slack Channel | ||
7 optional fields▸ show
| Due Datetime | due.datetime |
| Assignee ID | assignee_id |
| Project ID | project_id |
| Priority | priority |
| Task URL | url |
| Labels | labels |
| Description | description |
Step-by-Step Setup
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.
- 1Click 'New Workflow' in the top right
- 2Type a name: 'Todoist Deadline Alerts to Slack'
- 3Click 'Create' to open the workflow canvas
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.
- 1Click 'Add Trigger'
- 2Search for and select 'Schedule'
- 3Set the interval to 'Custom (CRON expression)'
- 4Enter: 0 8 * * 1-5 (weekdays at 8am UTC — adjust for your timezone)
- 5Click 'Save and continue'
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.
- 1Click 'Add a step' below the trigger
- 2Search 'Todoist' in the app search bar
- 3Select the 'Get Tasks' action
- 4Click 'Connect Account' in the right panel
- 5Authorize Todoist in the OAuth popup that appears
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.
- 1In the Todoist step config, find the 'Filter' input field
- 2Type: overdue | today
- 3Optionally add project scope: overdue | today & #YourProjectName
- 4Leave 'Project ID' blank unless filtering by ID instead of filter string
- 5Click 'Test' to confirm the filter returns tasks
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.
- 1Click 'Add a step' below the Todoist step
- 2Select 'Run Node.js code'
- 3Delete the default placeholder code
- 4Paste the formatting code from the Pro Tip section
- 5Click 'Test' to verify the output object
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,
};
},
});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.
- 1Click 'Add a step' after the formatting step
- 2Select 'Run Node.js code'
- 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') }
- 4Click 'Test' to verify the guard behaves correctly when task arrays are empty
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.
- 1Click 'Add a step'
- 2Search 'Slack' and select the app
- 3Choose the 'Send Message to a Channel' action
- 4Click 'Connect Account'
- 5Authorize Pipedream in the Slack OAuth screen
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.
- 1In the Channel field, type or select your target channel (e.g. #project-deadlines)
- 2In the Text field, click the expression toggle ({{}})
- 3Reference your code step output: steps.format_tasks.$return_value.slackMessage
- 4Toggle 'Parse Markdown' or 'mrkdwn' to enabled
- 5Click 'Test' to send a real message to the channel
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.
- 1Click 'Run Now' in the top right of the canvas
- 2Watch each step light up green as it runs
- 3Click any step to inspect its input and output data
- 4Open Slack and verify the message posted to the correct channel
- 5Confirm overdue tasks and today's tasks are separated correctly
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.
- 1Click the 'Paused' toggle at the top of the canvas
- 2Confirm activation in the dialog that appears
- 3Navigate to the 'Runs' tab to verify the next scheduled run time
- 4Optionally enable email error alerts under Settings > Notifications
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
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.
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.
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 channels — Extend 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 Fridays — Create 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 button — Upgrade 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
How to Send Weekly Todoist Reports to Slack with Pipedream
~15 min setup
How to Send Weekly Todoist Reports to Slack with Power Automate
~15 min setup
How to Send Weekly Todoist Reports to Slack with n8n
~20 min setup
How to Send Weekly Todoist Reports to Slack with Zapier
~8 min setup
How to Send Weekly Todoist Reports to Slack with Make
~12 min setup
How to Assign Todoist Tasks from Slack Mentions with Pipedream
~15 min setup