

How to Automate Daily Standups from Asana to Slack with n8n
Every morning at a scheduled time, n8n pulls completed Asana tasks and upcoming deadlines from the previous 24 hours, formats them into a structured standup report, and posts it to a Slack channel — no meeting required.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Engineering or product teams of 5–25 people who track all work in Asana and want async standups delivered to Slack without anyone manually compiling updates.
Not ideal for
Teams not using Asana as their primary task tracker — if work lives in Jira, Linear, or spreadsheets, start there instead.
Sync type
scheduledUse case type
reportingReal-World Example
A 12-person product team at a B2B SaaS company runs this workflow at 9:00 AM every weekday. Before it existed, the engineering lead spent 10–15 minutes each morning pulling together task updates from Asana and pasting them into Slack. Now the #standup channel receives a formatted digest automatically: tasks completed yesterday, tasks due today, and anything overdue. The lead uses that 15 minutes to actually prepare for the meeting instead.
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 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.
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Task Name | name | |
| Assignee Name | assignee.name | |
| Completed At | completed_at | |
| Due On | due_on | |
| Task Type (custom stamp) | ||
| Slack Channel ID | ||
3 optional fields▸ show
| Project Name | memberships[0].project.name |
| Task URL | permalink_url |
| Notes / Description | notes |
Step-by-Step Setup
n8n Canvas > + New Workflow
Create a new n8n workflow
Open your n8n instance and click the '+New Workflow' button in the top-left corner of the canvas. Give it a clear name like 'Daily Standup — Asana to Slack'. You'll see an empty canvas with a single '+' node placeholder in the center. This is where the trigger goes. Save the workflow immediately before adding nodes so you don't lose the name.
- 1Click '+ New Workflow' in the left sidebar
- 2Click the pencil icon next to 'My Workflow' and rename it 'Daily Standup — Asana to Slack'
- 3Press Enter to save the name
- 4Click the '+' node placeholder in the canvas center
Node Picker > Schedule Trigger > Settings
Add the Schedule trigger
In the node picker, search for 'Schedule' and select the 'Schedule Trigger' node. This fires the workflow at a fixed time every day. Click on the node after adding it to open its settings panel on the right. Set the trigger mode to 'Cron' and enter a cron expression for your standup time — for 9:00 AM Monday through Friday in UTC, use '0 9 * * 1-5'. Adjust for your team's timezone offset from UTC.
- 1Type 'Schedule' in the node search box
- 2Click 'Schedule Trigger' to add it to the canvas
- 3Click the node to open its settings panel
- 4Set 'Trigger Interval' to 'Custom (Cron)'
- 5Enter '0 9 * * 1-5' in the cron expression field
Node Picker > Asana > Task > Search
Connect Asana and fetch completed tasks
Click the '+' connector on the right side of the Schedule Trigger node to add the next node. Search for 'Asana' and select it. In the Asana node settings, set the Resource to 'Task' and the Operation to 'Search'. You'll need to create an Asana credential first — click 'Create New Credential', select 'Asana API', and paste your personal access token from Asana's developer console. Set the Workspace ID and Project ID to the project you want to pull tasks from.
- 1Click the '+' connector on the Schedule Trigger node
- 2Search 'Asana' in the node picker and select it
- 3Click 'Credential' dropdown and choose 'Create New Credential'
- 4Select 'Asana API' and paste your Personal Access Token
- 5Set Resource to 'Task', Operation to 'Search'
- 6Enter your Asana Workspace GID and Project GID in the respective fields
Asana Node > Additional Fields > Completed Since
Filter for tasks completed in the last 24 hours
The Asana Search operation returns all tasks matching your filters. You need to scope it to tasks completed since yesterday. In the Asana node's 'Additional Fields' section, add 'Completed Since' and set it to an expression. Click the expression editor (the gear icon next to the field) and enter: '{{ new Date(Date.now() - 86400000).toISOString() }}'. This generates an ISO timestamp for exactly 24 hours ago. Also set 'Completed' to true so you only get finished tasks.
- 1Scroll to 'Additional Fields' in the Asana node settings
- 2Click 'Add Field' and select 'Completed Since'
- 3Toggle the field to expression mode by clicking the gear/expression icon
- 4Paste: {{ new Date(Date.now() - 86400000).toISOString() }}
- 5Add another field: set 'Completed' to 'true'
Node Picker > Asana > Task > Search (second instance)
Add a second Asana node for upcoming deadlines
You need a separate Asana query to fetch tasks due today or overdue. Add another Asana node connected to the Schedule Trigger (not chained from the first Asana node — both run in parallel). Set this one to Resource 'Task', Operation 'Search', same credentials and project. In Additional Fields, set 'Due On' to today's date using the expression '{{ new Date().toISOString().split("T")[0] }}'. Also add a second variant of this node filtered to 'Due Before' today to catch overdue tasks.
- 1Click on the Schedule Trigger node to select it
- 2Click the '+' connector to add a second branch
- 3Search and add another Asana node
- 4Set Resource to 'Task', Operation to 'Search', use the same credential
- 5In Additional Fields, set 'Due On' using the date expression
- 6Duplicate this node and change 'Due On' to 'Due Before' with today's date for overdue tasks
Node Picker > Merge > Combine > Merge By Position
Merge all three data streams
Add a 'Merge' node and connect all three Asana nodes into it. The Merge node will wait for all branches to complete before proceeding. Set the merge mode to 'Combine' and the combination mode to 'Merge By Position' — this keeps all task data from all three queries accessible downstream. Click the node and verify all three inputs appear in the inputs list on the left panel.
- 1Search 'Merge' in the node picker and add it to the canvas
- 2Drag a connector from each of the three Asana nodes into the Merge node
- 3Click the Merge node to open settings
- 4Set 'Mode' to 'Combine'
- 5Set 'Combination Mode' to 'Merge By Position'
Node Picker > Code > JavaScript
Format the standup message with a Code node
Add a Code node after the Merge node. This is where you build the actual Slack message. The Code node runs JavaScript and has access to all merged items from upstream. Write logic that groups tasks by type (completed, due today, overdue), extracts task names and assignees, and builds a Slack Block Kit JSON payload. See the pro tip code below for the full implementation. Paste the code into the Code node's editor and click 'Execute Node' to test.
- 1Click '+' after the Merge node and search 'Code'
- 2Select 'Code' and click to open the editor
- 3Set the language to 'JavaScript'
- 4Paste the pro tip code into the editor
- 5Click 'Execute Node' to preview the formatted output
Paste this into the Code node (Step 7). It reads all merged items, splits them by 'task_type', formats the dates into human-readable strings, and returns a Slack Block Kit payload with three labeled sections plus a divider. The output goes directly into the Slack node's 'Blocks' expression field.
JavaScript — Code Node// n8n Code Node — Daily Standup Formatter▸ Show code
// n8n Code Node — Daily Standup Formatter // Reads all merged Asana task items and builds a Slack Block Kit payload const items = $input.all();
... expand to see full code
// n8n Code Node — Daily Standup Formatter
// Reads all merged Asana task items and builds a Slack Block Kit payload
const items = $input.all();
// Group tasks by type stamped in the Set node
const completed = items.filter(i => i.json.task_type === 'completed');
const dueToday = items.filter(i => i.json.task_type === 'due_today');
const overdue = items.filter(i => i.json.task_type === 'overdue');
// Format a date string for the header
const today = new Date();
const dateLabel = today.toLocaleDateString('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric'
});
// Helper: build a bullet line with Slack hyperlink
function formatTask(task) {
const name = task.json.name || 'Unnamed task';
const assignee = task.json.assignee?.name || 'Unassigned';
const url = task.json.permalink_url || '';
if (url) {
return `• <${url}|${name}> — ${assignee}`;
}
return `• ${name} — ${assignee}`;
}
// Helper: build a section block or a placeholder if empty
function buildSection(emoji, title, taskList) {
const lines = taskList.length > 0
? taskList.map(formatTask).join('\n')
: '_None_';
return {
type: 'section',
text: {
type: 'mrkdwn',
text: `${emoji} *${title}*\n${lines}`
}
};
}
// Assemble the Block Kit payload
const blocks = [
{
type: 'header',
text: {
type: 'plain_text',
text: `📋 Daily Standup — ${dateLabel}`,
emoji: true
}
},
{ type: 'divider' },
buildSection('✅', 'Completed Yesterday', completed),
{ type: 'divider' },
buildSection('📅', 'Due Today', dueToday),
{ type: 'divider' },
buildSection('🔴', 'Overdue', overdue),
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `Generated by n8n at ${new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })} • <https://app.asana.com|View in Asana>`
}
]
}
];
// Return as a single item so the Slack node receives one message payload
return [{ json: { blocks } }];Node Picker > Slack > Message > Post
Connect Slack and configure the message post
Add a Slack node after the Code node. Set the Resource to 'Message' and Operation to 'Post'. Create Slack credentials by clicking 'Create New Credential' — you'll need a Slack Bot Token (starts with 'xoxb-') from your Slack app's OAuth settings. Set the Channel to the exact channel name or ID where standups should post, e.g. '#standup'. In the 'Blocks' field, click the expression toggle and reference the blocks array from the Code node: '{{ $json.blocks }}'.
- 1Click '+' after the Code node and search 'Slack'
- 2Select the Slack node and set Resource to 'Message', Operation to 'Post'
- 3Click 'Create New Credential' and paste your Slack Bot Token
- 4Enter the target channel name in the 'Channel' field (e.g. #standup)
- 5Toggle 'Blocks' field to expression mode and enter {{ $json.blocks }}
- 6Set 'Text' to a fallback string like 'Daily Standup Report' for notification previews
channel: {{channel}}
ts: {{ts}}
Node Settings > Error Output > Slack (fallback)
Add error handling with a fallback Slack alert
n8n lets you add error workflows or use the built-in error output. Click the three-dot menu on any failing node to see error outputs. For production, add a separate Slack node connected to the error output of the Asana and Code nodes. This fallback node posts a simple error alert to a #alerts channel with the error message. Set the Slack message text to '{{ $json.error.message }}' to surface the exact failure reason.
- 1Click any critical node (e.g., the first Asana node) to select it
- 2Click the red error output connector on the node's bottom-right
- 3Add a Slack node connected to this error output
- 4Set the channel to '#alerts' or your team's error channel
- 5Set the message text to 'Standup workflow failed: {{ $json.error.message }}'
- 6Repeat for the Code node and the second Asana node
n8n Canvas Toolbar > Execute Workflow
Test with a manual execution
Before activating the schedule, run the workflow manually to verify the full chain. Click 'Execute Workflow' in the top toolbar. Watch each node light up green as it completes. Check the Slack channel to confirm the message posted correctly with the right task names. If any node turns red, click it to see the error details in the output panel. Fix issues before enabling the schedule.
- 1Click 'Execute Workflow' in the top-center toolbar
- 2Watch the execution flow left to right across the canvas
- 3Click any node to inspect its input and output data
- 4Open Slack and confirm the standup message appeared in the correct channel
- 5Check that completed tasks, due-today tasks, and overdue tasks each appear under the right section
n8n Canvas > Active Toggle (top right)
Activate the workflow
Once the test passes, flip the 'Active' toggle in the top-right of the n8n canvas. The workflow will now run automatically on the cron schedule you set in Step 2. You can verify the next scheduled run time by hovering over the Schedule Trigger node — it shows the next execution timestamp. Check the Executions tab in the left sidebar the next morning to confirm the first scheduled run completed successfully.
- 1Click the gray 'Inactive' toggle in the top-right corner of the canvas
- 2Confirm it turns green and reads 'Active'
- 3Click 'Save' to persist the active state
- 4Navigate to the 'Executions' tab in the left sidebar
- 5Check back the next scheduled morning to verify the first automatic run
Scaling Beyond 200+ tasks returned per Asana query+ Records
If your volume exceeds 200+ tasks returned per Asana query records, apply these adjustments.
Handle Asana API pagination
Asana's API returns a maximum of 100 tasks per request by default. If your project has 100+ tasks matching the filter, the node will silently truncate results. In the Asana node's Additional Fields, set 'Limit' to 100 and add a loop using n8n's 'Split In Batches' node paired with Asana's offset pagination to collect all pages before proceeding.
Cap the standup message length
Slack Block Kit messages have a 50-block limit and individual text fields cap at 3,000 characters. If your team closes 50+ tasks a day, the message will be truncated or rejected. Add logic in the Code node to limit each section to the top 10 tasks by completion time and append a count ('...and 23 more') rather than listing everything.
Avoid Asana API rate limits
Asana's API allows 1,500 requests per minute per token. With three simultaneous Asana queries, you're at 3 requests per workflow run — well within limits. But if you scale to 20+ projects, add a 500ms delay between Asana node executions using n8n's 'Wait' node to stay under rate limits during batch processing.
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 n8n for this if your team self-hosts or you need to keep standup data inside your own infrastructure. n8n runs on your own server, so Asana task names and Slack content never pass through a third-party automation vendor's servers — relevant if you're in a regulated industry or have strict data residency requirements. The Code node also gives you full control over the message format: you can build Block Kit payloads, group by assignee, filter by tag, or add conditional logic without hitting the limits of a GUI-based field mapper. The one scenario where you'd pick something else: if your team has zero technical members who can debug a JavaScript error at 9 AM when the standup fails. In that case, Zapier's simpler setup and clearer error emails are worth the trade-off.
n8n's pricing for this workflow is straightforward. The workflow makes 3 Asana API calls and 1 Slack API call per execution — 4 operations total. Running Monday through Friday, that's roughly 20 executions per month, or 80 operations. On n8n Cloud's Starter plan ($20/month), you get 2,500 executions included — this workflow uses less than 1% of that. Self-hosted n8n is free entirely, with the only cost being your server (a $5/month DigitalOcean droplet runs it fine). Compare that to Zapier, where this workflow requires a multi-step Zap on a paid plan starting at $19.99/month — and Zapier doesn't support the parallel branching needed for three simultaneous Asana queries without additional Zaps.
Zapier handles the Asana-to-Slack connection with a cleaner credential UI and takes about 8 minutes to connect both apps — faster than n8n if you've never set up API credentials before. But Zapier can't run three parallel Asana queries in one Zap, so you'd need three separate Zaps and a fourth to aggregate them, which gets expensive fast. Make (formerly Integromat) handles parallel branches natively and its visual router is easier to read than n8n's canvas for this specific branching pattern — if your team is visual thinkers who'll maintain this themselves, Make is a legitimate alternative. Power Automate has a native Asana connector only in premium plans, and its Block Kit formatting support in Slack is limited — you'd be stuck with plain text messages. Pipedream is closest to n8n in flexibility, with better built-in error handling and step-level logging, but it lacks n8n's self-hosting option. n8n is still the right call if data sovereignty matters or you want to run complex JavaScript without per-step costs.
Three things you'll hit after the workflow is running. First: Asana's 'Completed Since' filter uses UTC, not your local timezone. If your team is in PST, 'completed in the last 24 hours' as of 9 AM UTC is actually 1 AM PST — you'll miss tasks completed between 1 AM and 9 AM PST. Fix this by adjusting the timestamp in your expression to subtract your UTC offset. Second: Slack's Block Kit validates block structure strictly. A single missing 'type' key or an extra field that Block Kit doesn't recognize will cause a 400 error with a vague 'invalid_blocks' message. Test your payload at app.slack.com/block-kit-builder before deploying. Third: Asana personal access tokens don't expire by default, but if a team member who generated the token leaves the company and their Asana account is deactivated, the token stops working immediately and your standup silently fails. Use a service account or a shared admin token for production workflows.
Ideas for what to build next
- →Add per-assignee sections — Modify the Code node to group tasks by assignee name instead of (or in addition to) task type. This gives each team member a named section in the standup, which works better for teams of 8+ where a flat list loses accountability.
- →Pull from multiple Asana projects — Duplicate the three Asana node branches for a second project and merge all six streams together. Add a 'Project Name' field to each Set node so the Code node can label tasks by project — useful for cross-functional teams managing multiple workstreams.
- →Add a Slack reaction-based task update — Add a separate webhook workflow that listens for a specific emoji reaction (e.g., ✅) on the standup message and marks the corresponding Asana task complete — turning the Slack post into a two-way update surface.
Related guides
How to Share Notion Meeting Notes to Slack with Pipedream
~15 min setup
How to Share Notion Meeting Notes to Slack with Power Automate
~15 min setup
How to Share Notion Meeting Notes to Slack with n8n
~20 min setup
How to Send Notion Meeting Notes to Slack with Zapier
~8 min setup
How to Share Notion Meeting Notes to Slack with Make
~12 min setup
How to Create Notion Tasks from Slack with Pipedream
~15 min setup