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

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

scheduled

Use case type

reporting

Real-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.

/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.

Asana Personal Access Token with read access to the target workspace and project — generate at app.asana.com/0/my-apps
Slack Bot Token (xoxb-...) with the 'chat:write' and 'channels:read' OAuth scopes — create a Slack app at api.slack.com/apps
Slack bot invited to the target standup channel before the workflow runs
Asana project GID for the team project you want to pull tasks from — visible in the project URL
n8n instance running v1.0 or later, either self-hosted or n8n Cloud, with internet access to reach Asana and Slack APIs

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Task Namename
Assignee Nameassignee.name
Completed Atcompleted_at
Due Ondue_on
Task Type (custom stamp)
Slack Channel ID
3 optional fields▸ show
Project Namememberships[0].project.name
Task URLpermalink_url
Notes / Descriptionnotes

Step-by-Step Setup

1

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.

  1. 1Click '+ New Workflow' in the left sidebar
  2. 2Click the pencil icon next to 'My Workflow' and rename it 'Daily Standup — Asana to Slack'
  3. 3Press Enter to save the name
  4. 4Click the '+' node placeholder in the canvas center
What you should see: You should see the node picker panel slide open on the right side of the canvas.
2

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.

  1. 1Type 'Schedule' in the node search box
  2. 2Click 'Schedule Trigger' to add it to the canvas
  3. 3Click the node to open its settings panel
  4. 4Set 'Trigger Interval' to 'Custom (Cron)'
  5. 5Enter '0 9 * * 1-5' in the cron expression field
What you should see: The node should show a clock icon and display the next scheduled execution time below the cron field.
Common mistake — n8n runs on UTC by default. If your team is on Eastern Time (UTC-5), enter '0 14 * * 1-5' to fire at 9:00 AM ET. Getting this wrong means your standup posts at 4 AM or misses weekdays entirely.
n8n
+
click +
search apps
Slack
SL
Slack
Add the Schedule trigger
Slack
SL
module added
3

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.

  1. 1Click the '+' connector on the Schedule Trigger node
  2. 2Search 'Asana' in the node picker and select it
  3. 3Click 'Credential' dropdown and choose 'Create New Credential'
  4. 4Select 'Asana API' and paste your Personal Access Token
  5. 5Set Resource to 'Task', Operation to 'Search'
  6. 6Enter your Asana Workspace GID and Project GID in the respective fields
What you should see: After saving credentials, you should see a green checkmark next to the credential name. The node settings will show Workspace and Project fields populated.
Common mistake — The Asana node uses GIDs (numeric IDs), not project names. Find your project GID by opening the project in Asana, clicking the three-dot menu, and selecting 'Copy project link' — the long number at the end of the URL is the GID.
4

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.

  1. 1Scroll to 'Additional Fields' in the Asana node settings
  2. 2Click 'Add Field' and select 'Completed Since'
  3. 3Toggle the field to expression mode by clicking the gear/expression icon
  4. 4Paste: {{ new Date(Date.now() - 86400000).toISOString() }}
  5. 5Add another field: set 'Completed' to 'true'
What you should see: The expression field shows the formula in orange expression mode rather than plain text. When you test the node, it returns only tasks marked complete in the past 24 hours.
Common mistake — Filters are the most common place setups break. Double-check the field name and value exactly match what your app sends — a single capital letter difference will block everything.
Slack
SL
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Asana
AS
notified
5

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.

  1. 1Click on the Schedule Trigger node to select it
  2. 2Click the '+' connector to add a second branch
  3. 3Search and add another Asana node
  4. 4Set Resource to 'Task', Operation to 'Search', use the same credential
  5. 5In Additional Fields, set 'Due On' using the date expression
  6. 6Duplicate this node and change 'Due On' to 'Due Before' with today's date for overdue tasks
What you should see: Your canvas now shows the Schedule Trigger with three branches: completed tasks, due today, and overdue. Each Asana node should show the project name in its label.
Common mistake — Asana's API treats 'Due On' as an exact date match, not a range. To catch overdue tasks, you need a separate query using 'Due Before' — a single 'due on or before today' filter does not exist in Asana's v1 API.
6

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.

  1. 1Search 'Merge' in the node picker and add it to the canvas
  2. 2Drag a connector from each of the three Asana nodes into the Merge node
  3. 3Click the Merge node to open settings
  4. 4Set 'Mode' to 'Combine'
  5. 5Set 'Combination Mode' to 'Merge By Position'
What you should see: The Merge node shows three input connectors on its left side, each labeled with its source node name.
Common mistake — If one Asana query returns zero results (e.g., no overdue tasks), the Merge node may stall depending on your n8n version. Add a 'NoOp' node on any branch that might return empty to force it to always pass through.
7

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.

  1. 1Click '+' after the Merge node and search 'Code'
  2. 2Select 'Code' and click to open the editor
  3. 3Set the language to 'JavaScript'
  4. 4Paste the pro tip code into the editor
  5. 5Click 'Execute Node' to preview the formatted output
What you should see: The output panel shows a single item with a 'blocks' array — the Slack Block Kit payload ready to post. Each section should list task names under the correct header.
Common mistake — The Code node in n8n uses '$input.all()' to access all items from the previous node. If you use '$input.first()' by mistake, you'll only process one task. Always use '$input.all()' when iterating over merged results.

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 } }];
8

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 }}'.

  1. 1Click '+' after the Code node and search 'Slack'
  2. 2Select the Slack node and set Resource to 'Message', Operation to 'Post'
  3. 3Click 'Create New Credential' and paste your Slack Bot Token
  4. 4Enter the target channel name in the 'Channel' field (e.g. #standup)
  5. 5Toggle 'Blocks' field to expression mode and enter {{ $json.blocks }}
  6. 6Set 'Text' to a fallback string like 'Daily Standup Report' for notification previews
What you should see: The Slack node shows your bot name and the channel name. When you test it, you should see the formatted standup message appear in the Slack channel within 5 seconds.
Common mistake — Your Slack bot must be invited to the target channel before it can post. If you get a 'not_in_channel' error, open Slack, go to the channel, type '/invite @your-bot-name', and press Enter.
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
9

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.

  1. 1Click any critical node (e.g., the first Asana node) to select it
  2. 2Click the red error output connector on the node's bottom-right
  3. 3Add a Slack node connected to this error output
  4. 4Set the channel to '#alerts' or your team's error channel
  5. 5Set the message text to 'Standup workflow failed: {{ $json.error.message }}'
  6. 6Repeat for the Code node and the second Asana node
What you should see: Error paths now show as red connector lines going to the fallback Slack node. You can test by intentionally breaking a credential and running the workflow.
10

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.

  1. 1Click 'Execute Workflow' in the top-center toolbar
  2. 2Watch the execution flow left to right across the canvas
  3. 3Click any node to inspect its input and output data
  4. 4Open Slack and confirm the standup message appeared in the correct channel
  5. 5Check that completed tasks, due-today tasks, and overdue tasks each appear under the right section
What you should see: All nodes show green checkmarks. The Slack channel shows a formatted standup message with three sections populated with real task data.
Common mistake — If you run the test on a weekend or outside work hours, the Asana queries may return zero tasks (nothing was completed in the last 24 hours). Add a test task to Asana marked complete, or run on a Monday morning after actual work has happened.
n8n
▶ Run once
executed
Slack
Asana
Asana
🔔 notification
received
11

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.

  1. 1Click the gray 'Inactive' toggle in the top-right corner of the canvas
  2. 2Confirm it turns green and reads 'Active'
  3. 3Click 'Save' to persist the active state
  4. 4Navigate to the 'Executions' tab in the left sidebar
  5. 5Check back the next scheduled morning to verify the first automatic run
What you should see: The toggle is green and labeled 'Active'. The Executions tab shows the workflow queued for the next scheduled time.

Scaling Beyond 200+ tasks returned per Asana query+ Records

If your volume exceeds 200+ tasks returned per Asana query records, apply these adjustments.

1

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.

2

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.

3

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

VerdictWhy n8n for this workflow

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.

Cost

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.

Tradeoffs

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 sectionsModify 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 projectsDuplicate 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 updateAdd 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

Was this guide helpful?
Slack + Asana overviewn8n profile →