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

How to Send Daily Copper Pipeline Updates to Slack with Power Automate

A scheduled Power Automate flow queries Copper for open deals, calculates pipeline totals and forecast values, then posts a formatted summary to a Slack channel every morning.

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

Best for

Sales teams already inside Microsoft 365 who want a zero-touch morning pipeline digest posted to Slack without opening Copper.

Not ideal for

Teams that need real-time deal-stage alerts — use an event-triggered flow or Zapier's Copper new-deal trigger instead.

Sync type

scheduled

Use case type

reporting

Real-World Example

💡

A 12-person B2B SaaS sales team runs this flow every weekday at 8 AM to post a Copper pipeline snapshot to their #sales-daily Slack channel. Before this, the sales manager pulled the report manually from Copper each morning and pasted numbers into Slack — a 15-minute task that slipped on busy days. Now leadership sees total pipeline value, weighted forecast, and the top 5 deals by close date before their 8:30 standup.

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

Copper API key — generate one in Copper under Settings > Integrations > API Keys. Your Copper user must have a role that allows reading Opportunities.
Slack account with permission to post messages to the target channel. Bot tokens work best — create one at api.slack.com/apps with the chat:write and chat:write.public scopes.
Power Automate account with a license that includes the HTTP connector (Premium). HTTP is a Premium connector — it requires a Power Automate per-user or per-flow plan.
Access to make.powerautomate.com and permission to create new flows in your Microsoft 365 tenant. Some tenants restrict flow creation to admins.
A real Copper opportunity array JSON response for generating the Parse JSON schema. Run a test call against https://api.copper.com/developer_api/v1/opportunities/search with Postman or curl before starting.

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Deal Namename
Monetary Valuemonetary_value
Close Dateclose_date
Stage IDstage_id
Statusstatus
3 optional fields▸ show
Pipeline IDpipeline_id
Assignee IDassignee_id
Win Probabilitywin_probability

Step-by-Step Setup

1

My flows > + New flow > Scheduled cloud flow

Create a new Scheduled cloud flow

Go to make.powerautomate.com and sign in. Click 'My flows' in the left sidebar, then click '+ New flow' at the top and select 'Scheduled cloud flow' from the dropdown. Give the flow a name like 'Copper Daily Pipeline Digest', set the start time to 8:00 AM in your local timezone, and set the repeat interval to 1 day. Click 'Create' to land on the flow canvas.

  1. 1Click 'My flows' in the left sidebar
  2. 2Click '+ New flow' at the top of the page
  3. 3Select 'Scheduled cloud flow'
  4. 4Enter flow name: 'Copper Daily Pipeline Digest'
  5. 5Set start time to 8:00 AM local time, interval to 1 Day
  6. 6Click 'Create'
What you should see: You land on the flow canvas with a single 'Recurrence' trigger block showing your 8:00 AM daily schedule.
Common mistake — Power Automate schedules run in UTC by default. If you type 8:00 AM without adjusting the timezone field inside the Recurrence trigger, the message will post at the wrong local time. Expand 'Show advanced options' inside the trigger and set the 'Time zone' field explicitly.
2

Flow canvas > + New step > search 'HTTP' > HTTP action

Connect to Copper via HTTP

Copper does not have a native Power Automate connector, so you pull data using the HTTP action against Copper's REST API. Click '+ New step', search for 'HTTP', and select the 'HTTP' action (not Premium HTTP + Swagger). You will configure a GET request to Copper's opportunities endpoint. Set Method to GET and URI to 'https://api.copper.com/developer_api/v1/opportunities/search'. You need three headers: 'X-PW-AccessToken' (your Copper API key), 'X-PW-Application' (set to 'developer_api'), and 'Content-Type' ('application/json').

  1. 1Click '+ New step' below the Recurrence trigger
  2. 2Type 'HTTP' in the search bar and select the 'HTTP' action
  3. 3Set Method to 'POST' (Copper's search endpoint requires POST even for reads)
  4. 4Set URI to 'https://api.copper.com/developer_api/v1/opportunities/search'
  5. 5Add header 'X-PW-AccessToken' with your Copper API key value
  6. 6Add header 'X-PW-Application' with value 'developer_api'
  7. 7Add header 'Content-Type' with value 'application/json'
  8. 8In the Body field paste: {"page_size": 200, "status": "Open"}
What you should see: The HTTP action block shows Method: POST, the Copper URL, and three headers listed. No test result yet — that comes in step 4.
Common mistake — Copper's /opportunities/search endpoint is a POST, not a GET, even though you are reading data. Using GET returns a 405 error. Double-check the method dropdown.
3

Flow canvas > + New step > search 'Parse JSON' > Parse JSON action

Parse the Copper API response

Add a 'Parse JSON' action so Power Automate understands the array of deal objects Copper returns. Click '+ New step', search 'Parse JSON', and select it. In the 'Content' field, click in the box and select 'Body' from the HTTP step's dynamic content panel. For the Schema, click 'Generate from sample' and paste in a real JSON snippet from a Copper API test call (use Postman or curl with your API key first). The schema needs to capture at minimum: id, name, monetary_value, close_date, stage_id, pipeline_id, and assignee_id.

  1. 1Click '+ New step'
  2. 2Search 'Parse JSON' and select it
  3. 3Click the 'Content' field and pick 'Body' from the HTTP dynamic content panel
  4. 4Click 'Generate from sample'
  5. 5Paste a real Copper opportunity array JSON response and click 'Done'
What you should see: The Parse JSON block shows a valid schema with properties like 'name', 'monetary_value', 'close_date', and 'stage_id' listed. Green checkmark on the block.
Common mistake — If any deal in your Copper account has a null field (like missing close_date), the auto-generated schema will type that field as 'null' and parsing will fail on other records. Manually edit the schema to type nullable fields as ["string", "null"] or ["number", "null"].
4

Flow canvas > Save > Test > Manually > Run flow

Test the HTTP call and confirm deal data

Before building the message logic, verify real data flows through. Click 'Save' in the top right, then click 'Test' > 'Manually' > 'Run flow'. After the run completes, click the HTTP action block and expand 'Outputs' to see the raw JSON body. Check that deals are returning with monetary_value and close_date populated. If you see an empty array, your Copper API key or headers are wrong — fix before moving on.

  1. 1Click 'Save' in the top right
  2. 2Click 'Test' in the top right
  3. 3Select 'Manually' then click 'Run flow'
  4. 4After the run, click the HTTP block to expand its output
  5. 5Confirm deal objects appear in the 'Body' output
What you should see: The HTTP block output shows a JSON array of deal objects. You can see deal names, monetary values, and close dates in the raw output panel.
Power Automate
▶ Test flow
executed
Slack
Copper
Copper
🔔 notification
received
5

Flow canvas > + New step > search 'Compose' > Compose action

Calculate total pipeline value with a Compose action

You need to sum all deal values before posting to Slack. Add a 'Compose' action and use the Power Automate expression editor to total monetary_value across all parsed deals. Click '+ New step', add 'Compose', then click inside the Inputs field and switch to the 'Expression' tab. Enter the formula shown in the pro tip section below. This produces a single number representing total open pipeline value in dollars.

  1. 1Click '+ New step' and add a 'Compose' action
  2. 2Click inside the Inputs field
  3. 3Click the 'Expression' tab in the dynamic content panel
  4. 4Enter: sum(body('Parse_JSON')['monetary_value'])
  5. 5Click 'OK'
What you should see: The Compose block shows your expression in the Inputs field. After a test run, the Outputs panel shows a single dollar total like 487500.
Common mistake — Power Automate's sum() function on a parsed JSON array works only if all monetary_value fields are typed as numbers in your schema. If any came through as strings, wrap each value in int() or float() inside an apply-to-each loop first.
6

Flow canvas > + New step > Data Operations > Select

Build the top 5 deals list with Select and Filter

Add a 'Select' action to extract just the fields you need for the Slack message. Click '+ New step', search 'Select', and choose the Data Operations 'Select' action. Set 'From' to the Parse JSON output array. Map the key-value pairs: 'Deal' to the name field, 'Value' to monetary_value, 'Close' to close_date, and 'Stage' to stage_id. Then add a second 'Compose' action that uses the first(skip(sort(body('Select')), 0)) pattern — or simply use the expression in the pro tip — to pull the top 5 by close date.

  1. 1Click '+ New step' and search 'Select'
  2. 2Choose 'Select' under Data Operations
  3. 3Set 'From' to the Parse JSON body output
  4. 4Add Map row: key 'Deal', value = name dynamic field
  5. 5Add Map row: key 'Value', value = monetary_value dynamic field
  6. 6Add Map row: key 'Close', value = close_date dynamic field
  7. 7Add Map row: key 'Stage', value = stage_id dynamic field
What you should see: The Select action produces a clean array of objects with only the four fields you mapped, visible in the test output panel.
Common mistake — Stage_id from Copper is a numeric ID, not a human-readable label like 'Proposal Sent'. The message will show numbers like '123456' unless you either maintain a manual mapping in a Compose or call the Copper /pipeline_stages endpoint in a separate HTTP step to resolve IDs to names.
Slack
SL
trigger
filter
Deal Stage
matches criteria?
yes — passes through
no — skipped
Copper
CO
notified
7

Flow canvas > + New step > search 'Compose' > Compose action

Format the Slack message body

Add a final 'Compose' action to build the full Slack message string. This is where you combine the pipeline total from step 5 and the deal list from step 6 into a readable block. Use Slack's mrkdwn formatting: bold with *asterisks*, bullet points with a dash. Write the expression in the Inputs field mixing static text with dynamic content tokens. A sample structure: '*Daily Pipeline Report — [date]*\nTotal Open Pipeline: $[total]\n\n*Top Deals by Close Date:*\n[deal list]'.

  1. 1Add another 'Compose' action
  2. 2Click Inputs and switch between 'Dynamic content' and 'Expression' tabs to mix text and values
  3. 3Start with static text: '*Daily Pipeline Report — '
  4. 4Insert expression: formatDateTime(utcNow(), 'MMM dd yyyy')
  5. 5Add pipeline total from the earlier Compose output
  6. 6Add the formatted deal list from the Select output
What you should see: The Compose Inputs field shows a mix of static text and dynamic tokens. After a manual test run, the Outputs panel shows a fully formatted Slack message string.
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

Flow canvas > + New step > search 'Slack' > Post message (V2)

Connect your Slack account

Add the Slack action to post the message. Click '+ New step', search 'Slack', and select 'Post message (V2)' — not the older 'Post message' action, which is deprecated. Power Automate will prompt you to sign in to Slack. Click 'Sign in' and authenticate with the Slack workspace account that has permission to post to your #sales-daily channel. After authentication, the connection appears in the left sidebar under 'Connections'.

  1. 1Click '+ New step'
  2. 2Search 'Slack' in the connector search bar
  3. 3Select 'Post message (V2)'
  4. 4Click 'Sign in' in the authentication prompt
  5. 5Log in with your Slack workspace credentials
  6. 6Authorize the Power Automate app in Slack's permissions screen
What you should see: The Slack action block shows a green connection indicator and your workspace name. The 'Channel' and 'Message Text' fields become active.
Common mistake — The Slack connection is tied to the individual user account you authenticate with. If that person leaves the company or deactivates their Slack account, the flow breaks silently. Use a shared service account or Slack bot token instead.
Power Automate settings
Connection
Choose a connection…Add
click Add
Slack
Log in to authorize
Authorize Power Automate
popup window
Connected
green checkmark
9

Flow canvas > Slack - Post message (V2)

Configure the Slack post action

With the Slack connection active, fill in the action fields. Set 'Channel' to the Slack channel where you want the digest posted — type the channel name directly (e.g. #sales-daily) or pick from the dropdown. Set 'Message Text' to the output of the final Compose action from step 7. Leave 'Bot Name' blank to post as the authenticated user, or enter a display name like 'Pipeline Bot' if you used a bot token. Do not use the 'Blocks' field here unless you want to build a Block Kit payload separately.

  1. 1Click inside the 'Channel' field and type or select '#sales-daily'
  2. 2Click inside 'Message Text' and select the Compose output from step 7 via dynamic content
  3. 3Optionally enter 'Pipeline Bot' in the 'Bot Name' field
  4. 4Leave all other fields blank
What you should see: The Slack action shows Channel: #sales-daily and Message Text: showing the Compose token. The block has no red validation errors.
10

Flow canvas > HTTP action > ... > Configure run after

Add error handling with a Parallel Branch

If the Copper HTTP call fails, you want Slack to notify you rather than silently drop the report. Click the three dots on the HTTP action block and select 'Configure run after'. Add a second branch that runs only on failure or timeout. In that branch, add a Slack 'Post message (V2)' action pointing to the same channel with message: '*Pipeline report failed* — Copper API call returned an error. Check Power Automate run history.' This prevents the team from assuming no news means no deals.

  1. 1Click the '...' menu on the HTTP action block
  2. 2Select 'Configure run after'
  3. 3Check 'has failed' and 'has timed out' boxes, uncheck 'is successful'
  4. 4Click 'Done'
  5. 5Add a Slack 'Post message (V2)' action in this failure branch with an error message
What you should see: The canvas shows a forked path — the main success path continues to Parse JSON, while a separate failure path leads to a Slack error notification block.
11

My flows > Copper Daily Pipeline Digest > Turn on

Test end-to-end and activate

Click 'Save', then 'Test > Manually > Run flow' one final time. Watch the flow run live in the canvas — each block turns green as it succeeds. Check your #sales-daily Slack channel within 30 seconds to confirm the formatted message arrived. If everything looks correct, click 'Turn on' (the flow is already on if you saved it as a scheduled flow, but verify the toggle in My flows shows Active). The flow will now run automatically every weekday morning at 8:00 AM.

  1. 1Click 'Save' in the top right
  2. 2Click 'Test', select 'Manually', click 'Run flow'
  3. 3Watch each block turn green on the canvas
  4. 4Open Slack and confirm the message appears in #sales-daily
  5. 5Navigate to 'My flows' and confirm the flow status shows 'On'
What you should see: Your Slack channel shows the formatted pipeline digest with total value and top deals. The flow status in My flows reads 'On' with the next scheduled run time displayed.
Common mistake — Scheduled flows in Power Automate only trigger on the schedule if the flow is saved AND active. It is possible to save a flow that stays in draft. Confirm the toggle in My flows shows green/On, not grey/Off.

Paste this into two separate 'Compose' actions on the Power Automate canvas: one to calculate the weighted forecast (place it after your Parse JSON and Select steps), and one to build the formatted deal list string. In each Compose, click the Inputs field, switch to the 'Expression' tab, and enter the expression shown. The deal list expression assumes your Select action is named 'Select_Deals' — rename it to match whatever you called yours.

JavaScript — Code Step// Compose 1 — Weighted Forecast Total
▸ Show code
// Compose 1 — Weighted Forecast Total
// Expression tab in Power Automate Compose action:
div(

... expand to see full code

// Compose 1 — Weighted Forecast Total
// Expression tab in Power Automate Compose action:
div(
  sum(
    body('Select_Deals')?['WeightedValue']
  ),
  1
)

// Add 'WeightedValue' to your Select action Map with this expression:
mul(
  item()?['monetary_value'],
  div(float(item()?['win_probability']), 100)
)

// Compose 2 — Format deal list as Slack mrkdwn string
// Expression tab:
join(
  take(
    sort(
      body('Select_Deals'),
      'Close'
    ),
    5
  ),
  '\n'
)

// Then wrap each item in a Compose with:
concat(
  '- ',
  item()?['Deal'],
  ' — $',
  string(item()?['Value']),
  ' | Closes: ',
  formatDateTime(item()?['Close'], 'MMM dd')
)

Scaling Beyond 200+ open deals in Copper+ Records

If your volume exceeds 200+ open deals in Copper records, apply these adjustments.

1

Handle Copper API pagination

Copper's /opportunities/search endpoint returns a maximum of 200 records per request. If you have more than 200 open deals, the flow silently truncates the data. Add a 'page_number' field to the request body starting at 1, then use a Do Until loop that increments the page number and keeps calling the API until an empty array is returned. Merge results with a Union() expression in a Compose action.

2

Summarize instead of listing all deals

Above 50 deals, listing every deal in a Slack message becomes unreadable. Switch the message format to show only aggregate stats (total pipeline, weighted forecast, count by stage) plus just the top 5 deals by close date. Save the full list to a SharePoint file or send it as a Slack file attachment using the 'Upload file' action instead.

3

Increase HTTP timeout for large datasets

The HTTP action in Power Automate has a 120-second default timeout. Copper queries with 500+ deals can hit this limit. In the HTTP action settings, enable 'Asynchronous Pattern' under Settings to handle long-running requests. Alternatively, filter the Copper query server-side to a specific pipeline or date range to reduce response size.

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 Power Automate for this if your team is already inside Microsoft 365 and IT manages your automation environment centrally. Power Automate's scheduled flow trigger is solid, the Slack connector works without extra setup, and the run history logs integrate with your existing Microsoft compliance and audit tooling. The one scenario where you should pick something else: if your team has no developer resources and no Premium connector license. The HTTP action — required to talk to Copper — is Premium-only at $15/user/month. Make handles this same workflow for free using its HTTP module with no plan tier required.

Cost

The cost math is straightforward. This flow uses roughly 10-15 actions per run (HTTP call, Parse JSON, two Compose steps, Select, Slack post, error branch). At one run per weekday, that is ~22 runs per month or about 330 action executions. Power Automate's per-user plan ($15/month) includes 40,000 actions/month, so you will never hit the cap. The per-flow plan ($100/month for 5 flows) is overkill unless you are running this for multiple teams. Make's free tier gives you 1,000 operations/month — this flow fits comfortably for free. Zapier's equivalent on the Professional plan runs $49/month for scheduled Zaps. Power Automate wins on cost if you already pay for Microsoft 365 E3/E5, which includes some Power Automate capacity. Without that, Make is cheaper.

Tradeoffs

Here is where each competitor has a real edge. Make has a native Copper module with pre-built authentication — no HTTP action, no manual headers, no Premium connector required. Setup takes half the time. Zapier has a cleaner schedule trigger UI and a dedicated Copper 'Find Opportunities' action, so non-technical users can build this in 20 minutes without writing any expressions. n8n gives you a Function node where you can write the entire aggregation in JavaScript in one step rather than chaining Compose actions — cleaner for complex formatting. Pipedream lets you pull from Copper and post to Slack in ~30 lines of async JavaScript with full npm access, which is the fastest path if someone on your team codes. Power Automate is still the right call if you need SSO, Microsoft audit logs, DLP policies applied to the flow, or you are in a tenant where IT has blocked external automation tools.

Three things you will hit after setup. First: Copper's close_date comes back as a Unix timestamp (seconds since epoch), not a formatted date string. Power Automate's formatDateTime() function expects ISO 8601 format. You must convert it first: addSeconds('1970-01-01T00:00:00Z', int(item()?['close_date'])). Skip this and your dates display as raw numbers. Second: Power Automate's Slack connector occasionally loses its connection token when Slack rotates OAuth tokens — you will get a 'Connection is not valid' error with no warning in the flow itself. Check the Connections page in the left sidebar monthly and re-authenticate if the Slack connection shows a warning icon. Third: if the Copper API is slow or rate-limited (Copper allows 600 requests per minute), your HTTP action will time out without a meaningful error message in Power Automate's run history. Add a response timeout of 30 seconds in the HTTP action settings and configure the failure branch to fire on timeout, not just failure.

Ideas for what to build next

  • Add a Weekly Closed-Won SummaryCreate a second scheduled flow that fires every Friday at 5 PM, filters Copper opportunities by status 'Won' and close_date within the last 7 days, and posts a wins recap to a separate #sales-wins Slack channel. Reuse the same HTTP and Parse JSON setup from this flow.
  • Route Deal Alerts by OwnerExtend the flow to resolve assignee_id to a Slack user ID using a lookup table in a SharePoint list, then send each rep a direct Slack message with only their own deals rather than one broadcast to the whole channel.
  • Add a Copper Deal Stale AlertAdd a filter inside the Select action that flags deals with no activity in 14+ days (using Copper's date_last_contacted_at field), and call out those specific deals in the Slack message under a separate 'Deals Needing Attention' section.

Related guides

Was this guide helpful?
Slack + Copper overviewPower Automate profile →