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

How to Send Copper Lead Alerts to Slack with Pipedream

Fires a Slack DM or channel message to the assigned sales rep within seconds of a new lead being created or reassigned in Copper.

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

Best for

Sales teams using Copper as their CRM who want assigned reps notified in Slack the moment a lead lands in their queue.

Not ideal for

Teams that need two-way sync or want to update Copper records from Slack reactions — use a different pattern for that.

Sync type

real-time

Use case type

notification

Real-World Example

💡

A 12-person SaaS sales team gets inbound leads from a web form that feeds Copper. Before this workflow, reps refreshed Copper manually and routinely missed hot leads for 2-3 hours. Now, each rep gets a Slack DM within 10 seconds of assignment, including the lead name, company, phone, and a direct link to the Copper record. First-response time dropped from 140 minutes to under 8.

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 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.

Copper account with API access enabled and your API key available under Settings > Integrations > API Keys
Copper user role with permission to create and manage webhooks (typically Admin)
Slack workspace where you have permission to install apps and the bot has chat:write and users:read.email scopes
Pipedream account (free tier works for under ~333 workflow runs/day; paid starts at $19/month for higher volume)
All Copper sales reps must have Slack accounts using the same email address as their Copper user profile — required for the email-to-Slack-ID lookup in Step 5

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Lead Namename
Assignee IDassignee_id
Lead IDid
Event Typetype
5 optional fields▸ show
Company Namecompany_name
Phone Numberphone_numbers[0].number
Lead Statusstatus
Lead Sourcesource
Email Addressemail

Step-by-Step Setup

1

pipedream.com > Workflows > + New Workflow

Create a new Pipedream workflow

Go to pipedream.com and log in. Click 'Workflows' in the left sidebar, then click the blue '+ New Workflow' button in the top right. Give it a name like 'Copper Lead Assignment → Slack'. You'll land on the workflow canvas with an empty trigger slot at the top.

  1. 1Click 'Workflows' in the left sidebar
  2. 2Click '+ New Workflow' in the top right
  3. 3Type a name: 'Copper Lead Assignment → Slack'
  4. 4Click 'Create'
What you should see: You should see a blank workflow canvas with a grey 'Add a trigger' block at the top and a '+ Add a step' option below it.
2

Workflow Canvas > Add a trigger > Search 'Copper' > New Lead (Instant)

Add the Copper webhook trigger

Click the grey 'Add a trigger' block. In the search box, type 'Copper' and select it. Choose the trigger event 'New Lead (Instant)' — this uses Copper's native webhook support, so events fire within 2-5 seconds of creation. Pipedream will generate a unique webhook URL for you automatically.

  1. 1Click the grey 'Add a trigger' block
  2. 2Type 'Copper' in the search field
  3. 3Select 'Copper' from the app list
  4. 4Choose 'New Lead (Instant)' as the trigger event
  5. 5Click 'Connect Copper Account' and authenticate with your Copper API key
What you should see: You should see a green 'Connected' badge and a generated webhook endpoint URL displayed under the trigger configuration panel.
Common mistake — Copper's 'New Lead (Instant)' trigger covers creation events. Reassignment events require a separate trigger: 'Lead Assignee Changed (Instant)'. If you need both, you'll build two workflows or use an HTTP trigger and filter manually — covered in Step 4.
Pipedream
+
click +
search apps
Slack
SL
Slack
Add the Copper webhook trigger
Slack
SL
module added
3

Copper > Settings > Integrations > API & Webhooks > Add Webhook

Register the webhook in Copper

Copy the webhook URL Pipedream generated. In a new tab, go to your Copper account, navigate to Settings > Integrations > API & Webhooks. Click 'Add Webhook', paste the Pipedream URL, and select the events 'Lead Created' and 'Lead Updated'. Save it. Come back to Pipedream and click 'Generate Test Event' or create a test lead in Copper to fire the trigger.

  1. 1Copy the webhook URL from Pipedream's trigger panel
  2. 2In Copper, go to Settings > Integrations > API & Webhooks
  3. 3Click 'Add Webhook'
  4. 4Paste the Pipedream URL into the endpoint field
  5. 5Check 'Lead Created' and 'Lead Updated', then click Save
What you should see: Copper should show the webhook as 'Active' in the list. Back in Pipedream, after creating a test lead, you'll see a raw event payload appear in the trigger's 'Test' tab with lead fields populated.
Common mistake — Copper sends ALL lead update events to this webhook, not just reassignments. You must filter for assignee changes in a code step — otherwise reps get spammed every time a field is edited. Step 4 handles this.
4

Workflow Canvas > + Add a step > Custom Code > Node.js

Add a Node.js filter step for event type

Click '+ Add a step' below the trigger and choose 'Run Node.js code'. This step checks whether the incoming event is a new lead creation or specifically an assignee change — and exits early if it's an irrelevant update. Without this, every phone number correction or tag change triggers a Slack ping. Paste the filter logic shown in the Pro Tip section.

  1. 1Click '+ Add a step'
  2. 2Select 'Custom Code'
  3. 3Choose 'Run Node.js code'
  4. 4Paste the filter and assignee-lookup code from the Pro Tip below
  5. 5Click 'Test' to verify it passes for a lead creation event
What you should see: When you run the test with a lead creation payload, the step should return an object with the lead name, assignee ID, company, phone, and event type. If the event is an irrelevant update, the step should throw an error that stops the workflow.
Common mistake — Pipedream ends a workflow step early when you call $.flow.exit(). This is intentional — it's not an error. The workflow shows as 'Completed (exited early)' in logs, which is correct behavior for filtered events.
Slack
SL
trigger
filter
Type
matches criteria?
yes — passes through
no — skipped
Copper
CO
notified
5

Workflow Canvas > + Add a step > Custom Code > Node.js

Look up the assigned rep's name and Slack user ID

Copper returns an assignee as a numeric user ID (e.g., 12345), not a name or email. To send a Slack DM or @mention the right person, you need to resolve that ID. Add another Node.js step that calls the Copper API to fetch the user's email, then calls Slack's users.lookupByEmail API to get their Slack member ID. This is the critical step most tutorials skip.

  1. 1Click '+ Add a step' below the filter step
  2. 2Select 'Custom Code' > 'Run Node.js code'
  3. 3Use the Copper Users API endpoint: GET https://api.copper.com/developer_api/v1/users/{id}
  4. 4Pass the Copper API key from your connected account as an Authorization header
  5. 5Call Slack's users.lookupByEmail with the returned email to get the Slack member ID
What you should see: The step output should include a slackUserId field like 'U04ABCD1234' and a display name like 'Jordan Lee'. These values feed directly into the Slack message step.
Common mistake — If the assigned Copper user has never logged into your Slack workspace with that email, users.lookupByEmail returns a users_not_found error. Build a fallback in the code to post to a default #sales-leads channel instead of failing silently.
6

Workflow Canvas > + Add a step > Slack > Send a Message

Add the Slack send message step

Click '+ Add a step', search for 'Slack', and select the action 'Send a Message'. Connect your Slack account via OAuth — Pipedream will open a Slack authorization window. Set the channel field to the slackUserId from Step 5 prefixed with '@' to send a DM, or hardcode a channel like '#new-leads' for a team channel. Build the message text using the lead fields extracted in Step 4.

  1. 1Click '+ Add a step'
  2. 2Search 'Slack' and select it
  3. 3Choose 'Send a Message' as the action
  4. 4Click 'Connect Slack Account' and authorize via OAuth
  5. 5Set Channel to the slackUserId from Step 5 (for DM) or a channel name like '#new-leads'
What you should see: After clicking 'Test', you should see a success response from Slack's API with ok: true and a timestamp. Check Slack — the message should appear in the rep's DMs or the target channel within 2-3 seconds.
Common mistake — Slack DMs to a user ID require the chat:write scope. If you authenticated Slack using an older connected account on Pipedream, it may be missing this scope. Delete the connection, re-add it, and confirm chat:write appears in the OAuth permission list.
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
7

Workflow Canvas > Slack Step > Blocks field

Format the Slack message with Block Kit

Plain text Slack messages work but look poor. In the Slack step, switch the 'Text' field to 'Blocks' and paste a Block Kit JSON payload. Include the lead name as a header, company and phone in a section block, and a button block linking directly to the Copper lead URL (format: https://app.copper.com/companies/{leadId}). This gives reps one-click access to the record without searching.

  1. 1In the Slack step, find the 'Blocks' input field
  2. 2Paste the Block Kit JSON (construct this in the Node.js step before passing it to Slack)
  3. 3Reference the lead name, company, phone, and Copper URL from Step 4's output
  4. 4Include a fallback text value in the 'Text' field for notification previews
  5. 5Click 'Test' to preview the rendered message
What you should see: The Slack message should render with a bold header showing the lead name, two lines of contact details, and a clickable 'View in Copper' button. The notification preview on mobile shows the fallback text.
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.
8

pipedream.com > Workflows > + New Workflow

Handle lead reassignment events separately

Go back to Pipedream's Workflows list and create a second workflow. This one handles the 'Lead Updated' events where the assignee field specifically changed. Use the same Copper webhook URL (Copper already sends both events there) but add a filter in the code step that checks if the assignee_id in the current payload differs from the previous one. Copper's webhook payload includes a previous_assignee_id field on update events.

  1. 1Create a second workflow named 'Copper Lead Reassignment → Slack'
  2. 2Use an HTTP / Webhook trigger (not the Copper app trigger) to receive the same Copper webhook
  3. 3Add a Node.js filter step that checks: event.type === 'update' && event.assignee_id !== event.previous_assignee_id
  4. 4Reuse the same rep lookup and Slack message steps from the first workflow
  5. 5Register this second Pipedream webhook URL in Copper as an additional webhook endpoint
What you should see: When you reassign a lead in Copper, only the reassignment workflow fires a Slack message. The creation workflow ignores updates. Both workflows show separate event logs in Pipedream.
Common mistake — Copper does not guarantee that previous_assignee_id is always present in the payload — it appears only on leads that had a prior assignee. Add a null check in your filter step or the workflow will throw an undefined comparison error on first-assignment updates.
9

Workflow Canvas > + Add a step > Custom Code > Node.js

Add error handling and a fallback notification

Add a final Node.js step after the Slack action using Pipedream's $.flow.exit and try/catch pattern. If the Slack API call fails (rate limit, invalid user ID, missing scope), catch the error and post a fallback message to a hardcoded admin Slack channel like '#automation-errors'. This prevents leads from being silently dropped. Log the error payload so you can debug the specific lead that failed.

  1. 1Click '+ Add a step' after the Slack message step
  2. 2Select 'Custom Code' > 'Run Node.js code'
  3. 3Wrap the Slack call in a try/catch block
  4. 4On catch, use the Slack step to post to '#automation-errors' with the error message and lead ID
  5. 5Click 'Deploy' when done
What you should see: When you test with a bad Slack user ID, the workflow should post to #automation-errors instead of crashing. The Pipedream event log should show 'Completed' status, not 'Error'.
10

pipedream.com > Workflows > [Your Workflow] > Deploy

Test end-to-end and deploy

Create a real test lead in Copper and assign it to yourself. Watch the Pipedream event log in real time — you should see the webhook arrive, each step execute green, and the Slack message land within 5-10 seconds. Then reassign the lead to a colleague and confirm the second workflow fires. Once both pass, click 'Deploy' on each workflow to move them from test mode to live.

  1. 1Create a new lead in Copper and assign it to yourself
  2. 2Open Pipedream and watch the event log under your workflow
  3. 3Verify all steps show green checkmarks
  4. 4Check Slack for the DM or channel message
  5. 5Click 'Deploy' on both workflows to go live
What you should see: Both workflows show 'Active' status with green indicators in the Pipedream Workflows list. The Slack message arrives with correct lead name, company, phone, and a working Copper link.

Paste this into the Node.js code step added in Step 4. It handles event filtering, Copper user resolution, Slack user ID lookup, and Block Kit message construction in one step — so the Slack action step only needs to receive a pre-built payload.

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;

    // Exit early for non-assignment update events
    if (event.type === 'update') {
      const prevAssignee = event.previous_assignee_id ?? null;
      const currAssignee = event.assignee_id ?? null;
      if (prevAssignee === currAssignee) {
        $.flow.exit('Not an assignee change — skipping');
      }
    }

    const isReassignment = event.type === 'update';
    const leadId = event.id;
    const leadName = event.name || 'Unknown Lead';
    const company = event.company_name || '—';
    const phone = event.phone_numbers?.[0]?.number || '—';
    const status = event.status || '—';
    const copperUrl = `https://app.copper.com/companies/${leadId}`;
    const assigneeId = event.assignee_id;

    if (!assigneeId) {
      $.flow.exit('No assignee on this lead — skipping');
    }

    // Step 1: Resolve Copper user ID → email
    let repEmail;
    try {
      const copperUserRes = await axios({
        method: 'GET',
        url: `https://api.copper.com/developer_api/v1/users/${assigneeId}`,
        headers: {
          'X-PW-AccessToken': process.env.COPPER_API_KEY,
          'X-PW-Application': 'developer_api',
          'X-PW-UserEmail': process.env.COPPER_USER_EMAIL,
          'Content-Type': 'application/json',
        },
      });
      repEmail = copperUserRes.data.email;
    } catch (err) {
      console.error('Failed to fetch Copper user:', err.message);
      throw new Error(`Could not resolve Copper user ${assigneeId}`);
    }

    // Step 2: Resolve email → Slack user ID
    let slackUserId;
    let slackDisplayName;
    try {
      const slackRes = await axios({
        method: 'GET',
        url: 'https://slack.com/api/users.lookupByEmail',
        params: { email: repEmail },
        headers: { Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}` },
      });
      if (!slackRes.data.ok) {
        throw new Error(slackRes.data.error);
      }
      slackUserId = slackRes.data.user.id;
      slackDisplayName = slackRes.data.user.real_name;
    } catch (err) {
      console.error('Slack lookup failed for', repEmail, err.message);
      // Fall back to a team channel rather than failing
      slackUserId = process.env.SLACK_FALLBACK_CHANNEL;
      slackDisplayName = 'Sales Team';
    }

    // Step 3: Build Block Kit payload
    const headerText = isReassignment
      ? `🔄 Lead Reassigned to You: ${leadName}`
      : `🔔 New Lead Assigned: ${leadName}`;

    const blocks = [
      {
        type: 'header',
        text: { type: 'plain_text', text: headerText, emoji: true },
      },
      {
        type: 'section',
        fields: [
          { type: 'mrkdwn', text: `*Company:*\n${company}` },
          { type: 'mrkdwn', text: `*Phone:*\n${phone}` },
          { type: 'mrkdwn', text: `*Status:*\n${status}` },
          { type: 'mrkdwn', text: `*Assigned To:*\n${slackDisplayName}` },
        ],
      },
      {
        type: 'actions',
        elements: [
          {
            type: 'button',
            text: { type: 'plain_text', text: 'View in Copper', emoji: true },
            url: copperUrl,
            style: 'primary',
          },
        ],
      },
    ];

    return {
      slackUserId,
      slackDisplayName,
      blocks: JSON.stringify(blocks),
      fallbackText: `${headerText} — ${company} | ${phone}`,
      copperUrl,
      leadName,
      isReassignment,
    };
  },
});
Pipedream
▶ Deploy & test
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 Pipedream for this if your team has at least one person comfortable reading Node.js, even if they're not a full-time developer. The user ID resolution step — converting a Copper numeric assignee ID to a Slack member ID — requires two API calls chained together, and doing that cleanly in Zapier or Make requires awkward workarounds. In Pipedream, it's 20 lines of async/await. The other reason to pick Pipedream: webhook processing is genuinely instant. Copper fires the event, Pipedream receives and executes it in 2-5 seconds, and the rep has a Slack message before they've finished saving the lead. If your team is entirely non-technical and nobody wants to touch code, use Zapier's Copper + Slack integration instead — the user lookup step is harder to build but Zapier's lookup actions can approximate it.

Cost

Pipedream's free tier gives you 10,000 credits/month. This workflow burns roughly 30 credits per run (Copper user lookup, Slack user lookup, Slack send). At 50 lead events per day that's 1,500 credits/day or 45,000 credits/month — you'll need the $19/month plan, which includes 100,000 credits. Make's equivalent setup costs $9/month for 10,000 operations and handles the same volume for less. But Make doesn't give you inline Node.js, so the user ID resolution requires a separate HTTP module chain that's fragile to maintain. Zapier's equivalent is $49/month at the volume needed for multi-step Zaps. Pipedream at $19/month is the right price-to-capability ratio for this specific workflow.

Tradeoffs

Zapier handles the Copper trigger more reliably out of the box — their native Copper integration has been tested against edge cases for years and you won't hit the payload parsing issues Pipedream sometimes surfaces with Copper's nested phone_numbers array. Make's scenario debugger is better than Pipedream's event inspector for visual step-by-step tracing when something breaks. n8n lets you self-host, which matters if your Copper data has GDPR or data residency constraints. Power Automate has no usable Copper connector and would require custom HTTP actions for everything — skip it here. Pipedream still wins for this use case because the code step makes the two-API-lookup pattern clean, the webhook trigger is fastest, and the $19/month plan covers most small sales teams without hitting limits.

Three things you'll hit after setup. First: Copper's webhook fires on every field edit, not just assignments. If a rep updates a phone number, your workflow triggers. The filter step is not optional — without it, reps get 10-20 Slack pings per lead per day. Second: Copper's API rate limit is 600 requests per minute per account. If you bulk-import 500 leads at once (common after a trade show), Copper fires 500 webhooks in under a minute and your user-lookup calls will start hitting 429 errors. Add retry logic with exponential backoff in your code step or set Pipedream's concurrency limit to throttle execution. Third: the Copper Users API occasionally returns a cached stale email if a user recently changed their Copper account email. If a rep reports not receiving alerts, check that their Copper email and Slack email are currently in sync — not just that they matched at setup time.

Ideas for what to build next

  • Add a Slack reply thread for rep acknowledgmentExtend the workflow to capture a Slack reply (or emoji reaction) from the rep and update the Copper lead's status to 'In Progress' via the Copper API — closes the loop so managers can see who has acknowledged their leads.
  • Build a daily digest for unacknowledged leadsAdd a second scheduled Pipedream workflow that runs at 9 AM each morning, queries Copper for leads assigned in the last 24 hours still in 'New' status, and posts a digest to #sales-leads — catches anything that slipped through without pinging reps repeatedly.
  • Route high-value leads to a separate #hot-leads channelAdd a conditional branch in the Node.js step that checks the lead's source or a custom Copper field for lead score — leads above a threshold get posted to both the rep's DM and a shared #hot-leads channel so the whole team sees priority prospects.

Related guides

Was this guide helpful?
Slack + Copper overviewPipedream profile →