Intermediate~20 min setupCommunication & Project ManagementVerified April 2026
Slack logo
Monday.com logo

How to Create Monday.com Tasks from Slack with n8n

When a teammate reacts with a specific emoji to any Slack message, n8n captures the message text, sender, and channel, then creates a Monday.com task with that context automatically.

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

Best for

Teams already using Monday.com for task tracking who want to capture action items directly from Slack without switching apps or copy-pasting.

Not ideal for

Teams who need two-way sync — if Monday.com task updates should post back to Slack, this one-way setup needs a second workflow.

Sync type

real-time

Use case type

routing

Real-World Example

💡

A 22-person product team at a B2B SaaS company reacts with a ✅ emoji whenever a Slack message contains a customer request or bug report. Before this workflow, someone had to manually copy the message into Monday.com — it happened maybe 60% of the time, and context got lost in translation. Now every ✅ reaction creates a Monday.com task in the 'Backlog' group with the original message text, the Slack channel name, and the message author pre-filled as the task description.

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.

Slack workspace admin access or permission to create and install Slack apps
Slack bot scopes: reactions:read, channels:history, channels:read, users:read
Monday.com account with API access and your personal API token from the Developers section
n8n instance (self-hosted or n8n Cloud) with a publicly accessible URL so Slack can reach your webhook
Monday.com board ID and the column IDs for Status, Description, and Assignee columns on your target board

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Task Namename
7 optional fields▸ show
Description / Long Text Columnlong_text
Status Columnstatus
Assignee (People Column)people
Slack Channeltext
Slack Message Linklink
Reacting Usertext
Creation Datedate

Step-by-Step Setup

1

api.slack.com/apps > Your App > Event Subscriptions

Create a Slack App and configure the Event Subscriptions webhook

Go to api.slack.com/apps and click 'Create New App', then choose 'From Scratch'. Name it something like 'n8n Task Bot' and select your workspace. Navigate to 'Event Subscriptions' in the left sidebar and toggle 'Enable Events' on. You'll need to paste your n8n webhook URL here — set up the n8n node first (Step 2) and come back to complete this.

  1. 1Go to api.slack.com/apps and click 'Create New App'
  2. 2Choose 'From Scratch', enter app name, select your workspace
  3. 3Click 'Event Subscriptions' in the left sidebar
  4. 4Toggle 'Enable Events' to On
  5. 5Leave the Request URL field blank — you'll fill this in after Step 2
What you should see: You should see the Event Subscriptions page with the toggle turned on and a blank Request URL field ready for your webhook.
Common mistake — Slack requires your webhook URL to respond with a challenge verification within 3 seconds. n8n's webhook node handles this automatically — but only if the workflow is active, not in test mode.

This Code node runs after the IF filter and before the Slack API call. It extracts and normalizes all fields from the raw reaction_added webhook payload — message timestamp, channel ID, reacting user, and item type — and prepares a clean object for the downstream nodes. Paste it into a Code node set to 'Run Once for Each Item' mode, placed between the IF node's true branch and the HTTP Request node.

JavaScript — Code Node// n8n Code Node: Extract and normalize Slack reaction_added payload
▸ Show code
// n8n Code Node: Extract and normalize Slack reaction_added payload
// Place between: IF node (true branch) → this Code node → HTTP Request (conversations.history)
const body = $input.item.json.body;

... expand to see full code

// n8n Code Node: Extract and normalize Slack reaction_added payload
// Place between: IF node (true branch) → this Code node → HTTP Request (conversations.history)

const body = $input.item.json.body;
const event = body.event;

// Validate we have what we need before going further
if (!event || event.type !== 'reaction_added') {
  throw new Error(`Unexpected event type: ${event?.type}. Check your Slack event subscription.`);
}

if (!event.item || event.item.type !== 'message') {
  // Reactions on files or app messages — skip gracefully
  return [{ json: { skip: true, reason: 'Reaction was not on a message item', eventType: event.item?.type } }];
}

// Extract core fields from the reaction event
const channelId = event.item.channel;
const messageTs = event.item.ts;
const reactingUserId = event.user;       // Who reacted (the person flagging the task)
const originalAuthorId = event.item_user; // Who wrote the original message (potential assignee)
const reactionName = event.reaction;      // e.g. 'white_check_mark'
const eventTs = event.event_ts;           // When the reaction was added

// Build a Slack permalink manually (faster than calling chat.getPermalink)
const tsForUrl = messageTs.replace('.', '');
const slackPermalink = `https://slack.com/archives/${channelId}/p${tsForUrl}`;

// Format a human-readable timestamp for Monday.com
const reactionDate = new Date(parseFloat(eventTs) * 1000);
const formattedDate = reactionDate.toISOString().split('T')[0]; // YYYY-MM-DD

// Build the output object for downstream nodes
return [
  {
    json: {
      channelId,
      messageTs,
      reactingUserId,
      originalAuthorId: originalAuthorId || reactingUserId, // fallback if item_user missing
      reactionName,
      slackPermalink,
      formattedDate,
      skip: false,
      // Passed to conversations.history call:
      historyParams: {
        channel: channelId,
        latest: messageTs,
        limit: 1,
        inclusive: 'true'
      }
    }
  }
];
2

n8n Canvas > + Node > Webhook

Add a Webhook trigger node in n8n

Open your n8n instance and create a new workflow. Click the '+' button to add the first node and search for 'Webhook'. Select the Webhook node and set the HTTP Method to POST. Copy the 'Test URL' shown — this is what you'll paste into Slack in the next step. Keep the Response Mode as 'Immediately' and set the Response Code to 200.

  1. 1Click the '+' button on the blank canvas
  2. 2Search for 'Webhook' and select it
  3. 3Set HTTP Method to POST
  4. 4Set Response Mode to 'Immediately'
  5. 5Copy the 'Test URL' from the node panel
What you should see: The Webhook node appears on the canvas with a Test URL like https://your-n8n-instance.com/webhook-test/abc123. The node shows a grey dot indicating it's waiting for activation.
Common mistake — Copy the webhook URL carefully — it expires if you regenerate it, and any scenarios using the old URL will silently stop working.
n8n
+
click +
search apps
Slack
SL
Slack
Add a Webhook trigger node i…
Slack
SL
module added
3

api.slack.com/apps > Event Subscriptions > Subscribe to Bot Events

Paste the webhook URL into Slack and subscribe to reaction_added events

Go back to your Slack app's Event Subscriptions page and paste the n8n Test URL into the Request URL field. Slack will immediately send a challenge request — your n8n webhook needs to be active (click 'Listen for Test Events' in n8n first) to respond. Once Slack shows a green 'Verified' badge, scroll down to 'Subscribe to Bot Events' and add 'reaction_added'. Save your changes.

  1. 1In n8n, click 'Test Workflow' to start listening on the test URL
  2. 2Paste the n8n Test URL into Slack's Request URL field
  3. 3Wait for the green 'Verified' checkmark to appear
  4. 4Click 'Add Bot User Event' and search for 'reaction_added'
  5. 5Select 'reaction_added' and click 'Save Changes'
What you should see: Slack shows a green 'Verified' badge next to your webhook URL and 'reaction_added' appears in the Bot Events list.
Common mistake — If you subscribe to 'message.channels' instead of 'reaction_added', you'll trigger the workflow on every message — that's thousands of Monday.com tasks per day. Use reaction_added only.
4

api.slack.com/apps > OAuth & Permissions > Bot Token Scopes

Install the Slack app to your workspace and add it to target channels

In your Slack app settings, go to 'OAuth & Permissions' in the left sidebar. Under 'Bot Token Scopes', add the scopes: reactions:read, channels:history, channels:read, and users:read. Click 'Install App to Workspace' and authorize it. Once installed, copy the Bot User OAuth Token — you'll need it in Step 7. Then go into each Slack channel you want to monitor and type /invite @n8n-task-bot.

  1. 1Click 'OAuth & Permissions' in the left sidebar
  2. 2Under 'Bot Token Scopes', click 'Add an OAuth Scope'
  3. 3Add: reactions:read, channels:history, channels:read, users:read
  4. 4Click 'Install App to Workspace' and click 'Allow'
  5. 5Copy the 'Bot User OAuth Token' (starts with xoxb-)
What you should see: You have a Bot User OAuth Token starting with xoxb- copied to your clipboard, and the app appears in your workspace's app directory.
Common mistake — The bot only sees reactions in channels it's been invited to. If you forget to /invite the bot, the reaction_added event fires but n8n receives nothing — no error, just silence.
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
5

n8n Canvas > + Node > IF

Add an IF node to filter for your chosen emoji only

Not every reaction should create a Monday.com task — only your designated trigger emoji (e.g., ✅ or 📌). Add an IF node after the Webhook node. Set the condition to check Value 1 as '{{$json.body.event.reaction}}' and Value 2 as the emoji name without colons — for ✅ use 'white_check_mark'. Only the True branch continues to task creation.

  1. 1Click '+' after the Webhook node and search for 'IF'
  2. 2Set Condition to 'String'
  3. 3Set Value 1 to expression: {{$json.body.event.reaction}}
  4. 4Set Operation to 'Equal'
  5. 5Set Value 2 to: white_check_mark (no colons, no emoji character)
What you should see: The IF node shows two output branches labeled 'true' and 'false'. Only the true branch will connect to the next node.
Common mistake — Slack sends emoji names without colons and with underscores for spaces. The thumbsup emoji is 'thumbsup', not '👍' or ':thumbsup:'. Test by reacting and checking the raw webhook payload in n8n.
Slack
SL
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Monday.com
MO
notified
6

n8n Canvas > + Node > Code

Add a Code node to extract and format message context

The reaction_added event payload contains the message timestamp and channel ID, but not the actual message text or the sender's name. Add a Code node after the IF node's true branch to restructure the data. This node will format the task name, pull the channel ID, and prepare all fields for Monday.com. Paste the JavaScript from the Pro Tip section into this node.

  1. 1Click '+' on the true branch of the IF node
  2. 2Search for 'Code' and select it
  3. 3Set Mode to 'Run Once for Each Item'
  4. 4Paste the pro tip code into the code editor
  5. 5Click 'Test Step' to verify output looks correct
What you should see: The Code node outputs an object with fields: taskName, description, channelId, reactingUser, originalMessageTs, and assigneeId all populated with real values from the Slack event.
Common mistake — Map fields using the variable picker — don't type field names manually. Hand-typed variable names often have invisible spacing errors that produce blank output.

This Code node runs after the IF filter and before the Slack API call. It extracts and normalizes all fields from the raw reaction_added webhook payload — message timestamp, channel ID, reacting user, and item type — and prepares a clean object for the downstream nodes. Paste it into a Code node set to 'Run Once for Each Item' mode, placed between the IF node's true branch and the HTTP Request node.

JavaScript — Code Node// n8n Code Node: Extract and normalize Slack reaction_added payload
▸ Show code
// n8n Code Node: Extract and normalize Slack reaction_added payload
// Place between: IF node (true branch) → this Code node → HTTP Request (conversations.history)
const body = $input.item.json.body;

... expand to see full code

// n8n Code Node: Extract and normalize Slack reaction_added payload
// Place between: IF node (true branch) → this Code node → HTTP Request (conversations.history)

const body = $input.item.json.body;
const event = body.event;

// Validate we have what we need before going further
if (!event || event.type !== 'reaction_added') {
  throw new Error(`Unexpected event type: ${event?.type}. Check your Slack event subscription.`);
}

if (!event.item || event.item.type !== 'message') {
  // Reactions on files or app messages — skip gracefully
  return [{ json: { skip: true, reason: 'Reaction was not on a message item', eventType: event.item?.type } }];
}

// Extract core fields from the reaction event
const channelId = event.item.channel;
const messageTs = event.item.ts;
const reactingUserId = event.user;       // Who reacted (the person flagging the task)
const originalAuthorId = event.item_user; // Who wrote the original message (potential assignee)
const reactionName = event.reaction;      // e.g. 'white_check_mark'
const eventTs = event.event_ts;           // When the reaction was added

// Build a Slack permalink manually (faster than calling chat.getPermalink)
const tsForUrl = messageTs.replace('.', '');
const slackPermalink = `https://slack.com/archives/${channelId}/p${tsForUrl}`;

// Format a human-readable timestamp for Monday.com
const reactionDate = new Date(parseFloat(eventTs) * 1000);
const formattedDate = reactionDate.toISOString().split('T')[0]; // YYYY-MM-DD

// Build the output object for downstream nodes
return [
  {
    json: {
      channelId,
      messageTs,
      reactingUserId,
      originalAuthorId: originalAuthorId || reactingUserId, // fallback if item_user missing
      reactionName,
      slackPermalink,
      formattedDate,
      skip: false,
      // Passed to conversations.history call:
      historyParams: {
        channel: channelId,
        latest: messageTs,
        limit: 1,
        inclusive: 'true'
      }
    }
  }
];
7

n8n Canvas > + Node > HTTP Request

Add a Slack node to fetch the original message text

The reaction event only gives you the message timestamp — not the text. Add a Slack node after the Code node and set the operation to 'Get Permalink' or use the HTTP Request node to call conversations.history with the channel ID and timestamp. Use your Bot Token from Step 4. This fetches the actual message text so your Monday.com task has meaningful content, not just a timestamp.

  1. 1Click '+' after the Code node and search for 'HTTP Request'
  2. 2Set Method to GET
  3. 3Set URL to: https://slack.com/api/conversations.history
  4. 4Add Header: Authorization = Bearer xoxb-your-token
  5. 5Add Query Parameters: channel = {{$json.channelId}}, latest = {{$json.originalMessageTs}}, limit = 1, inclusive = true
What you should see: The HTTP Request node returns a JSON response with messages[0].text containing the original Slack message text that was reacted to.
Common mistake — conversations.history requires the bot to be a member of the channel AND the channel:history scope. If you get 'not_in_channel' error, go back and /invite the bot to that channel.
8

Monday.com > Avatar > Developers > My Access Tokens

Connect Monday.com credentials in n8n

Add a Monday.com node after the HTTP Request node. In n8n, click 'Create New Credential' for Monday.com and select 'API Token'. Get your API token from Monday.com by clicking your avatar in the bottom left, selecting 'Developers', then 'My Access Tokens', and clicking 'Copy'. Paste it into n8n and save the credential.

  1. 1In Monday.com, click your avatar in the bottom-left corner
  2. 2Select 'Developers' from the menu
  3. 3Click 'My Access Tokens' then 'Show' next to your token
  4. 4Copy the token
  5. 5In n8n, paste it into the Monday.com credential field and click 'Save'
What you should see: The Monday.com credential shows a green checkmark in n8n confirming the API token is valid.
Common mistake — Monday.com API tokens don't expire automatically, but if you regenerate yours in Monday.com's developer settings, this credential will break silently. Test monthly.
9

n8n Canvas > Monday.com Node > Create Item

Configure the Monday.com node to create the task

Set the Monday.com node Operation to 'Create Item'. Select your target board from the Board dropdown — n8n fetches your boards automatically. Set the Group to your preferred group (e.g., 'Backlog' or 'Inbox'). Set the Item Name to an expression pointing to the message text. Map additional column values like Status, Description, and Assignee using the Column Values field with Monday.com's column IDs.

  1. 1Set Resource to 'Item' and Operation to 'Create'
  2. 2Select your target Board from the dropdown
  3. 3Select the target Group (e.g., 'Backlog')
  4. 4Set Item Name to expression: {{$node['HTTP Request'].json.messages[0].text.slice(0, 80)}}
  5. 5Add Column Values for status, description, and assignee fields
What you should see: The Monday.com node shows a preview of the item it will create, with the task name pulled from the Slack message text.
Common mistake — Monday.com column IDs are not the same as column names. To find a column's ID, go to the board, click the three dots on a column header, and select 'Column Settings'. The ID appears in the URL.
10

n8n Canvas > Workflow Toggle (top right)

Activate the workflow and switch to the production webhook URL

Before activating, go back to Step 2 and note the 'Production URL' — it's different from the Test URL. In your Slack app's Event Subscriptions page, replace the Test URL with the Production URL. Then in n8n, click the toggle in the top right to activate the workflow. The workflow now runs on live events without you clicking 'Test'.

  1. 1Copy the Production URL from the Webhook node (not the Test URL)
  2. 2Go back to api.slack.com/apps > Event Subscriptions
  3. 3Replace the Test URL with the Production URL
  4. 4Click 'Save Changes' in Slack
  5. 5Click the activation toggle in n8n's top right corner
What you should see: The workflow toggle shows green/active in n8n. React to a Slack message with your trigger emoji — a Monday.com task should appear within 5 seconds.
Common mistake — Copy the webhook URL carefully — it expires if you regenerate it, and any scenarios using the old URL will silently stop working.
11

n8n > Executions > Latest Run

Test end-to-end and check execution logs

React to any message in your monitored Slack channel with the trigger emoji. Switch to n8n and click 'Executions' in the left sidebar to see the run. Each node should show green. Click into any node to see the exact data it processed. If Monday.com received the item, go to your board and confirm the task appears in the right group with the correct name and description.

  1. 1React to a Slack message with your trigger emoji (e.g., ✅)
  2. 2In n8n, click 'Executions' in the left sidebar
  3. 3Click the latest execution entry
  4. 4Click each node to inspect input/output data
  5. 5Go to your Monday.com board and confirm the task was created
What you should see: All nodes show green checkmarks in the execution log. Your Monday.com board has a new task with the Slack message text as the task name and the channel name in the description.
n8n
▶ Run once
executed
Slack
Monday.com
Monday.com
🔔 notification
received

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 and wants full control over the Slack token, message data, and where tasks land. The Code node advantage is real here — parsing the reaction_added payload, resolving user IDs, and formatting Monday.com column values cleanly takes about 20 lines of JavaScript that you'd otherwise hack together with five separate transformation nodes. n8n also lets you add conditional routing (different boards for different channels) without paying per task. The one case where I'd pick something else: if you're a non-technical team and nobody wants to touch JavaScript, Make handles this workflow with zero code and a friendlier UI.

Cost

Cost math: each Slack reaction triggers one workflow execution in n8n. One execution touches five nodes (Webhook, IF, Code, HTTP Request, Monday.com). On n8n Cloud's Starter plan at $20/month, you get 2,500 executions/month — that's 2,500 tasks created from Slack reactions. At that rate, cost is effectively $0.008 per task. Self-hosted n8n costs only your server fees, making this workflow free at any volume. Monday.com's API has no per-call cost. Slack's API is free for this use case. Total monthly cost for a 30-person team creating ~200 tasks/month via Slack reactions: $20 on n8n Cloud, or ~$5-10 server costs self-hosted.

Tradeoffs

Make handles the Slack 'Watch Events' trigger natively without building a custom app — it's genuinely easier to set up for non-developers and takes about half the time. Zapier has a 'New Reaction Added' trigger that works with zero webhook configuration, but it polls every 5-15 minutes instead of firing instantly, so your tasks appear with a lag. Power Automate has no native Slack connector worth using — you'd end up on a third-party connector with limited event support. Pipedream's Slack source is excellent and fires in under 2 seconds, with built-in user resolution helpers, but costs $19/month for always-on sources. n8n wins on cost and flexibility, Make wins on setup speed, Pipedream wins on Slack-specific features.

Three things you'll hit post-launch. First, Slack's reaction_added event includes item_user (the message author) only sometimes — if the message is older than a few days or in certain channel types, that field is missing and your assignee mapping breaks. Add a fallback. Second, Monday.com's people column expects an integer user ID, not an email or name — you need to call Monday.com's users query once to build a lookup table, or your assignee field will always be empty. Third, if your n8n instance goes down for maintenance and someone reacts during that window, the event is lost permanently — Slack doesn't retry failed webhook deliveries. Set up n8n's built-in error alerting and consider a short downtime window policy for the team.

Ideas for what to build next

  • Post a Slack confirmation when the task is createdAdd a Slack node at the end of the workflow to reply in the thread of the reacted message with a link to the new Monday.com item. This closes the loop so the person who reacted knows the task was captured.
  • Map Slack users to Monday.com users automaticallyAdd an HTTP Request node that calls Slack's users.info API to get the reacting user's email, then queries Monday.com's users API to find the matching Monday.com user ID. This makes the Assignee field accurate instead of blank.
  • Route tasks to different Monday.com boards by channelAdd a Switch node after the Code node that checks the channelId and sends tasks from #engineering to a 'Tech Backlog' board, #marketing to a 'Campaigns' board, and so on. One workflow handles all channels without duplicating the setup.

Related guides

Was this guide helpful?
Slack + Monday.com overviewn8n profile →