

How to Send Copper Deal Stage Alerts to Slack with Power Automate
Polls Copper for deal stage changes and posts a formatted Slack channel message with the deal name, new stage, owner, and value every time an opportunity moves forward or stalls.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Microsoft-shop sales teams already using Power Automate who want deal stage visibility in Slack without leaving their existing automation stack.
Not ideal for
Teams that need sub-minute alerts — Power Automate polls Copper on a schedule, so you'll see up to a 15-minute lag between a stage change and the Slack message.
Sync type
scheduledUse case type
notificationReal-World Example
A 12-person B2B software sales team routes all deal alerts to a #pipeline Slack channel so reps and their manager see stage changes without logging into Copper. Before this flow, the sales manager exported a pipeline report each morning and pinged reps manually when deals hadn't moved — a 20-minute daily task that still missed same-day changes. After setup, every stage move posts automatically within 15 minutes, and the team added a 🏆 emoji rule for 'Won' stage posts that turned into a team ritual.
What Will This Cost?
Drag the slider to your expected monthly volume.
Each platform counts differently — Zapier: 1 task per trigger. Make: 1 operation per module per record. n8n: 1 execution per run.





Prices shown for annual billing. Based on published pricing as of April 2026.
Estimated ROI
1000
min saved/mo
$583
labor value/mo
Free
no platform cost
Based on ~2 min manual effort per operation at $35/hr fully loaded labor cost.
Implementation
Import this workflow directly into 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.
Optional
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Deal Name | name | |
| Stage ID | stage_id | |
| Stage Name | name | |
| Date Modified | date_modified | |
| Deal ID | id | |
4 optional fields▸ show
| Monetary Value | monetary_value |
| Assignee ID | assignee_id |
| Close Date | close_date |
| Pipeline ID | pipeline_id |
Step-by-Step Setup
make.powerautomate.com > My flows > + New flow > Scheduled cloud flow
Create a new Scheduled cloud flow
Go to make.powerautomate.com and sign in. From the left sidebar, click 'My flows', then click '+ New flow' in the top bar and select 'Scheduled cloud flow'. Name the flow 'Copper Deal Stage Notifications'. Set the recurrence to every 15 minutes — this is the polling interval that determines how quickly stage changes reach Slack. Click 'Create' to open the flow editor.
- 1Click 'My flows' in the left sidebar
- 2Click '+ New flow' in the top toolbar
- 3Select 'Scheduled cloud flow' from the dropdown
- 4Enter 'Copper Deal Stage Notifications' in the Name field
- 5Set Repeat every to '15' and select 'Minute' from the unit dropdown
- 6Click 'Create'
Flow editor > + New step > Variables > Initialize variable
Initialize a variable to store the last-checked timestamp
Click '+ New step' below the Recurrence trigger. Search for 'Initialize variable' and select the 'Variables' action. Name the variable 'LastRunTime' and set the type to 'String'. In the Value field, paste this expression: addMinutes(utcNow(), -15) — this tells the flow to look back 15 minutes on each run, matching your poll interval. This variable is how you avoid re-processing deals that already sent a notification.
- 1Click '+ New step'
- 2Type 'Initialize variable' in the search bar
- 3Select 'Initialize variable' under the Variables connector
- 4Set Name to 'LastRunTime'
- 5Set Type to 'String'
- 6Click inside the Value field, then click 'Expression' tab and paste: addMinutes(utcNow(), -15)
- 7Click 'OK'
Flow editor > + New step > HTTP
Connect to Copper via HTTP to fetch recently updated opportunities
Power Automate does not have a native Copper connector, so you'll use the HTTP action to call Copper's REST API directly. Click '+ New step', search for 'HTTP', and select the HTTP action (not HTTP + Swagger). Set Method to POST and URI to https://api.copper.com/developer_api/v1/opportunities/search. Add three headers: X-PW-AccessToken with your Copper API key, X-PW-Application set to developer_api, and Content-Type set to application/json. In the Body field, enter the JSON payload shown in the sub-steps below.
- 1Click '+ New step'
- 2Type 'HTTP' in the search bar and select the HTTP action
- 3Set Method to 'POST'
- 4Set URI to: https://api.copper.com/developer_api/v1/opportunities/search
- 5Click '+ Add new parameter' and add Header: X-PW-AccessToken = [your Copper API key]
- 6Add Header: X-PW-Application = developer_api
- 7Add Header: Content-Type = application/json
- 8In Body, paste: {"page_size": 200, "sort_by": "date_modified", "sort_direction": "desc"}
Flow editor > + New step > Data Operation > Parse JSON
Parse the Copper API response
After the HTTP action, click '+ New step' and search for 'Parse JSON'. Select it from the Data Operation connector. In the Content field, click the dynamic content picker and select 'Body' from the HTTP step. For the Schema field, click 'Generate from sample' and paste in a sample Copper opportunity JSON response (see the schema in the pro tip section). This step converts the raw API response into named fields that you can reference in later steps without writing expressions.
- 1Click '+ New step'
- 2Type 'Parse JSON' in the search bar
- 3Select 'Parse JSON' under Data Operation
- 4Click the Content field and select 'Body' from the HTTP step in dynamic content
- 5Click 'Generate from sample'
- 6Paste your sample Copper opportunity array JSON and click 'Done'
Flow editor > + New step > Data Operation > Filter array
Apply a filter to isolate deals modified in the last 15 minutes
Click '+ New step' and search for 'Filter array' under Data Operation. Set the From field to the array output of your Parse JSON step. In the filter condition, set the left side to the date_modified field from dynamic content, set the operator to 'is greater than or equal to', and set the right side to the expression variables('LastRunTime'). This narrows the full opportunity list down to only deals that changed since the last poll run.
- 1Click '+ New step'
- 2Search for 'Filter array' and select it under Data Operation
- 3Set the From field to the body/array output of the Parse JSON step
- 4Click 'Edit in advanced mode' if simple mode fields are not flexible enough
- 5In the left condition field, select 'date_modified' from dynamic content
- 6Set operator to 'is greater than or equal to'
- 7In the right field, switch to Expression and type: variables('LastRunTime')
Flow editor > + New step > Control > Apply to each
Add an Apply to each loop over filtered deals
Click '+ New step' and search for 'Apply to each'. Set the output from previous steps field to the Body output of the Filter array step. Every action you add inside this loop runs once per deal that changed stage. This is where you'll build the Slack message. Keep the loop as lean as possible — don't add extra HTTP calls inside it unless necessary, since each one counts against your Copper rate limit.
- 1Click '+ New step'
- 2Select 'Control' then 'Apply to each'
- 3Click the 'Select an output from previous steps' field
- 4Choose 'Body' from the Filter array step in dynamic content
- 5Click inside the loop to start adding actions
Flow editor > Apply to each > + Add an action > HTTP
Resolve the pipeline stage name from the stage ID
Copper passes stage_id as a numeric ID, not a human-readable label like 'Proposal Sent'. Inside the Apply to each loop, add another HTTP action that calls GET https://api.copper.com/developer_api/v1/pipeline_stages/[stage_id] using the same three Copper headers. Replace [stage_id] with the dynamic content field stage_id from your Parse JSON output. Follow this with a second Parse JSON step to extract the name field from the stage response. This gives you the readable stage name to display in Slack.
- 1Inside the Apply to each loop, click '+ Add an action'
- 2Search for 'HTTP' and select it
- 3Set Method to 'GET'
- 4Set URI to: https://api.copper.com/developer_api/v1/pipeline_stages/ then append the stage_id dynamic content field
- 5Add the same three Copper headers: X-PW-AccessToken, X-PW-Application, Content-Type
- 6Add a second Parse JSON action inside the loop after this HTTP call
- 7Set Content to the Body of this HTTP call and generate schema from a sample stage response
This expression block goes inside a Compose action placed between your Filter array step and the Apply to each loop. It handles three things at once: converts the Copper Unix timestamp to a readable date, formats monetary_value as USD currency, and builds the full Slack message string so the Slack action only needs to reference a single Compose output. Paste the expression into the Compose action's Inputs field using the Expression editor tab.
JavaScript — Code Step// Place this in a Compose action (Expression mode) BEFORE the Apply to each loop.▸ Show code
// Place this in a Compose action (Expression mode) BEFORE the Apply to each loop.
// Reference: outputs('Compose_Deal_Message') in the Slack Message Text field.
// Full message expression (paste as one block in the Compose Inputs field):... expand to see full code
// Place this in a Compose action (Expression mode) BEFORE the Apply to each loop.
// Reference: outputs('Compose_Deal_Message') in the Slack Message Text field.
// Full message expression (paste as one block in the Compose Inputs field):
concat(
if(
equals(string(item()?['stage_id']), '7'),
'🏆 *Deal Won:* ',
'*Deal Update:* '
),
item()?['name'],
' moved to *',
body('Parse_Stage_Response')?['name'],
'*. Value: ',
formatNumber(item()?['monetary_value'], 'C0', 'en-US'),
'. Close Date: ',
formatDateTime(
addSeconds('1970-01-01T00:00:00Z', item()?['close_date']),
'MMM d, yyyy'
),
'. View: https://app.copper.com/companies/',
string(item()?['id'])
)Flow editor > Apply to each > + Add an action > Slack > Post message
Add the Slack connection and configure the message action
Inside the Apply to each loop, click '+ Add an action' and search for 'Slack'. Select 'Post message' from the Slack connector. If you haven't connected Slack yet, Power Automate will prompt you to sign in — click 'Sign in' and authorize the bot with the correct workspace. In the Channel Name field, type the exact Slack channel name without the # symbol (e.g. pipeline or deals). Build the message text using dynamic content fields from your Parse JSON steps.
- 1Inside the Apply to each loop, click '+ Add an action'
- 2Type 'Slack' in the search bar
- 3Select 'Post message' from the Slack connector
- 4If prompted, click 'Sign in' and complete the OAuth flow for your Slack workspace
- 5In the Channel Name field, type the target channel name (no # prefix)
- 6In the Message Text field, compose your message using dynamic content
channel: {{channel}}
ts: {{ts}}
Flow editor > Apply to each > Slack > Post message > Message Text
Build the Slack message body with deal details
In the Message Text field of the Slack action, compose a message that includes the key deal fields. Use plain text with Slack mrkdwn formatting for readability. Reference dynamic content from your Parse JSON steps for each field. A good starting template: *Deal Update:* [name] moved to *[stage name]*. Value: $[monetary_value]. Owner: [assignee email]. View in Copper: https://app.copper.com/companies/[id]. Add a conditional prefix like 🏆 for 'Won' stage using a Condition action before the Slack step if you want emoji-based routing.
- 1Click inside the Message Text field of the Slack action
- 2Type '*Deal Update:* ' then select 'name' from dynamic content
- 3Type ' moved to *' then select the stage 'name' from the second Parse JSON output
- 4Type '*. Value: $' then select 'monetary_value' from dynamic content
- 5Type '. Owner: ' then select 'assignee_email' or resolve from assignee ID
- 6Type a newline then type the Copper deal URL with the dynamic 'id' appended
Flow editor > Save > Test > Manually > Run flow
Test the flow with a live Copper deal
Click 'Save' in the top toolbar, then click 'Test' in the top right and select 'Manually'. Click 'Run flow'. Power Automate runs the flow immediately regardless of the 15-minute schedule. While the test runs, open Copper and manually move a deal to a different stage. If the deal's date_modified falls within the last 15 minutes, it will appear in the filtered results and trigger a Slack post. Watch the flow run details — each step shows a green checkmark or red X with the input/output payload visible.
- 1Click 'Save' in the top toolbar
- 2Click 'Test' in the upper right corner
- 3Select 'Manually' and click 'Run flow'
- 4Open Copper and move an existing deal to a different pipeline stage
- 5Return to Power Automate and watch the run details panel
- 6Click each step tile to expand the input/output JSON and verify field values
make.powerautomate.com > My flows > [Flow name] > Run history
Enable the flow and confirm the schedule is active
After a successful test, click the back arrow to return to the flow detail page. Confirm the flow status shows 'On' — it should be on by default after saving. Check the 'Run history' tab to see the first scheduled run after your test. The Recurrence trigger fires every 15 minutes from the time you created the flow. If you need to change the start time, click the Recurrence trigger tile and set the 'Start time' field to a specific UTC datetime.
- 1Click the back arrow to exit the flow editor
- 2Confirm the flow status indicator shows 'On'
- 3Click the 'Run history' tab
- 4Wait up to 15 minutes for the first scheduled run to appear
- 5Click any run entry to see per-step pass/fail and execution time
Going live
Production Checklist
Before you turn this on for real, confirm each item.
Troubleshooting
Common errors and how to fix them.
Frequently Asked Questions
Common questions about this workflow.
Analysis
Use Power Automate for this if your team already lives in the Microsoft ecosystem — SharePoint, Teams, Azure AD — and you need deal notifications to fit into existing governance around connectors and data policies. The HTTP connector gives you full Copper API access without waiting for a native connector, and the expression language handles the Unix timestamp conversion and currency formatting that Copper's raw API output requires. The one case where you'd pick something else: if your team has zero tolerance for up-to-15-minute lag and needs sub-minute alerts, Power Automate's polling architecture can't match Make or n8n running a webhook listener.
The cost math is straightforward. This flow uses roughly 6-8 actions per run: Recurrence, Initialize Variable, HTTP (Copper search), Parse JSON, Filter array, Apply to each, HTTP (stage lookup), Slack post. At a 15-minute polling interval, that's 96 runs per day and roughly 700 base actions daily before any deals trigger the loop. Power Automate's per-user plan costs $15/month and includes 40,000 actions/month — you'll consume about 21,000 on polling overhead alone, leaving 19,000 for actual deal processing. That covers roughly 270 deal stage changes per month before you hit the cap. Make's equivalent setup costs $9/month with 10,000 operations and a native Copper module, making it cheaper for low-volume teams. For high volume (500+ stage changes/month), Zapier gets expensive fast at $49-$69/month for the tiers that handle that throughput.
Make has a native Copper module — 'Watch Opportunities' — that uses webhook-style instant triggers instead of polling, so stage changes hit Slack in under 30 seconds. Zapier's Copper integration is mature and requires no HTTP actions, but the Zap editor gives you less control over timestamp formatting and conditional routing. n8n lets you self-host and run the Copper HTTP calls in a Function node with full JavaScript, which is better for complex message formatting and deduplication logic. Pipedream's event sources can poll Copper and emit individual events per deal, which makes the downstream logic cleaner. Power Automate wins here specifically if: you need Azure Key Vault for API key storage, your IT team restricts which SaaS tools can hold credentials, or you're bundling this with other Microsoft 365 automations and want a single admin pane.
Three things you'll hit after setup. First, Copper's search endpoint returns all opportunities sorted by date_modified, but 'modified' means any field — custom fields, notes, tags. You will get Slack noise from deal updates that had nothing to do with stage. Fix this by storing the last known stage_id per deal in SharePoint and diffing on each run. Second, the Power Automate Slack connector posts as the bot user, and if your Slack workspace has a message retention policy or compliance archiving, those bot messages are treated differently than user messages — confirm with your Slack admin before rolling this out. Third, Copper's API returns assignee_id as a numeric integer, not a name or email. Resolving it requires a separate GET to /v1/users/[id], which adds another API call per loop iteration. Cache user IDs in a SharePoint list on first run and refresh weekly, or your Slack messages will either show raw IDs or burn through extra API calls on every deal update.
Ideas for what to build next
- →Add a daily digest instead of per-deal pings — Switch to a Scheduled flow that runs once at 9am and posts a bulleted summary of all deals that changed stages in the past 24 hours. This reduces Slack noise for high-velocity teams while keeping visibility intact.
- →Route 'Won' and 'Lost' deals to separate Slack channels — Add a Switch control inside the Apply to each loop that checks the stage name and posts Won deals to #wins and Lost deals to #retrospectives. Keeps celebration and analysis in the right spaces without manual filtering.
- →Write stage changes back to a SharePoint tracking list — Add a SharePoint 'Create item' action after each Slack post to log the deal name, stage, value, and timestamp. After 30 days, you have a stage-change history you can analyze in Power BI to find where deals stall most often.
Related guides
How to Share Notion Meeting Notes to Slack with Pipedream
~15 min setup
How to Share Notion Meeting Notes to Slack with Power Automate
~15 min setup
How to Share Notion Meeting Notes to Slack with n8n
~20 min setup
How to Send Notion Meeting Notes to Slack with Zapier
~8 min setup
How to Share Notion Meeting Notes to Slack with Make
~12 min setup
How to Create Notion Tasks from Slack with Pipedream
~15 min setup