

How to Send Copper Deal Stage Alerts to Slack with Pipedream
Fires a Slack message to a sales channel every time a Copper deal moves to a new pipeline stage.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Sales teams of 5-30 reps who live in Slack and want instant visibility into deal movement without logging into Copper.
Not ideal for
Teams who need two-way sync or want to update Copper stage from Slack — use a different workflow for that.
Sync type
real-timeUse case type
notificationReal-World Example
A 12-person B2B SaaS sales team posts every deal stage change to #deals-live in Slack. Before this automation, reps manually refreshed Copper 4-5 times a day and still missed when deals moved to Proposal or Closed Won for hours. Now the message fires within 10 seconds of the stage change, includes the deal value and owner name, and the team uses it to jump on stalled deals before they go cold.
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 Pipedream
Copy the pre-built Pipedream blueprint and paste it straight into Pipedream. 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.
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Deal Name | name | |
| Pipeline Stage ID | pipeline_stage_id | |
| Assignee ID | assignee_id | |
| Deal ID | id | |
4 optional fields▸ show
| Deal Value | monetary_value |
| Close Date | close_date |
| Pipeline ID | pipeline_id |
| Tags | tags |
Step-by-Step Setup
pipedream.com > Workflows > New Workflow
Create a new Pipedream workflow
Go to pipedream.com and sign in. Click 'Workflows' in the left sidebar, then click the blue 'New Workflow' button in the top right. You'll land on an empty canvas with a trigger slot at the top and a prompt to add your first step. Give the workflow a name like 'Copper Deal Stage → Slack' so you can find it later.
- 1Click 'Workflows' in the left navigation
- 2Click 'New Workflow' in the top right
- 3Click the workflow title at the top and rename it to 'Copper Deal Stage → Slack'
Workflow Canvas > Add Trigger > Copper > Opportunity Stage Changed
Add the Copper webhook trigger
Click the 'Add Trigger' block. Search for 'Copper' in the app search bar. Select the Copper app, then choose the 'Opportunity Stage Changed' event source — this is the specific trigger that fires only on stage transitions, not on every deal update. Pipedream will generate a unique webhook URL for Copper to call.
- 1Click the gray 'Add Trigger' block
- 2Type 'Copper' in the search box
- 3Select 'Copper' from the app results
- 4Choose 'Opportunity Stage Changed' from the trigger list
- 5Click 'Connect Copper Account' and complete OAuth
Copper > Settings > Integrations > Webhooks > Add Webhook
Register the webhook URL in Copper
Open Copper in a new tab. Go to Settings > Integrations > Webhooks. Click 'Add Webhook'. Paste the Pipedream webhook URL into the Endpoint field. Under 'Events', check 'Opportunity Updated' — this is the event Copper fires when a stage changes. Save the webhook. Copper will send a verification ping to confirm the endpoint is live.
- 1Navigate to Settings in the Copper left sidebar
- 2Click 'Integrations', then 'Webhooks'
- 3Click 'Add Webhook'
- 4Paste your Pipedream webhook URL into the Endpoint URL field
- 5Check the 'Opportunity Updated' event box and click Save
Copper > Any Deal > Stage Dropdown | Pipedream > Workflow > Trigger > Event Inspector
Send a test event from Copper
In Copper, open any deal and move it to a different pipeline stage manually. This sends a real webhook payload to Pipedream. Switch back to Pipedream and click 'Refresh' next to the trigger step — you should see the raw payload in the event inspector on the right side of the screen. Expand the payload to confirm it includes 'pipeline_stage_id' and 'name' fields.
- 1In Copper, open a test deal
- 2Click the pipeline stage dropdown and select a different stage
- 3Switch to Pipedream and click 'Refresh' on the trigger step
- 4Click the incoming event to expand the payload
Workflow Canvas > + Add a step > Run Node.js code
Add a Node.js code step to filter and enrich the event
Click '+ Add a step' below the trigger, then select 'Run Node.js code'. This step does two things: it filters out non-stage-change events (since Copper fires on any deal update), and it resolves the stage ID to a human-readable name by calling the Copper API. You'll use the async/await pattern with Pipedream's built-in axios helper. Paste the code from the Pro Tip section into the code editor.
- 1Click '+ Add a step'
- 2Click 'Run Node.js code'
- 3Clear the default code in the editor
- 4Paste the enrichment and filter code into the editor
- 5Click 'Test' to run it against your test event
Paste this into the Node.js code step (Step 5). It filters non-stage-change events, resolves the stage ID and assignee ID to human-readable names via the Copper REST API, and returns a clean object ready for the Slack step to consume directly.
JavaScript — Code Stepimport axios from 'axios';▸ Show code
import axios from 'axios';
export default defineComponent({
async run({ steps, $ }) {... expand to see full code
import axios from 'axios';
export default defineComponent({
async run({ steps, $ }) {
const event = steps.trigger.event.body;
// Copper fires on all opportunity updates — skip if stage didn't change
const updatedFields = event.updated_fields || [];
if (!updatedFields.includes('pipeline_stage_id')) {
return { skip: true };
}
const COPPER_API_KEY = process.env.COPPER_API_KEY;
const COPPER_EMAIL = process.env.COPPER_USER_EMAIL;
const headers = {
'X-PW-AccessToken': COPPER_API_KEY,
'X-PW-Application': 'developer_api',
'X-PW-UserEmail': COPPER_EMAIL,
'Content-Type': 'application/json',
};
// Fetch pipeline stages to resolve stage ID to name
const pipelinesRes = await axios.get(
'https://api.copper.com/developer_api/v1/pipelines',
{ headers }
);
let stageName = `Stage ID ${event.pipeline_stage_id}`;
for (const pipeline of pipelinesRes.data) {
const match = pipeline.stages.find(s => s.id === event.pipeline_stage_id);
if (match) {
stageName = match.name;
break;
}
}
// Resolve assignee ID to a full name
let ownerName = 'Unassigned';
if (event.assignee_id) {
try {
const userRes = await axios.get(
`https://api.copper.com/developer_api/v1/users/${event.assignee_id}`,
{ headers }
);
ownerName = userRes.data.name || 'Unassigned';
} catch (err) {
console.log('Could not resolve owner:', err.message);
}
}
// Format deal value
const dealValue = event.monetary_value
? `$${Number(event.monetary_value).toLocaleString('en-US')}`
: 'No value set';
// Build Copper deep link
const copperLink = `https://app.copper.com/companies/deals/${event.id}`;
return {
skip: false,
dealName: event.name,
stageName,
ownerName,
dealValue,
copperLink,
dealId: event.id,
};
},
});Workflow Canvas > + Add a step > Filter
Add a filter step to skip non-stage changes
Click '+ Add a step' and select 'Filter' from Pipedream's built-in helpers. Configure it to continue only when the previous code step returns 'skip: false'. This prevents the workflow from posting to Slack when Copper fires on address updates, note additions, or any other field change that isn't a stage transition. Set the condition to: steps.code.$return_value.skip === false.
- 1Click '+ Add a step'
- 2Click 'Filter' from the helper options
- 3Set the condition field to
steps.code.$return_value.skip - 4Set the operator to 'equals'
- 5Set the value to
false
Workflow Canvas > + Add a step > Slack > Send Message to Channel
Add the Slack step and connect your account
Click '+ Add a step' and search for 'Slack'. Select the Slack app, then choose 'Send Message to Channel' as the action. Click 'Connect Slack Account' — this opens an OAuth popup. Authorize Pipedream to post to your workspace. You'll need to be a Slack admin or have permission to authorize apps for your workspace.
- 1Click '+ Add a step'
- 2Search for 'Slack' and select it
- 3Choose 'Send Message to Channel'
- 4Click 'Connect Slack Account'
- 5Complete the Slack OAuth flow and select your workspace
Workflow Canvas > Slack Step > Channel + Text Fields
Configure the Slack message content
In the Channel field, type the exact channel name including the # symbol — e.g. #deals-live. In the Text field, build the message using dynamic values from the code step. Reference fields like {{steps.code.$return_value.dealName}}, {{steps.code.$return_value.stageName}}, and {{steps.code.$return_value.dealValue}}. Use Slack's mrkdwn format for bold text — wrap field names in asterisks.
- 1Click the Channel field and type your target channel name (e.g. #deals-live)
- 2Click the Text field
- 3Type your message template using double-curly references to code step outputs
- 4Toggle 'mrkdwn' to ON so Slack renders bold and emoji formatting
- 5Click 'Test' to send a real message to the channel
Copper > Deal > Stage Dropdown | Pipedream > Workflow > Event History
Test the full workflow end to end
Go back to Copper and move a deal to a different stage. Watch Pipedream's workflow event log — you should see all steps turn green within 10 seconds. Check the Slack channel to confirm the message arrived with correct deal name, stage name, value, and owner. If the filter step stops the workflow, confirm the test event is actually a stage change and not a different field update.
- 1Open a real deal in Copper
- 2Change its pipeline stage
- 3Switch to Pipedream and click 'Event History' in the left panel
- 4Click the new event to see each step's result
- 5Check your Slack channel for the message
Workflow Canvas > Deploy Button (top right)
Deploy the workflow to production
Click the gray 'Deploy' button in the top right of the Pipedream canvas. The button turns blue and the workflow status changes from 'Development' to 'Active'. From this point, every Copper stage change fires the workflow automatically with no manual intervention. Monitor the first 10-15 real events in the Event History tab to confirm no unexpected errors surface from real production data.
- 1Click the 'Deploy' button in the top right
- 2Confirm the status badge changes to 'Active'
- 3Open Event History in the left sidebar
- 4Watch the first real events arrive and confirm all steps pass
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 Pipedream for this if your team has someone comfortable reading and writing JavaScript. The real advantage here is the enrichment step — Copper's webhook only sends stage IDs, not stage names, and resolving those IDs requires an API call. In Pipedream you write that in 10 lines of async Node.js. In Zapier you'd need a separate Lookup step that costs extra tasks and often fails silently on null values. The one scenario where you'd skip Pipedream: if nobody on your team can debug a Node.js error at 9pm when a deal is stuck, use Make instead — the visual debugger is much more forgiving.
Pipedream's free tier includes 10,000 workflow invocations per month. This workflow uses roughly 1 invocation per deal stage change. A 10-person sales team moving 3-4 deals per day generates about 90 events per month — well inside free. At 50 reps moving 10 deals each per day, you hit 15,000 events/month and need the $19/month Basic plan. Make charges per operation: this workflow takes 3-4 operations per run (webhook receive, API call, filter, Slack post), so 15,000 runs costs about 60,000 operations — roughly $16/month on Make's Core plan. Cost difference is minimal at this scale; pick based on whether you want code or visual UI.
Zapier has a pre-built Copper trigger called 'Updated Opportunity' that requires zero setup on the Copper side — no manual webhook registration. That's genuinely faster to start. The problem: Zapier polls every 5-15 minutes on most plans, so your team waits up to 15 minutes for a Closed Won notification. Make offers the same visual simplicity as Zapier with real-time webhook support, which is a better match for this use case than Zapier. n8n lets you self-host and add complex branching logic with its visual node editor — good if you need 10 different Slack routing rules. Pipedream still wins here for one reason: the inline code step handles the stage ID lookup, the null checks, and the Slack formatting in a single place with full debugging output, and it's free up to 10,000 runs.
Three things you'll run into after the first week. First, Copper's webhook doesn't include a 'previous_stage_id' field — you only get the new stage. If you want messages like 'moved FROM Qualified TO Proposal', you need to store stage history yourself, either in Pipedream's built-in data store or an external database. Second, the Copper API rate limit is 600 requests per minute — the stage lookup and assignee lookup together cost 2 API calls per event. At 300 rapid-fire stage changes in one minute (pipeline cleanup scenario), you'll hit the cap and get 429 errors. Add a await new Promise(r => setTimeout(r, 110)) delay between calls as a safety buffer. Third, Copper returns monetary_value as a plain float with no currency symbol or formatting. If your team has international deals, you'll need to store the currency code separately and format it per-locale in your code, or you'll post '$48000' instead of '€40,320' to the wrong channel.
Ideas for what to build next
- →Route notifications to different channels by stage — Add conditional logic in the Node.js code step to post Closed Won deals to #wins, Stalled deals to #at-risk, and everything else to #deals-live. Takes about 10 minutes to add.
- →Add a daily digest of all stage changes — Create a second Pipedream workflow on a scheduled trigger that queries the Copper API for all deals updated in the last 24 hours and posts a summary table to Slack every morning at 9am.
- →Trigger Copper deal updates from Slack reactions — Build the reverse direction: when a rep adds a specific emoji reaction to a deal notification in Slack, a Pipedream workflow calls the Copper API to move the deal to the next stage automatically.
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