

How to Create Copper Tasks from Slack with Pipedream
Listens for a Slack slash command or emoji reaction and instantly creates a follow-up task in Copper CRM, pre-filled with the prospect name, due date, and assignee parsed from the message.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Small-to-mid sales teams using Copper and Slack together who want to log follow-up tasks without leaving the conversation thread
Not ideal for
Teams that need two-way sync between Slack threads and Copper task updates — use a dedicated Copper webhook listener for that instead
Sync type
real-timeUse case type
importReal-World Example
A 12-person SaaS sales team at a seed-stage company holds all prospect discussions in Slack. Before this workflow, a rep had to copy context from Slack, open Copper, find the right contact, and manually create a task — taking 3-4 minutes per task and often skipped entirely. Now a rep types /copper-task follow up with Acme Corp by Friday @jess in any channel, and a task appears in Copper within 5 seconds, assigned to the right person with a parsed due date.
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 | ||
| Task Name | name | |
| Due Date | due_date | |
| Status | status | |
5 optional fields▸ show
| Assignee ID | assignee_id |
| Related Resource Type | related_resource.type |
| Related Resource ID | related_resource.id |
| Priority | priority |
| Details | details |
Step-by-Step Setup
pipedream.com > Workflows > New Workflow
Create a new Pipedream Workflow
Go to pipedream.com and sign in. Click the green 'New Workflow' button in the top-left of the dashboard. Give the workflow a clear name like 'Slack → Copper: Follow-up Tasks' so it's easy to find later. Pipedream opens a blank canvas with a trigger slot at the top.
- 1Click 'New Workflow' in the left sidebar
- 2Enter the workflow name 'Slack → Copper: Follow-up Tasks'
- 3Click 'Create' to open the workflow editor
Workflow Editor > Add Trigger > Slack > Slash Command
Add a Slack Slash Command trigger
Click the grey 'Add Trigger' block. Search for 'Slack' in the app search bar and select it. From the trigger list, choose 'Slash Command' — this fires every time a user invokes your custom slash command in any channel. Pipedream will generate a unique webhook URL that Slack will POST to when the command is used. Copy this URL; you'll need it in step 3.
- 1Click the 'Add Trigger' block
- 2Type 'Slack' in the search field and select the Slack app
- 3Scroll to find 'Slash Command' and click it
- 4Copy the generated webhook URL shown in the trigger config panel
api.slack.com/apps > Your App > Slash Commands > Create New Command
Register the Slash Command in your Slack App
Go to api.slack.com/apps and open your existing Slack app, or click 'Create New App' if you don't have one. Navigate to 'Slash Commands' in the left sidebar and click 'Create New Command'. Set the command to /copper-task, paste the Pipedream webhook URL into the 'Request URL' field, and add a short description like 'Create a follow-up task in Copper'. Save the command, then reinstall the app to your workspace from 'Install App' in the left nav.
- 1Open api.slack.com/apps and select your Slack app
- 2Click 'Slash Commands' in the left sidebar
- 3Click 'Create New Command'
- 4Set Command to '/copper-task', paste the Pipedream webhook URL into 'Request URL'
- 5Click 'Save', then go to 'Install App' and click 'Reinstall to Workspace'
Workflow Editor > + Add Step > Run Node.js code
Add a step to immediately acknowledge Slack
Slack will time out if it doesn't receive a 200 response within 3 seconds. Add a new step in Pipedream right after the trigger by clicking the '+' button. Select 'Run Node.js code'. Use $.respond() to immediately return a 200 acknowledgment to Slack before the rest of the workflow runs. This step must be the first step after the trigger.
- 1Click the '+' button below the Slack trigger block
- 2Select 'Run Node.js code' from the step menu
- 3Paste the acknowledgment code into the code editor
- 4Name the step 'ack_slack'
Workflow Editor > + Add Step > Run Node.js code
Parse the slash command text
The Slack slash command payload arrives as a URL-encoded body. Pipedream's trigger automatically parses it into steps.trigger.event.body. Add another Node.js code step to extract the task name, due date, and assignee from the command text. For example, /copper-task follow up with Acme Corp by Friday @jess sends text='follow up with Acme Corp by Friday @jess'. Write a simple parser to split on 'by' for the date and '@' for the user mention.
- 1Click '+' below the ack_slack step
- 2Select 'Run Node.js code'
- 3Name the step 'parse_command'
- 4Paste the parsing code that reads steps.trigger.event.body.text
Workflow Editor > + Add Step > Run Node.js code
Look up the Copper contact by name
Copper tasks must be linked to a resource — typically a Person or Opportunity. Add a Node.js code step that calls the Copper People Search API (POST /v1/people/search) with the company or person name extracted from the command text. This returns the Copper person ID you'll attach to the task. Connect your Copper account via 'Connect an Account' in the step config panel — Pipedream stores the API key securely.
- 1Click '+' below the parse_command step
- 2Select 'Run Node.js code'
- 3Name the step 'lookup_copper_contact'
- 4Click 'Connect an Account' and select or add your Copper credentials
- 5Paste the Copper People Search API call code
Workflow Editor > + Add Step > Run Node.js code
Resolve the Slack @mention to a Copper assignee
The @mention in the slash command gives you a Slack user ID, not a name or email. Add a Node.js step that calls the Slack users.info API to get the user's email address, then queries Copper's /v1/users endpoint to find the matching Copper user ID. This ID goes into the task's assignee_id field. Without this step, all tasks would be assigned to the API key owner by default.
- 1Click '+' below the lookup_copper_contact step
- 2Select 'Run Node.js code'
- 3Name the step 'resolve_assignee'
- 4Paste code that calls Slack users.info then matches email against Copper /v1/users
Paste this as a single Node.js code step in Pipedream — it handles Slack's immediate acknowledgment, command parsing, Copper contact lookup, assignee resolution, task creation, and Slack confirmation in one step with full error handling. Place it directly after the Slack Slash Command trigger and name the step 'full_task_pipeline'.
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 body = steps.trigger.event.body;
const rawText = body.text || '';
const channelId = body.channel_id;
const slackUserId = body.user_id;
// Immediately acknowledge Slack to avoid timeout
await $.respond({ status: 200, body: '' });
// --- Parse slash command text ---
// Format: "task description by [date] @mention"
const byIndex = rawText.toLowerCase().lastIndexOf(' by ');
const atIndex = rawText.lastIndexOf('@');
const taskName = byIndex > -1
? rawText.substring(0, byIndex).trim()
: rawText.replace(/@\S+/, '').trim();
const dateStr = byIndex > -1
? rawText.substring(byIndex + 4, atIndex > byIndex ? atIndex : undefined).trim()
: null;
const mentionUsername = atIndex > -1
? rawText.substring(atIndex + 1).trim().split(' ')[0]
: null;
// Convert natural date to Unix timestamp (seconds)
const dueTimestamp = dateStr
? Math.floor(new Date(dateStr).getTime() / 1000)
: Math.floor(Date.now() / 1000) + 86400 * 3; // default: 3 days from now
const copperHeaders = {
'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',
};
// --- Resolve Slack @mention to Copper assignee ID via email ---
let copperAssigneeId = null;
if (mentionUsername) {
try {
const slackUsersResp = await axios.get(
`https://slack.com/api/users.lookupByEmail?email=${mentionUsername}@${process.env.COMPANY_EMAIL_DOMAIN}`,
{ headers: { Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}` } }
);
const slackEmail = slackUsersResp.data?.user?.profile?.email;
if (slackEmail) {
const copperUsersResp = await axios.get(
'https://api.copper.com/developer_api/v1/users',
{ headers: copperHeaders }
);
const matched = copperUsersResp.data.find(u => u.email === slackEmail);
if (matched) copperAssigneeId = matched.id;
}
} catch (e) {
console.log('Assignee resolution failed, proceeding without assignee:', e.message);
}
}
// --- Search for Copper contact by name ---
let relatedResource = null;
try {
const searchResp = await axios.post(
'https://api.copper.com/developer_api/v1/people/search',
{ name: taskName.replace(/^(urgent:|follow up with|check in with)/i, '').trim() },
{ headers: copperHeaders }
);
if (searchResp.data.length > 0) {
relatedResource = { id: searchResp.data[0].id, type: 'person' };
}
} catch (e) {
console.log('Contact lookup failed:', e.message);
}
// --- Create Copper task ---
let copperTask = null;
try {
const taskPayload = {
name: taskName,
due_date: dueTimestamp,
status: 'Open',
details: `Created from Slack #${body.channel_name}: ${rawText}`,
...(copperAssigneeId && { assignee_id: copperAssigneeId }),
...(relatedResource && { related_resource: relatedResource }),
};
const taskResp = await axios.post(
'https://api.copper.com/developer_api/v1/tasks',
taskPayload,
{ headers: copperHeaders }
);
copperTask = taskResp.data;
} catch (e) {
// Notify user of failure via Slack DM
await axios.post(
'https://slack.com/api/chat.postMessage',
{
channel: slackUserId,
text: `❌ Couldn't create Copper task for: "${rawText}"\nCreate it manually: https://app.copper.com/companies/tasks/new`,
},
{ headers: { Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}` } }
);
throw new Error(`Copper task creation failed: ${e.message}`);
}
// --- Send Slack confirmation ---
await axios.post(
'https://slack.com/api/chat.postMessage',
{
channel: channelId,
text: [
`✅ *Task created in Copper*`,
`*Task:* ${copperTask.name}`,
`*Due:* ${new Date(copperTask.due_date * 1000).toDateString()}`,
`*Assigned to:* ${copperAssigneeId ? mentionUsername : 'Unassigned'}`,
relatedResource ? `*Linked contact:* Copper Person #${relatedResource.id}` : '',
`<https://app.copper.com/companies/tasks/${copperTask.id}|View task in Copper>`,
].filter(Boolean).join('\n'),
},
{ headers: { Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}` } }
);
return { copperTaskId: copperTask.id, taskName: copperTask.name, assigneeId: copperAssigneeId };
},
});Workflow Editor > + Add Step > Run Node.js code
Create the task in Copper
Add a final Node.js code step that calls the Copper Tasks API (POST /v1/tasks). Map the parsed values into the request body: name from the command text, due_date as a Unix timestamp, assignee_id from the resolved user, and related_resource linking to the Copper person found in step 6. The Copper API returns the full created task object including its ID.
- 1Click '+' below the resolve_assignee step
- 2Select 'Run Node.js code'
- 3Name the step 'create_copper_task'
- 4Map steps.parse_command.taskName, steps.parse_command.dueDate, steps.resolve_assignee.copper_assignee_id, and steps.lookup_copper_contact.copper_person_id into the POST body
Workflow Editor > + Add Step > Run Node.js code
Send a confirmation back to the Slack user
After the task is created, post a confirmation back to the channel or DM the user who triggered the command. Add a Node.js code step that calls the Slack chat.postMessage API with the task details: task name, due date, assignee, and a link to the Copper task using the format https://app.copper.com/companies/tasks/{task_id}. Use the channel_id from the trigger payload as the target channel.
- 1Click '+' below the create_copper_task step
- 2Select 'Run Node.js code'
- 3Name the step 'notify_slack'
- 4Use steps.trigger.event.body.channel_id as the Slack channel target
- 5Build the message string using steps.create_copper_task.$return_value.id for the Copper link
Workflow Editor > + Add Step > Run Node.js code
Add error handling for failed lookups
If the Copper contact lookup or assignee resolution fails, the workflow should not silently drop the task. Add a Node.js step with try/catch that catches errors from steps 6 and 7, then posts a fallback Slack DM to the command sender with a direct link to create the task manually in Copper. Use steps.trigger.event.body.user_id to target the DM. This prevents tasks from being lost when a contact name doesn't match.
- 1Click '+' after the notify_slack step, or wrap steps 6-9 in a single try/catch step
- 2Name the step 'error_handler'
- 3Use $.send.http or the Slack chat.postMessage API to DM the user on failure
- 4Include the original command text in the DM so the rep has context to fix it manually
Workflow Editor > Deploy button (top right) > Event Inspector (bottom panel)
Deploy and test end-to-end
Click 'Deploy' in the top-right corner of the Pipedream workflow editor to make the workflow live. Open any Slack channel and type /copper-task follow up with Acme Corp by Friday @jess. Watch the Pipedream event inspector (bottom of the workflow editor) to see each step execute in real time. Confirm the task appears in Copper under the matched contact within 5 seconds.
- 1Click the blue 'Deploy' button in the top-right corner
- 2Open a Slack channel and type '/copper-task follow up with Acme Corp by Friday @jess'
- 3Watch the Pipedream Event Inspector update as each step fires
- 4Open Copper and navigate to the matched contact to confirm the task appears
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 includes developers who want to customize the task parsing logic, or if you need the slash command to respond in under 500ms (Pipedream's webhook latency averages 150-200ms). The instant webhook processing and Node.js code steps mean you can write a real date parser, handle edge cases in the command text, and call multiple APIs in sequence without stitching together visual blocks. If your team is non-technical and wants to build this without code, use Zapier's Slack trigger with a Code by Zapier step — it's slower to process but easier to hand off to a non-developer to maintain.
Pipedream's free tier gives you 10,000 credits/month. This workflow consumes roughly 4-6 credits per run (one trigger + four API call steps). At 100 tasks/month, you're using 400-600 credits — well inside free tier. At 1,000 tasks/month you're at 4,000-6,000 credits, still free. The paid Basic plan at $19/month gives 100,000 credits, which handles ~16,000-25,000 tasks/month. Zapier charges per task: at 1,000 tasks/month you'd be on the $29/month Starter plan. Pipedream is cheaper by $10/month at that volume.
Zapier has a pre-built Copper integration with a 'Create Task' action that maps fields visually — no code, 10 minutes to set up, but you lose the ability to parse natural language from the slash command text without a Code by Zapier step. Make handles the webhook response timing well with its HTTP module and can parse the command text using its built-in string functions, but the Copper integration is community-built and less maintained. n8n gives you full code control similar to Pipedream and self-hosted options for teams with data residency requirements — if that's your constraint, n8n is the better pick. Power Automate has no native Copper connector, so you'd be building raw HTTP actions for every API call, which is more work than Pipedream with no advantage. Pipedream wins here because the combination of instant webhooks and Node.js steps solves the hardest part of this workflow: responding to Slack in time while still doing real processing.
Three things you'll hit after launch. First, Copper's People Search returns multiple results when a contact name is ambiguous — if you have 'Acme Corp (East)' and 'Acme Corp (West)', the search returns both and your code picks the first one. Add a step that handles multiple results by posting a Slack message asking the user to clarify. Second, Slack's slash command payload encodes spaces as '+' in the text field — your parser must decode the URL encoding before splitting on keywords, or 'follow+up+with+Acme+Corp' will fail to parse. Use decodeURIComponent(body.text.replace(/\+/g, ' ')) before any string operations. Third, Copper rate-limits API calls to 600 requests per minute. At normal usage this isn't an issue, but if you build a batch digest workflow later (next steps above), a team of 20 reps all checking tasks at 8am simultaneously could briefly hit that limit — add a 100ms delay between Copper API calls in batch scenarios.
Ideas for what to build next
- →Add emoji-reaction triggers — Set up a second Pipedream workflow that listens for a specific emoji reaction (e.g. 📋) on any Slack message and creates a Copper task from the message text — no slash command needed, works directly on existing prospect discussions.
- →Sync Copper task completions back to Slack — Build a reverse workflow using Copper's webhook for task status changes that posts a '✅ Task completed' message to the originating Slack channel when a rep marks the task done in Copper.
- →Add a daily task digest in Slack — Create a scheduled Pipedream workflow that runs every morning at 8am, queries Copper's tasks API for all tasks due today, and posts a grouped digest to the #sales channel with assignee mentions so reps see their day's follow-ups without opening Copper.
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