Intermediate~15 min setupCommunication & CRMVerified April 2026
Slack logo
Copper logo

How to Create Copper Tasks from Slack with Power Automate

When a Slack message gets a specific reaction emoji or a slash command is used, Power Automate fires instantly and creates a follow-up task in Copper tied to the relevant contact or opportunity.

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

Best for

Sales teams already on Microsoft 365 who discuss prospects in Slack and want task creation without leaving the conversation.

Not ideal for

Teams using Slack slash commands with complex argument parsing — n8n or Pipedream handle that text transformation more cleanly.

Sync type

real-time

Use case type

routing

Real-World Example

💡

A 12-person SaaS sales team discusses deal blockers in a #prospects Slack channel. When a rep reacts to a message with a 📋 emoji, Power Automate fires and drops a follow-up task into Copper against the matching contact — due in 48 hours by default. Before this, reps copy-pasted notes from Slack into Copper manually, and about 30% of action items never made it into the CRM.

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 Power Automate

Copy the pre-built Power Automate blueprint and paste it straight into Power Automate. 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.

Copper API key with read/write access — found under Copper Settings > Integrations > API Keys
Slack workspace admin access to create and install a custom Slack app with reaction_added event subscription and channels:history + chat:write scopes
Microsoft 365 account with Power Automate access (the HTTP connector that calls external APIs requires a paid plan — see cost section)
Copper account email address matching the API key owner — required as a header in every Copper API call
Slack bot token (xoxb-...) from your custom app after installing it to the workspace under OAuth & Permissions

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Task Namename
Due Datedue_date
Statusstatus
5 optional fields▸ show
Assigneeassignee_id
Related Resource Typerelated_resource.type
Related Resource IDrelated_resource.id
Details / Notesdetails
Prioritypriority

Step-by-Step Setup

1

api.slack.com/apps > Create New App > From scratch

Set up a Slack app to capture reaction events

Power Automate's native Slack connector does not expose reaction_added events. You need a custom Slack app to push those events to Power Automate via an outgoing webhook. Go to api.slack.com/apps, click 'Create New App', choose 'From scratch', name it 'PA Task Bot', and select your workspace. You'll come back here in Step 3 to paste the Power Automate webhook URL into the Event Subscriptions section.

  1. 1Go to api.slack.com/apps and sign in
  2. 2Click the green 'Create New App' button
  3. 3Select 'From scratch'
  4. 4Enter app name 'PA Task Bot' and select your workspace
  5. 5Click 'Create App'
What you should see: You land on the app's Basic Information page showing your App ID and credentials panel.
Common mistake — If you have a Slack Enterprise Grid account, the app must be installed at the org level, not just the workspace level, or events won't fire across all channels.
2

make.powerautomate.com > My flows > + New flow > Automated cloud flow

Create a new Automated cloud flow in Power Automate

Go to make.powerautomate.com and sign in with your Microsoft 365 account. In the left sidebar click 'My flows', then click '+ New flow' and select 'Automated cloud flow'. Name it 'Slack Reaction → Copper Task'. For the trigger, search for 'When a HTTP request is received' — this is under the Request connector. Select it and click Create. Power Automate will generate a unique POST URL after you save the flow for the first time.

  1. 1Click 'My flows' in the left sidebar
  2. 2Click '+ New flow' then select 'Automated cloud flow'
  3. 3Enter flow name 'Slack Reaction → Copper Task'
  4. 4Search 'HTTP request' in the trigger picker and select 'When a HTTP request is received'
  5. 5Click 'Create'
What you should see: The flow canvas opens with a single trigger card labeled 'When a HTTP request is received' showing an empty Request Body JSON Schema field.
Common mistake — The webhook URL is not generated until you save the flow at least once. Do not skip saving before moving to Step 3.
3

Flow canvas > HTTP trigger card > Use sample payload to generate schema

Paste the Slack event payload schema into the HTTP trigger

In the HTTP trigger card, click 'Use sample payload to generate schema'. Paste the JSON below representing a Slack reaction_added event — this tells Power Automate what fields to expect so it can surface them as dynamic content in later steps. After pasting, click 'Done'. Then save the flow using the Save button in the top toolbar. Copy the generated POST URL from the trigger card — you'll need it in the next step.

  1. 1Click inside the HTTP trigger card to expand it
  2. 2Click 'Use sample payload to generate schema'
  3. 3Paste the Slack reaction_added JSON payload
  4. 4Click 'Done'
  5. 5Click 'Save' in the top toolbar and copy the generated URL
What you should see: The Request Body JSON Schema field is now populated with auto-generated schema and you can see the POST URL appear above the schema box.
Power Automate
+
click +
search apps
Slack
SL
Slack
Paste the Slack event payloa…
Slack
SL
module added
4

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

Subscribe to reaction_added events in your Slack app

Back in api.slack.com/apps, open your 'PA Task Bot' app and go to 'Event Subscriptions' in the left menu. Toggle 'Enable Events' to On. Paste the Power Automate POST URL into the 'Request URL' field. Slack will immediately send a challenge request — Power Automate's HTTP trigger handles this automatically and Slack should show a green 'Verified' badge within 10 seconds. Then under 'Subscribe to bot events', click 'Add Bot User Event' and add reaction_added.

  1. 1Open your Slack app and click 'Event Subscriptions' in the left sidebar
  2. 2Toggle 'Enable Events' to On
  3. 3Paste the Power Automate POST URL into 'Request URL'
  4. 4Wait for the green 'Verified' checkmark
  5. 5Click 'Add Bot User Event' and search for and select 'reaction_added'
  6. 6Click 'Save Changes'
What you should see: The Request URL field shows a green 'Verified' label and reaction_added appears in the bot events list.
Common mistake — Slack only fires reaction_added for messages in channels where the bot is invited. Run '/invite @PA Task Bot' in every channel you want to monitor — otherwise events will be silently dropped.
5

Flow canvas > + New step > Control > Condition

Add a condition to filter for the task emoji only

Back in Power Automate, click '+ New step' below the trigger. Search for 'Condition' and add a Control > Condition action. In the left value field, use the dynamic content picker to select 'reaction' from the Slack payload. Set the operator to 'is equal to'. In the right value field, type the emoji name without colons — for example, memo (which is 📋). This ensures only that specific reaction triggers task creation and other reactions are ignored.

  1. 1Click '+ New step'
  2. 2Search 'Condition' and select 'Condition' under Control
  3. 3Click the left value field and select 'reaction' from dynamic content
  4. 4Set the operator dropdown to 'is equal to'
  5. 5Type memo in the right value field
What you should see: The condition card shows two branches: 'If yes' and 'If no'. The 'If no' branch can be left empty — it will do nothing for other reactions.
Common mistake — Slack sends emoji names without colons and with underscores for spaces. The reaction 📋 is memo, not :memo:. Test with the exact string Slack sends using the flow run history.
Slack
SL
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Copper
CO
notified
6

Flow canvas > If yes branch > Add an action > HTTP

Fetch the Slack message text to use as the task name

Inside the 'If yes' branch, click 'Add an action'. Search for 'HTTP' and add the HTTP action (not a connector — the raw HTTP action). Configure it as a GET request to the Slack conversations.history API endpoint: https://slack.com/api/conversations.history. Add query parameters channel (from dynamic content: item.channel.id) and latest (from dynamic content: item.event_ts), with limit set to 1. In the Headers, add Authorization: Bearer YOUR_SLACK_BOT_TOKEN. This pulls back the exact message text that was reacted to.

  1. 1Inside 'If yes', click 'Add an action'
  2. 2Search 'HTTP' and select the HTTP action
  3. 3Set Method to GET
  4. 4Set URI to https://slack.com/api/conversations.history
  5. 5Add query parameters: channel = item.channel.id, latest = item.event_ts, limit = 1
  6. 6Add Header: Authorization = Bearer YOUR_SLACK_BOT_TOKEN
What you should see: The HTTP action card shows a green GET badge and all parameters are filled. You won't see actual data until a test run.
Common mistake — The Slack bot token must have channels:history scope. If you get a missing_scope error during testing, go back to api.slack.com/apps > OAuth & Permissions and add it, then reinstall the app.
7

Flow canvas > Add an action > Data Operation > Parse JSON

Parse the Slack API response with Parse JSON

After the HTTP action, click 'Add an action' and search for 'Parse JSON' under the Data Operation connector. In the Content field, select 'Body' from the previous HTTP step's dynamic content. For the schema, click 'Generate from sample' and paste a sample conversations.history response. The key fields you need are messages[0].text (the message body) and messages[0].ts (the timestamp). Power Automate will now expose these as dynamic content tokens in subsequent steps.

  1. 1Click 'Add an action' after the HTTP step
  2. 2Search 'Parse JSON' and select it under Data Operation
  3. 3In Content, pick 'Body' from the HTTP step's dynamic content
  4. 4Click 'Generate from sample' and paste a sample conversations.history JSON response
  5. 5Click 'Done'
What you should see: The Parse JSON card shows a schema block. In the next step, dynamic content from this action includes fields like text, ts, and user.
8

Flow canvas > Add an action > HTTP (POST to Copper API)

Connect to Copper via HTTP POST to create the task

Copper does not have a native Power Automate connector, so you'll use the HTTP action again with Copper's REST API. Click 'Add an action', select HTTP, and set Method to POST. Set URI to https://api.copper.com/developer_api/v1/tasks. Add three Headers: X-PW-AccessToken (your Copper API key), X-PW-Application (copper_chrome_extension), and Content-Type (application/json). In the Body field, build the JSON manually using dynamic content tokens — see field mapping below for the full structure.

  1. 1Click 'Add an action' and select HTTP
  2. 2Set Method to POST
  3. 3Set URI to https://api.copper.com/developer_api/v1/tasks
  4. 4Add Header: X-PW-AccessToken = your Copper API key
  5. 5Add Header: X-PW-Application = copper_chrome_extension
  6. 6Add Header: Content-Type = application/json
  7. 7In Body, enter the JSON payload using dynamic content tokens
What you should see: The HTTP action card shows POST and the Copper API URL. You'll validate it's working in the test step.
Common mistake — Copper's X-PW-UserEmail header is also required — it must match the email of the Copper account that owns the API key, otherwise you'll get a 401 even with a valid token.
9

Flow canvas > HTTP POST body > Expression editor

Set the task due date using an expression

In the Body JSON for the Copper task, the due_date field expects a Unix timestamp (integer), not an ISO date string. In Power Automate, use the expression editor to calculate 48 hours from now. Click the Body field, position your cursor where due_date value goes, and switch to the Expression tab. Enter: div(sub(ticks(addHours(utcNow(),48)),ticks('1970-01-01')),10000000) — this converts the future timestamp to Unix epoch seconds. Click OK to insert it as a token.

  1. 1Click into the Body field of the Copper HTTP POST action
  2. 2Position cursor at the due_date value location
  3. 3Click 'Expression' tab in the dynamic content panel
  4. 4Enter: div(sub(ticks(addHours(utcNow(),48)),ticks('1970-01-01')),10000000)
  5. 5Click 'OK' to insert the expression token
What you should see: The Body field shows a blue expression token where the due_date value is, rather than a plain text date.
10

Flow canvas > Add an action > Slack > Post message (V2)

Send a Slack confirmation message back to the channel

After the Copper task is created, add a final action to confirm back in Slack. Click 'Add an action', search for 'Slack' in the connector list, and select 'Post message (V2)'. Connect your Slack account using the Connections prompt that appears. Set Channel to the dynamic content value item.item.channel.id. Set Message Text to something like: '✅ Task created in Copper: ' followed by the Parse JSON text token. This closes the loop so the rep knows the task was logged without leaving Slack.

  1. 1Click 'Add an action'
  2. 2Search 'Slack' and select 'Post message (V2)'
  3. 3Sign in to Slack when the Connections prompt appears
  4. 4Set Channel to dynamic content: item.item.channel.id
  5. 5Set Message Text to: ✅ Task created in Copper: [text token from Parse JSON]
What you should see: The Slack action card shows your workspace name and the channel ID field is populated. After a test run, you'll see the confirmation message appear in the Slack channel.
Common mistake — The native Slack connector in Power Automate uses OAuth, which requires the bot to have chat:write scope. If post fails with 'not_in_channel', the bot needs to be invited to that specific channel first.
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
11

make.powerautomate.com > My flows > [Flow name] > 28-day run history

Test end-to-end and review run history

Save the flow. Go to a Slack channel where the bot is invited and react to any message with the 📋 emoji. In Power Automate, go to My flows, click your flow name, and scroll to the '28-day run history' section at the bottom. Click the most recent run to see each step expand with its inputs and outputs. Check that the Copper HTTP POST returned a 200 status and that the response body contains a task id field. If any step shows a red X, click it to read the exact error.

  1. 1Save the flow using the Save button
  2. 2In Slack, react to a message with 📋 in a channel where the bot is present
  3. 3Go to My flows and click the flow name
  4. 4Scroll to '28-day run history' and click the latest run
  5. 5Expand each step and verify the Copper POST step shows status 200 and a task id in the response
What you should see: Every step shows a green checkmark, the Copper POST step shows a 200 response with a numeric task id, and a confirmation message appears in the Slack channel.

This expression block goes inside the HTTP POST Body field of your Copper action step. It handles three things: truncating overly long Slack messages to 500 characters so Copper's name field doesn't reject them, computing the Unix due date 48 hours out, and appending the Slack channel ID to the details field for traceability. Switch to Expression mode in each field and paste the relevant line.

JavaScript — Code Step// Task name — truncate Slack message text to 500 chars
▸ Show code
// Task name — truncate Slack message text to 500 chars
if(greater(length(body('Parse_JSON')?['messages']?[0]?['text']), 500),
  concat(substring(body('Parse_JSON')?['messages']?[0]?['text'], 0, 497), '...'),

... expand to see full code

// Task name — truncate Slack message text to 500 chars
if(greater(length(body('Parse_JSON')?['messages']?[0]?['text']), 500),
  concat(substring(body('Parse_JSON')?['messages']?[0]?['text'], 0, 497), '...'),
  body('Parse_JSON')?['messages']?[0]?['text']
)

// Due date — Unix timestamp 48 hours from now
div(
  sub(
    ticks(addHours(utcNow(), 48)),
    ticks('1970-01-01')
  ),
  10000000
)

// Details — append Slack source for traceability
concat(
  'Created from Slack channel ',
  triggerBody()?['event']?['item']?['channel'],
  ' at ',
  utcNow()
)
Power Automate
▶ Test flow
executed
Slack
Copper
Copper
🔔 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 Power Automate for this if your team is already on Microsoft 365 and you want this flow managed inside the same admin console as your other business automations. Power Automate's audit logging, DLP policies, and integration with Azure AD make it the right call for companies with IT governance requirements. It also makes sense if you're building other flows that touch SharePoint, Teams, or Dynamics — keeping everything in one platform cuts credential sprawl. The one scenario where you'd skip Power Automate here: if your team uses Slack slash commands with complex text parsing, the expression editor in Power Automate gets painful fast compared to writing three lines of JavaScript in Pipedream.

Cost

The cost math is straightforward. Power Automate Premium (required for the HTTP connector) runs $15/user/month. Each flow run costs against your run quota — Automated flows on Premium get 40,000 runs/user/month, which is far more than you'll use for this workflow. At 50 Slack reactions per day that become tasks, you're using about 1,500 runs/month — well inside the limit. The real cost is the plan itself: $15/month per user who owns the flow. Compare that to Make's Connections plan at $9/month for 10,000 operations, which covers the same volume. If cost is the only variable, Make is $6/month cheaper. But if you're already paying for Microsoft 365 Business Premium, check whether Power Automate is included in your license before assuming you need an upgrade.

Tradeoffs

Zapier has a native Slack trigger called 'New Reaction Added to Message' that takes 3 minutes to configure — no custom Slack app needed. That's a genuine advantage. Make handles the Copper API call and text transformation in a single HTTP module with cleaner visual branching than Power Automate's nested conditions. n8n lets you write the entire Unix timestamp calculation and message truncation in a single Function node with six lines of JavaScript, which is faster to maintain than Power Automate's expression chains. Pipedream wins on Slack event handling specifically — it has a native Slack event source that manages the OAuth handshake automatically, so you skip the custom app setup entirely. Power Automate is still right for this use case when Microsoft 365 governance, IT admin oversight, or existing enterprise licensing make the platform a requirement — not because it's technically superior for this specific workflow.

Three things you'll hit after setup. First, Copper's API returns 422 if the task name exceeds 500 characters — Slack messages can easily hit that length in a busy thread, so the truncation expression in the pro tip section is not optional. Second, Power Automate's HTTP connector does not automatically retry on Copper 429 rate limit responses — you need to manually add a Scope with Configure Run After plus a Delay action to handle retries, or tasks will silently fail during high-activity periods. Third, the Slack Events API has a 3-second response deadline — Power Automate usually responds fast enough, but if your flow has multiple sequential HTTP calls (like a Copper contact lookup before task creation), you can breach that window. The result is Slack retrying the event, which means duplicate task creation. Handle this by responding to Slack immediately in a separate lightweight flow and using a queue or storage variable to process the actual Copper write asynchronously.

Ideas for what to build next

  • Link tasks to specific Copper contacts automaticallyAdd a Copper People Search API call before the task creation step. Extract a name or company from the Slack message text using Power Automate's string functions, search Copper, and pass the returned contact ID into related_resource.id — so tasks attach to the right record instead of floating unlinked.
  • Post a daily digest of open tasks to a Slack channelBuild a second Scheduled cloud flow that runs each morning at 8am, calls the Copper tasks API filtered by status=Open and due_date=today, and posts a formatted list to your #sales-standup channel — so the team sees the day's follow-ups without opening Copper.
  • Add a slash command interface for manual task detailsSet up a Slack slash command like /task [contact name] [description] that posts to the same Power Automate webhook URL with structured arguments. Parse the command text in Power Automate using split() and indexOf() expressions to extract contact name and description, giving reps more control than a reaction alone.

Related guides

Was this guide helpful?
Slack + Copper overviewPower Automate profile →