

How to Create Copper Tasks from Slack with n8n
Listens for a Slack slash command or emoji reaction, parses the message text, and creates a follow-up task in Copper CRM — no manual copy-paste required.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Sales teams who discuss prospects in Slack and want to log follow-up tasks in Copper without leaving the conversation.
Not ideal for
Teams that need two-way sync or want Copper task updates to post back to Slack — build a separate workflow for that.
Sync type
real-timeUse case type
routingReal-World Example
A 12-person B2B sales team at a logistics SaaS company discusses deal updates in a #prospects Slack channel. A rep types '/copper-task Follow up with Acme on pricing — due Friday' and a Copper task appears instantly on the related contact, assigned to that rep. Before this, tasks were created manually at end-of-day — or forgotten entirely — because switching to Copper mid-conversation broke focus.
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 n8n
Copy the pre-built n8n blueprint and paste it straight into n8n. 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 | |
| Related Resource ID | related_resource.id | |
| Related Resource Type | related_resource.type | |
5 optional fields▸ show
| Due Date | due_date |
| Assignee ID | assignee_id |
| Status | status |
| Priority | priority |
| Details | details |
Step-by-Step Setup
api.slack.com/apps > Your App > Slash Commands > Create New Command
Create a Slack Slash Command
Go to api.slack.com/apps, open your app (or create one), and navigate to Slash Commands in the left sidebar. Click 'Create New Command'. Set the command to /copper-task, the Request URL to a placeholder for now — you'll replace it after n8n gives you a webhook URL. Set the short description to 'Create a Copper follow-up task'.
- 1Go to api.slack.com/apps and open or create your Slack app
- 2Click 'Slash Commands' in the left sidebar
- 3Click the green 'Create New Command' button
- 4Enter '/copper-task' in the Command field
- 5Paste a placeholder URL in the Request URL field — you'll update it in Step 3
- 6Click Save
api.slack.com/apps > Your App > OAuth & Permissions
Install the Slack App to Your Workspace
Navigate to 'OAuth & Permissions' in your Slack app settings. Under Bot Token Scopes, add commands and users:read. Scroll up and click 'Install to Workspace', then authorize it. Copy the Bot User OAuth Token — it starts with xoxb-. You'll need this in n8n.
- 1Click 'OAuth & Permissions' in the left sidebar
- 2Scroll to 'Bot Token Scopes' and click 'Add an OAuth Scope'
- 3Add 'commands' and 'users:read' scopes
- 4Click 'Install to Workspace' at the top of the page
- 5Click Allow on the authorization screen
- 6Copy the Bot User OAuth Token (starts with xoxb-)
n8n > New Workflow > + Add Node > Webhook
Create the n8n Workflow and Add a Webhook Trigger
Open your n8n instance and click 'New Workflow'. Add a Webhook node as the trigger. Set the HTTP Method to POST and Authentication to None (Slack signs requests with a header — you'll validate that separately). Click 'Listen for Test Event' to get the webhook URL, then copy it.
- 1Click 'New Workflow' in the top-left of n8n
- 2Click the + button to add a node and search for 'Webhook'
- 3Set HTTP Method to POST
- 4Set Path to something readable like 'copper-task'
- 5Click 'Listen for Test Event' — n8n will display the webhook URL
- 6Copy the webhook URL
api.slack.com/apps > Your App > Slash Commands > /copper-task > Edit
Connect the Webhook URL to Slack
Go back to api.slack.com/apps, open your Slash Command settings, and replace the placeholder Request URL with the n8n webhook URL you just copied. Save the command. Now trigger the slash command from Slack by typing '/copper-task Test follow-up with Acme' in any channel. n8n should receive the payload immediately.
- 1Open your Slack app settings and click 'Slash Commands'
- 2Click 'Edit' next to /copper-task
- 3Paste the n8n webhook URL into the Request URL field
- 4Click Save
- 5Open Slack and type '/copper-task Test follow-up with Acme' in any channel
- 6Press Enter to send
n8n Workflow Editor > + Add Node > Code
Parse the Slash Command Text
Add a Code node after the Webhook trigger. The slash command payload puts everything the user typed after /copper-task into the text field. You need to extract the task name, due date (if included), and any contact reference. Use a JavaScript regex to pull out an optional 'due:YYYY-MM-DD' pattern from the text, and treat the remainder as the task name.
- 1Click the + button after the Webhook node and search for 'Code'
- 2Set Mode to 'Run Once for All Items'
- 3Paste the parsing logic from the Pro Tip section below
- 4Click 'Execute Node' to test with the sample Slack payload
n8n Workflow Editor > + Add Node > HTTP Request
Look Up the Copper Contact or Lead
Add an HTTP Request node to search Copper for the contact mentioned in the Slack message. Copper's API endpoint for searching people is POST https://api.copper.com/developer_api/v1/people/search. Send the contact name (or email if your team includes it in the command) as the query. Set the headers to include X-PW-AccessToken, X-PW-Application (developer_api), and X-PW-UserEmail — all required by Copper.
- 1Add an HTTP Request node after the Code node
- 2Set Method to POST
- 3Set URL to 'https://api.copper.com/developer_api/v1/people/search'
- 4Add headers: X-PW-AccessToken (your Copper API key), X-PW-Application (developer_api), X-PW-UserEmail (your Copper account email), Content-Type (application/json)
- 5Set Body to JSON: { "name": "{{ $json.contactName }}" }
- 6Click Execute Node to test the search
n8n Workflow Editor > + Add Node > IF
Handle No-Match Results with an IF Node
Add an IF node to check whether the Copper search returned at least one result. Set the condition to check if the array length of the HTTP Request output is greater than 0. Wire the False branch to a Slack node that sends a direct message back to the user telling them no contact was found. Wire the True branch to continue to task creation.
- 1Add an IF node after the HTTP Request node
- 2Set Condition to: {{ $json.length }} > 0
- 3On the False branch, add a Slack node set to 'Send a Direct Message'
- 4Configure the Slack DM to message the original user_id with: 'No Copper contact found for that name. Try again with a full name or email.'
- 5On the True branch, continue to the next step
n8n Workflow Editor > + Add Node > HTTP Request
Create the Task in Copper
Add another HTTP Request node on the True branch. This one hits Copper's task creation endpoint: POST https://api.copper.com/developer_api/v1/tasks. The body needs name, due_date (Unix timestamp in milliseconds), assignee_id, and a related resource object pointing to the Copper contact ID. Map these fields from the parsed Slack payload and the contact lookup result.
- 1Add an HTTP Request node on the True branch of the IF node
- 2Set Method to POST
- 3Set URL to 'https://api.copper.com/developer_api/v1/tasks'
- 4Use the same Copper API headers from Step 6
- 5Set Body to JSON using the field mapping from the Field Mapping section below
- 6Click Execute Node to create a test task
n8n Workflow Editor > + Add Node > Slack
Confirm Success Back to Slack
Add a Slack node at the end of the True branch to send a confirmation message. Post to the original channel_id with a message that includes the task name, due date, and a direct link to the Copper contact. This closes the loop so the rep knows the task was created without leaving Slack.
- 1Add a Slack node after the Copper task creation node
- 2Set Operation to 'Send a Message'
- 3Set Channel to {{ $('Webhook').item.json.body.channel_id }}
- 4Set Message to: '✅ Task created in Copper: *{{ $json.taskName }}* — due {{ $json.dueDate }}. View contact: https://app.copper.com/companies/people/{{ $json.copperContactId }}'
- 5Add your Slack Bot Token in the credentials dropdown
- 6Click Execute Node
n8n Workflow Editor > Active Toggle (top right)
Activate the Workflow
Click the toggle in the top-right of the n8n editor to switch the workflow from inactive to active. The webhook URL is now live and will process every /copper-task command your team sends. Test end-to-end from Slack with a real contact name and check that the task appears in Copper within 5 seconds.
- 1Click the gray toggle in the top-right corner of the n8n workflow editor
- 2Confirm the toggle turns green and shows 'Active'
- 3Open Slack and type '/copper-task Follow up with Sarah Chen on proposal — due:2024-03-20'
- 4Check Copper for the new task on Sarah Chen's contact record
- 5Verify the Slack confirmation message appears in the channel
This Code node runs after the Webhook trigger and before the Copper API calls. It parses the raw Slack slash command text to extract the task name, optional due date, and optional contact name — then outputs clean fields for downstream nodes. Paste this into a Code node set to 'Run Once for All Items' mode.
JavaScript — Code Node// Paste into n8n Code node (Run Once for All Items mode)▸ Show code
// Paste into n8n Code node (Run Once for All Items mode) // Parses Slack slash command text into structured Copper task fields const items = $input.all();
... expand to see full code
// Paste into n8n Code node (Run Once for All Items mode)
// Parses Slack slash command text into structured Copper task fields
const items = $input.all();
const payload = items[0].json.body;
const rawText = payload.text || '';
const userId = payload.user_id || '';
const userName = payload.user_name || '';
const channelId = payload.channel_id || '';
const channelName = payload.channel_name || '';
// Extract optional due date in format due:YYYY-MM-DD
const dueDateMatch = rawText.match(/due:(\d{4}-\d{2}-\d{2})/);
const dueDateStr = dueDateMatch ? dueDateMatch[1] : null;
// Convert due date string to Unix timestamp in SECONDS (Copper requires seconds)
let dueDateUnix = null;
if (dueDateStr) {
const dateObj = new Date(dueDateStr + 'T00:00:00Z');
dueDateUnix = Math.floor(dateObj.getTime() / 1000);
}
// Strip the due:YYYY-MM-DD pattern from task name and clean up whitespace
const taskName = rawText
.replace(/due:\d{4}-\d{2}-\d{2}/gi, '')
.replace(/--/g, '-')
.trim()
.replace(/\s{2,}/g, ' ');
// Normalize contact name: assume contact name appears before the first dash or 'on'
// Reps type: "Follow up with Sarah Chen on proposal" — extract "Sarah Chen"
const contactMatch = taskName.match(/with ([A-Z][a-z]+ [A-Z][a-z]+)/i);
const contactName = contactMatch
? contactMatch[1]
.split(' ')
.map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
.join(' ')
: null;
// Build details string for Copper task notes field
const details = `Created from #${channelName} by ${userName} via Slack slash command`;
return [
{
json: {
taskName,
dueDateUnix,
dueDateStr,
contactName,
slackUserId: userId,
slackUserName: userName,
channelId,
channelName,
details,
},
},
];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 n8n for this if your team self-hosts and wants full control over the Slack payload parsing logic. The Code node lets you handle edge cases — multiple contact matches, missing due dates, keyword-based priority detection — without duct-taping together three separate no-code nodes. If your Copper contact names are inconsistent (mixed case, nicknames, abbreviations), n8n's code node lets you normalize them with real JavaScript before the API call. The one scenario where you'd pick something else: if your team has zero engineering capacity and nobody wants to write even 20 lines of JavaScript, Zapier's Slack + Copper integration handles basic task creation through a form-based UI with no code required.
n8n Cloud costs $20/month for up to 2,500 workflow executions. This workflow uses 1 execution per slash command. At 50 reps each sending 3 slash commands per day, that's 150 executions/day, roughly 4,500/month — you'd hit the Starter limit and need the Pro plan at $50/month. If you self-host n8n on a $6/month VPS, the execution cost drops to zero beyond server costs. Zapier would charge per task at ~$50–75/month for the same volume on the Professional plan. Make falls in between at around $9/month on the Core plan, which covers 10,000 operations.
Zapier handles the Slack slash command trigger with a dedicated zap trigger and a pre-built Copper action — setup takes about 15 minutes with no code, but you can't customize how contacts are matched and there's no built-in fallback for multiple results. Make gives you better conditional logic through its router module, and you can branch on match count without a code node, but the Copper integration in Make is community-built and occasionally lags behind Copper's API. Power Automate has no native Copper connector — you'd use HTTP actions for everything, which puts it at the same effort level as n8n but with a worse debugging experience. Pipedream offers the cleanest code-first experience for this use case with built-in Slack and Copper API helpers, and its free tier covers 10,000 invocations/month — genuinely worth considering if you're comfortable with Node.js and want to skip the n8n UI entirely. n8n wins here because it combines visual debugging, the Code node for parsing logic, and self-hosting economics for teams who need all three.
Three things you'll hit after setup. First, Copper rate-limits API requests to 600 per minute per user — that's not a problem at normal slash command volume, but if you run load tests or batch-import tasks, you'll hit 429 errors. Add a Wait node between search and create calls if you're ever running bulk operations. Second, Slack slash commands time out at 3 seconds — if your Copper contact search is slow (sometimes it is on large databases), n8n's immediate 200 response saves you, but any visible slowness in the confirmation message will make reps think it failed. Third, Copper's API returns dates in Unix seconds but its UI displays them in the user's local timezone. A task due March 20 at midnight UTC will show as March 19 for reps in US time zones. Set your due date timestamps to noon UTC instead of midnight to avoid off-by-one day issues.
Ideas for what to build next
- →Sync Copper Task Completion Back to Slack — Build a reverse workflow that polls Copper every 15 minutes for tasks marked complete and posts a summary to the original Slack channel — closes the feedback loop for the whole team.
- →Add Emoji Reaction Trigger as an Alternative — Use the Slack Events API to listen for a specific emoji reaction (e.g. 📋) on any message, then use that message's text as the task name — lets reps create tasks from existing messages without retyping.
- →Route Tasks to the Right Copper Opportunity — Extend the slash command syntax to accept an optional deal name (e.g. /copper-task deal:Acme-Q2 Follow up on pricing) and link the created task to a Copper opportunity instead of just a contact.
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