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

How to Send Copper Lead Alerts to Slack with Power Automate

Polls Copper for new or reassigned leads and sends a formatted Slack direct message to the assigned sales rep within minutes.

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

Best for

Microsoft 365 teams who already use Power Automate and need lead assignment alerts without adding another automation tool.

Not ideal for

Teams needing sub-60-second alert delivery — Copper has no native webhook, so polling adds latency.

Sync type

scheduled

Use case type

notification

Real-World Example

💡

A 12-person B2B sales team at a managed IT services company uses this to ping reps in Slack the moment a new inbound lead is assigned in Copper. Before this flow, reps logged into Copper manually and routinely missed freshly assigned leads for 2-3 hours. Now the assigned rep gets a Slack DM within 5 minutes of assignment, including the lead name, company, phone number, and a direct link to the Copper record.

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 and the email address of the Copper account that owns the key — found in Copper Settings > Integrations > API Keys
Copper user accounts for each sales rep must have email addresses that match their Slack accounts — mismatches break the user lookup in Step 8
Slack app or bot with OAuth scopes: users:read, users:read.email, chat:write, and im:write — a Slack admin must authorize the Power Automate Slack connection with these scopes
Power Automate account with a license that supports the HTTP connector (Premium) — the HTTP action is not available on the free or seeded Microsoft 365 plans
Microsoft 365 account with permission to create flows in your tenant — if your org restricts flow creation, contact your Power Platform admin

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Lead Namename
Assignee IDassignee_id
Date Modifieddate_modified
Lead IDid
Assignee Emailemail
5 optional fields▸ show
Company Namecompany_name
Phone Numbersphone_numbers
Email Addressesemail_addresses
Lead Statusstatus
Lead Sourcecustomer_source_id

Step-by-Step Setup

1

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

Open Power Automate and start a new Scheduled flow

Go to make.powerautomate.com and sign in with your Microsoft 365 account. In the left sidebar, click 'My flows', then click '+ New flow' at the top. Select 'Scheduled cloud flow' from the dropdown. Because Copper does not expose webhooks, you will poll it on a recurring interval — every 5 minutes is a practical starting point. Name the flow something like 'Copper Lead Assignment Alert'.

  1. 1Navigate to make.powerautomate.com and sign in
  2. 2Click 'My flows' in the left sidebar
  3. 3Click '+ New flow' in the top toolbar
  4. 4Select 'Scheduled cloud flow'
  5. 5Set the flow name to 'Copper Lead Assignment Alert', interval to 5, and unit to Minutes, then click 'Create'
What you should see: The flow designer canvas opens with a 'Recurrence' trigger block already placed at the top, showing your 5-minute interval.
Common mistake — Do not use 'Automated cloud flow' here. Copper has no Power Automate trigger connector, so event-based triggering is not available — scheduled polling is the only option.
2

Flow canvas > + New step > Search 'HTTP' > HTTP action

Add an HTTP action to call the Copper Leads API

Click '+ New step' below the Recurrence trigger. In the action search bar, type 'HTTP' and select the 'HTTP' action (not HTTP + Swagger). You will use this to call Copper's REST API directly, since there is no native Copper connector in Power Automate. Set Method to POST and the URI to 'https://api.copper.com/developer_api/v1/leads/search'. This endpoint accepts a JSON body to filter leads modified after a specific timestamp.

  1. 1Click '+ New step'
  2. 2Type 'HTTP' in the search bar and select the 'HTTP' action
  3. 3Set Method to 'POST'
  4. 4Set URI to 'https://api.copper.com/developer_api/v1/leads/search'
  5. 5Under 'Headers', add: X-PW-AccessToken (your Copper API key), X-PW-Application (developer_api), X-PW-UserEmail (your Copper login email), Content-Type (application/json)
What you should see: The HTTP action card shows POST, the Copper search endpoint URL, and all four headers filled in without any red validation errors.
Common mistake — The X-PW-UserEmail header must match the email of the Copper account that owns the API key — mismatches return a 401 even when the API key itself is valid.
3

HTTP action > Body field > Expression editor

Build the Copper leads search request body

In the HTTP action's Body field, you need to pass a JSON filter that returns only leads modified in the last 5 minutes. Use a Power Automate expression to calculate the timestamp dynamically. Click the Body field, then open the expression editor. The body should filter by 'minimum_updated_date' set to 5 minutes ago. Also request the 'assignee_id' and 'date_modified' fields to detect reassignment.

  1. 1Click inside the Body field of the HTTP action
  2. 2Paste the following JSON, replacing the date value with an expression: {"minimum_updated_date": EXPRESSION, "page_size": 25}
  3. 3Click the Expression tab and enter: formatDateTime(addMinutes(utcNow(), -5), 'yyyy-MM-ddTHH:mm:ssZ') to generate the lookback timestamp
  4. 4Confirm the full body reads: {"minimum_updated_date": "@{formatDateTime(addMinutes(utcNow(), -5), 'yyyy-MM-ddTHH:mm:ssZ')}", "page_size": 25}
What you should see: The Body field shows the JSON with the dynamic expression embedded inline — it will look like a mix of plain JSON and blue dynamic-content tokens.
Common mistake — Copper's search API returns leads modified at OR after the timestamp — if your flow runs exactly on schedule, you may see the same lead in two consecutive polls. Add a Compose action to cache the last-seen lead IDs in a storage mechanism (like a SharePoint list) to prevent duplicate alerts.
4

Flow canvas > + New step > Search 'Parse JSON' > Data Operations - Parse JSON

Parse the Copper API response with Parse JSON

After the HTTP action, click '+ New step' and search for 'Parse JSON'. Select the 'Data Operations - Parse JSON' action. Set the Content field to the Body output from the previous HTTP step. You need to provide a schema so Power Automate can reference individual fields like lead name, assignee ID, and phone number in later steps. Use the schema provided in the pro tip section or generate one by pasting a sample Copper lead response.

  1. 1Click '+ New step' and search 'Parse JSON'
  2. 2Select 'Data Operations - Parse JSON'
  3. 3In the 'Content' field, click and select 'Body' from the HTTP action's dynamic content panel
  4. 4Click 'Generate from sample', paste a real Copper lead JSON response, and click 'Done'
  5. 5Verify the schema shows fields including id, name, assignee_id, phone_numbers, and date_modified
What you should see: The Parse JSON action shows a valid schema block with no red borders, and dynamic content from this step (like 'name', 'assignee_id') is now available to subsequent steps.
5

Flow canvas > + New step > Built-in > Apply to each

Add an Apply to Each loop over the returned leads

Copper's search endpoint returns an array of leads. You need to loop through each one and send a separate Slack message per lead. Click '+ New step', search for 'Apply to each', and select it. In the 'Select an output from previous steps' field, choose the parsed array body from the Parse JSON action. All remaining steps — the Copper assignee lookup and the Slack message — will live inside this loop.

  1. 1Click '+ New step'
  2. 2Search 'Apply to each' and select it under 'Built-in'
  3. 3Click inside 'Select an output from previous steps'
  4. 4From the dynamic content panel, select the array output from Parse JSON (it will be labeled 'Body' or the top-level array key)
  5. 5Confirm the loop card is now wrapping a blank interior — all next steps go inside here
What you should see: An 'Apply to each' loop block appears on the canvas with an empty interior area and the Copper leads array set as its input.
Common mistake — If the Parse JSON schema wraps the leads in a root key like 'value' or the array is nested, you must select the correct nested array here — selecting the wrong level causes the loop to iterate over characters, not lead objects.
6

Apply to each loop > + Add an action > HTTP

Resolve the assignee ID to a name and email via HTTP

Copper stores the assigned rep as a numeric assignee_id, not a name. Inside the Apply to each loop, add another HTTP action to call 'GET https://api.copper.com/developer_api/v1/users/{assignee_id}' to fetch the rep's name and email. Use the same four Copper API headers from Step 2. You will use the rep's email to look up their Slack user in the next step.

  1. 1Inside the Apply to each loop, click '+ Add an action'
  2. 2Search 'HTTP' and select the HTTP action
  3. 3Set Method to 'GET'
  4. 4Set URI to: https://api.copper.com/developer_api/v1/users/ then append the 'assignee_id' dynamic token from the Parse JSON output
  5. 5Add the same four Copper API headers: X-PW-AccessToken, X-PW-Application, X-PW-UserEmail, Content-Type
What you should see: The HTTP action URI shows the base URL with the assignee_id token embedded, like 'https://api.copper.com/developer_api/v1/users/@{items('Apply_to_each')?['assignee_id']}'.
Common mistake — If a lead is unassigned, assignee_id will be null and this HTTP call will return a 404. Add a Condition action before this step checking that assignee_id is not empty — otherwise the entire flow run fails on unassigned leads.

Paste this into a 'Compose' action placed immediately after the Parse JSON step for the assignee lookup. It builds the complete Slack message body as a single expression, including a formatted timestamp and a fallback for missing phone numbers. Reference this Compose action's output in the Slack 'Send a direct message' Body field.

JavaScript — Code Stepconcat(
▸ Show code
concat(
  '🔔 New lead assigned to you
',

... expand to see full code

concat(
  '🔔 New lead assigned to you
',
  '*Name:* ', items('Apply_to_each')?['name'], '
',
  '*Company:* ', if(empty(items('Apply_to_each')?['company_name']), '_(no company)_', items('Apply_to_each')?['company_name']), '
',
  '*Phone:* ', if(empty(items('Apply_to_each')?['phone_numbers']), '_(no phone)_', first(items('Apply_to_each')?['phone_numbers'])?['number']), '
',
  '*Source:* ', if(empty(items('Apply_to_each')?['customer_source_id']), '_(unknown)_', string(items('Apply_to_each')?['customer_source_id'])), '
',
  '*Status:* ', items('Apply_to_each')?['status'], '
',
  '*Assigned to:* ', body('Parse_JSON_2')?['name'], '
',
  '*View in Copper:* https://app.copper.com/companies/', string(items('Apply_to_each')?['id']), '/leads/', string(items('Apply_to_each')?['id'])
)
7

Apply to each loop > + Add an action > Parse JSON

Parse the assignee API response

Add a second Parse JSON action inside the loop to extract the rep's name and email from the user lookup response. Set Content to the Body of the assignee HTTP action. Generate the schema from a sample Copper user response — it should include fields like id, name, and email. You will use the email field to address the Slack DM in the next step.

  1. 1Inside the loop, click '+ Add an action'
  2. 2Search and select 'Data Operations - Parse JSON'
  3. 3Set Content to the Body output from the assignee HTTP action
  4. 4Click 'Generate from sample' and paste a sample Copper user object with id, name, and email
  5. 5Click 'Done' and verify 'name' and 'email' appear as available dynamic content tokens
What you should see: A second Parse JSON block appears inside the loop, and the dynamic content panel now shows both the lead fields (from Step 4) and the assignee's name and email (from this step).
8

Apply to each loop > + Add an action > Slack > Look up Slack user by email

Look up the Slack user by email

Inside the loop, add a new action and search for 'Slack'. Select the Slack connector, then choose the action 'Look up Slack user by email'. This returns the Slack user ID needed to send a direct message. Set the Email field to the email token from the assignee Parse JSON step. If this is your first Slack action, Power Automate will prompt you to create a Slack Connection — sign in with the Slack account that has the permissions to look up users and send DMs.

  1. 1Inside the loop, click '+ Add an action'
  2. 2Search 'Slack' and select the Slack connector
  3. 3Choose 'Look up Slack user by email'
  4. 4In the Email field, insert the 'email' dynamic token from the assignee Parse JSON action
  5. 5If prompted, click 'Sign in' to create a Slack Connection and authorize with your Slack workspace admin account
What you should see: The Slack 'Look up user by email' action card shows the email token in the Email field, and if the connection is new, a green 'Connected' status appears next to the Slack connection name.
Common mistake — The Slack app used for the connection must have the 'users:read.email' OAuth scope. If your Slack admin has not granted this, the lookup will return a 'missing_scope' error at runtime — not at connection time.
9

Apply to each loop > + Add an action > Slack > Send a direct message

Add the Slack 'Send a direct message' action

Still inside the loop, add another Slack action and select 'Send a direct message'. Set the 'User Name or ID' field to the Slack user ID returned by the lookup action in Step 8. In the Message Text field, compose the alert using dynamic tokens. Include the lead's name, company, phone number, assigned date, and a direct link to the Copper record formatted as a URL. Keep the message scannable — one or two lines per data point.

  1. 1Inside the loop, click '+ Add an action'
  2. 2Search 'Slack' and select 'Send a direct message'
  3. 3In 'User Name or ID', insert the 'User ID' dynamic token from the Slack user lookup action
  4. 4In 'Message Text', build the alert: '🔔 New lead assigned to you\n*Name:* [name token]\n*Company:* [company token]\n*Phone:* [phone token]\n*View in Copper:* https://app.copper.com/companies/[id token]/leads/[id token]'
  5. 5Save the action
What you should see: The Slack action card shows a Slack user ID token in the recipient field and a formatted multi-line message body with lead data tokens embedded throughout.
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.
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
10

Apply to each loop > + Add an action (before HTTP lookup) > Control > Condition

Add a Condition to filter only newly assigned leads

Right now the flow alerts on any lead modified in the last 5 minutes — including name edits, status changes, and note additions that are not assignment events. To narrow it down, add a Condition action at the top of the loop (before the assignee lookup) that checks whether the lead's 'assignee_id' is not null and whether 'date_modified' is within your lookback window. This cuts noise significantly for active teams who update leads frequently.

  1. 1Inside the loop, click '+ Add an action' at the very top of the loop (drag to reorder if needed)
  2. 2Search 'Condition' and select 'Control - Condition'
  3. 3In the left condition field, insert the 'assignee_id' dynamic token
  4. 4Set the operator to 'is not equal to'
  5. 5Set the right field to 'null' (type the word null or leave blank depending on your Power Automate version) — move the remaining steps into the 'If yes' branch
What you should see: The Condition block shows 'assignee_id is not equal to null', with the HTTP lookup, Parse JSON, and Slack actions nested inside the 'If yes' branch and the 'If no' branch left empty.
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
= "New"
yes — passes through
no — skipped
Copper
CO
notified
11

Flow canvas > Save > Test > Manually > Run flow

Test, enable, and monitor the flow

Click 'Save' in the top toolbar, then click 'Test' and choose 'Manually' to trigger an immediate run. In Copper, create a test lead and assign it to a real rep. Return to Power Automate and watch the run history — green checkmarks on each action mean the flow executed cleanly. Check the target rep's Slack DMs to confirm the message arrived. Once validated, the flow runs automatically every 5 minutes with no further action needed.

  1. 1Click 'Save' in the top toolbar
  2. 2Click 'Test', select 'Manually', then click 'Run flow'
  3. 3Open Copper and create or reassign a test lead to a rep whose email matches a Slack account
  4. 4Return to Power Automate and watch the run detail page for green checkmarks on each step
  5. 5Check the assigned rep's Slack DMs to confirm the formatted alert arrived
What you should see: Each action in the run detail shows a green checkmark, the run duration is under 10 seconds, and the assigned sales rep's Slack DMs show the correctly formatted lead alert with name, company, phone, and Copper link.
Common mistake — Power Automate's 'Test manually' mode runs the flow immediately but does NOT wait for the recurrence — it fires once right now. If Copper has no leads modified in the past 5 minutes at the moment of testing, the Apply to each loop iterates zero times and no Slack message is sent. Always create the test lead in Copper before clicking 'Run flow'.
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 organization is already in the Microsoft 365 ecosystem and your IT team controls Slack and Copper access centrally. The main advantage: your Slack Connection and HTTP credentials live inside your tenant's managed environment, which matters for teams with compliance requirements around data leaving Microsoft's infrastructure. Power Automate also lets you store the Copper API key in an Environment Variable tied to your Power Platform environment — a cleaner secret-management story than most other platforms offer natively. That said, if your team has no existing Power Automate footprint, pick Make instead — the setup is 40% faster and you won't need to manage a Premium connector license just to make an HTTP call.

Cost

Power Automate's pricing for this flow is straightforward but adds up at scale. Each flow run consumes Power Platform requests: roughly 8 actions per run (Recurrence, HTTP search, Parse JSON, Apply to each, HTTP user lookup, Parse JSON, Slack lookup, Slack DM). At 5-minute polling that is 288 runs per day, or about 8,640 runs per month. On the Power Automate Premium plan at $15/user/month, you get 40,000 Power Platform requests per user — this flow fits comfortably. The hidden cost is the HTTP connector itself: it is a Premium connector, meaning every user whose account runs this flow needs a Premium license. Make's equivalent setup costs $9/month flat for up to 10,000 operations, with no per-user premium requirement — cheaper by roughly 40% for small teams.

Tradeoffs

Zapier handles this use case with a simpler UI — their Copper 'New Lead' trigger is a native connector that avoids the manual HTTP setup entirely, saving about 30 minutes of configuration. Make is faster to build (no Parse JSON steps needed — it parses HTTP responses automatically) and supports HTTP natively on its free tier. n8n lets you run the whole flow self-hosted with no polling costs at all, and the Copper HTTP node plus Slack node are pre-built. Pipedream gives you real webhooks if you proxy Copper events through a custom endpoint, dropping latency from 5 minutes to under 5 seconds. Power Automate wins here specifically when your IT security team needs everything inside Azure AD, or when you are already paying for a Power Automate Premium license as part of a Dynamics 365 bundle and the marginal cost is zero.

Three things you will hit after going live. First, Copper's search API returns leads modified within your window regardless of which field changed — a rep adding a note triggers an alert the same as a reassignment. You need to implement the activity log check described in the next steps section, or your reps will start ignoring the bot within a week. Second, Power Automate's Apply to each loop runs actions sequentially by default, not in parallel — if 15 leads come in during one poll cycle, the loop takes 15x your per-iteration time, which can exceed 5 minutes and cause your next scheduled run to overlap. Turn on concurrency control and cap it at degree 1. Third, the Copper Users API returns a phone number and email that may differ from what is in your Slack directory — particularly at companies where personal Gmail addresses are used in Copper but corporate addresses are in Slack. Build a mapping table in SharePoint early rather than debugging mismatches rep by rep after launch.

Ideas for what to build next

  • Post to a shared #new-leads Slack channel in addition to DMsAdd a second Slack action inside the loop that posts a summary to a team channel like #sales-leads. This gives sales managers visibility into all assigned leads without needing to check Copper directly.
  • Log each alert to a SharePoint list for deduplication and audit trailBefore sending the Slack message, check a SharePoint list for the lead ID. If it already exists, skip the message. If not, add it and proceed. This eliminates duplicate alerts from boundary-case polling and gives you a searchable record of every notification sent.
  • Extend the alert to cover lead reassignments, not just new assignmentsAdd a second HTTP call that fetches the lead's previous assignee_id from Copper's activity log endpoint and compares it to the current one. If they differ, modify the Slack message to say 'Lead reassigned to you from [previous rep name]' so the new rep has full context.

Related guides

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