

How to Send Daily Close Pipeline Updates to Slack with Pipedream
A scheduled Pipedream workflow that pulls pipeline metrics, upcoming tasks, and overdue activities from Close every morning and posts a formatted summary to a Slack channel.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Sales managers at 5-30 person inside sales teams who want a daily Slack digest without paying for a BI tool or asking reps to update dashboards manually.
Not ideal for
Teams that need real-time deal alerts — use a webhook-based workflow instead so updates fire within seconds of a stage change.
Sync type
scheduledUse case type
reportingReal-World Example
A 12-person SaaS inside sales team runs this every weekday at 8:00 AM. Before the automation, managers pulled Close reports manually each morning, a process that took 15-20 minutes and often happened late or not at all. Now, #sales-pipeline gets a formatted Slack message before standup: total open pipeline value, deals moved yesterday, tasks due today, and a list of overdue activities by rep name.
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.
Optional
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Pipeline Total Value | value | |
| Deal Lead Name | lead_name | |
| Assigned Rep | user_name | |
| Expected Close Date | close_date | |
| Deal Status Label | status_label | |
| Task Due Date | due_date | |
| Task Type | type | |
| Task Assigned To | assigned_to | |
1 optional field▸ show
| Opportunity Last Updated | updated |
Step-by-Step Setup
pipedream.com > Workflows > New Workflow
Create a new Pipedream workflow
Go to pipedream.com and sign in. Click 'New Workflow' in the top-right corner. You'll land on the workflow canvas with an empty trigger slot at the top. Give your workflow a name immediately — something like 'Daily Close Pipeline Digest' — using the pencil icon next to 'Untitled Workflow' at the top of the page. Naming it now prevents confusion when you have multiple workflows running.
- 1Click 'New Workflow' in the top-right corner of the Workflows dashboard
- 2Click the pencil icon next to 'Untitled Workflow' at the top of the canvas
- 3Type 'Daily Close Pipeline Digest' and press Enter
Workflow Canvas > Add a trigger > Schedule > Cron Expression
Set the Schedule trigger
Click the 'Add a trigger' block at the top of the canvas. In the trigger search panel, type 'Schedule' and select the 'Schedule' source built into Pipedream. Choose 'Cron Expression' for full control over timing — the simple interval option doesn't let you target specific days of the week. Enter a cron expression for your desired time, for example '0 8 * * 1-5' fires at 8:00 AM UTC Monday through Friday. Adjust the UTC offset to match your team's timezone.
- 1Click 'Add a trigger' on the canvas
- 2Type 'Schedule' in the search box and select the Pipedream-native Schedule source
- 3Select 'Cron Expression' as the schedule type
- 4Enter '0 8 * * 1-5' in the cron field (adjust UTC offset for your timezone)
- 5Click 'Save and continue'
Workflow Canvas > + Add a step > Apps > Close > Make API Request
Connect your Close account
Click '+ Add a step' below the trigger block. Search for 'Close' and select the Close app. Choose the action 'Make API Request' — this gives you direct access to Close's REST API, which is more flexible than the pre-built actions for this reporting use case. In the step configuration panel, connect your Close account by clicking 'Connect Account' and entering your Close API key (found in Close under Settings > API). Pipedream stores this as a Connected Account you can reuse across workflows.
- 1Click '+ Add a step' and search for 'Close'
- 2Select the Close app from the results
- 3Choose 'Make API Request' as the action
- 4Click 'Connect Account' in the step panel
- 5Paste your Close API key and click 'Connect'
Close Step > Method > URL > Query Parameters
Fetch open pipeline opportunities from Close
In the Close 'Make API Request' step, configure the request to hit the Opportunities endpoint. Set the Method to GET and the URL to 'https://api.close.com/api/v1/opportunity/?status_type=active&_limit=200'. This returns up to 200 active opportunities with their value, status, assigned user, and expected close dates. You'll use this data to calculate pipeline totals and identify deals by rep in later steps. Add a query parameter '_fields' with value 'id,lead_id,lead_name,value,status_label,user_name,date_won,close_date,updated' to keep the response payload small.
- 1Set Method to 'GET'
- 2Set URL to 'https://api.close.com/api/v1/opportunity/?status_type=active&_limit=200'
- 3Add query parameter '_fields' with value 'id,lead_id,lead_name,value,status_label,user_name,date_won,close_date,updated'
- 4Click 'Test' to run the step and confirm data returns
Workflow Canvas > + Add a step > Apps > Close > Make API Request
Fetch overdue and today's tasks from Close
Add a second Close 'Make API Request' step. This call targets the Tasks endpoint to retrieve activities due today or overdue. Set the URL to 'https://api.close.com/api/v1/task/?is_complete=false&_order_by=due_date&_limit=100'. You'll filter in the next step using JavaScript, but pulling all incomplete tasks here gives you the full dataset. Close tasks include type (call, email, follow-up), due date, assigned user, and the associated lead name — all fields you need for the daily digest.
- 1Click '+ Add a step' and select Close again
- 2Choose 'Make API Request'
- 3Set Method to 'GET'
- 4Set URL to 'https://api.close.com/api/v1/task/?is_complete=false&_order_by=due_date&_limit=100'
- 5Click 'Test' to confirm task objects return with due_date and assigned_to fields
Workflow Canvas > + Add a step > Code > Run Node.js code
Add a Node.js step to calculate pipeline metrics
Click '+ Add a step' and choose 'Run Node.js code'. This is the core logic step — it takes the raw Close API responses from steps 4 and 5 and computes the numbers you'll post to Slack. You'll calculate total open pipeline value, count deals per rep, identify deals with close dates that have already passed, and split tasks into 'due today' vs 'overdue' buckets. Paste the code from the pro tip section into this step. The step references previous step outputs using Pipedream's 'steps' object.
- 1Click '+ Add a step'
- 2Select 'Code' from the step type options
- 3Choose 'Run Node.js code'
- 4Paste the provided code into the editor
- 5Click 'Test' and confirm the output object contains pipelineTotal, dealsByRep, overdueTasks, and todayTasks keys
Workflow Canvas > + Add a step > Code > Run Node.js code
Format the Slack message with Block Kit
Add another Node.js code step specifically for message formatting. Close API values come back with amount in cents for currency fields — you must divide by 100 to get dollars. Build a Slack Block Kit payload here rather than a plain text string. Block Kit lets you use bold headers, dividers, and bullet lists that render cleanly on both desktop and mobile Slack. This step outputs a single 'blocks' array that the next step passes directly to the Slack API.
- 1Click '+ Add a step' and select 'Run Node.js code'
- 2Rename the step to 'format_message' using the step header
- 3Build the blocks array using the metrics from the previous step output
- 4Click 'Test' and verify the output contains a valid 'blocks' array with header, section, and divider types
Workflow Canvas > + Add a step > Apps > Slack > Send Message to a Channel
Connect your Slack account
Add a new step and search for 'Slack'. Select the 'Send Message to a Channel' action. Click 'Connect Account' and authorize Pipedream to post to your Slack workspace. Pipedream uses OAuth and will redirect you to Slack's permission screen. Grant the 'chat:write' and 'chat:write.public' scopes — you need both to post to channels your Slack app hasn't been explicitly added to. After authorization, you'll return to Pipedream with a Connected Account badge.
- 1Click '+ Add a step' and search for 'Slack'
- 2Select 'Send Message to a Channel'
- 3Click 'Connect Account' and follow the Slack OAuth flow
- 4Confirm 'chat:write' and 'chat:write.public' are included in the permission screen
- 5Click 'Allow' and return to Pipedream
Slack Step > Channel > Notification Text > Blocks
Configure the Slack message step
In the Slack step, select your target channel from the Channel dropdown — for example '#sales-pipeline' or '#daily-standup'. Set the 'Notification Text' field to something like 'Daily Pipeline Update — see below' (this appears in push notifications and desktop alerts). In the 'Blocks' field, reference the output of your format_message step using the expression picker: type '{{' and select 'steps.format_message.$return_value.blocks'. Leave 'Text' blank since you're using blocks. Toggle 'unfurl_links' off to prevent Slack from expanding any lead URLs in the message.
- 1Select your target Slack channel from the Channel dropdown
- 2Set Notification Text to 'Daily Pipeline Update — see message below'
- 3Click into the Blocks field and type '{{' to open the expression picker
- 4Navigate to steps.format_message.$return_value.blocks and select it
- 5Set unfurl_links to false
Workflow Canvas > Test Workflow button (top of canvas)
Test the full workflow end-to-end
Click 'Test Workflow' at the top of the canvas to run all steps in sequence using a simulated trigger event. Watch each step go green or red in order. If the Close steps succeed but the Slack step fails, the error message in the step panel will tell you whether it's a channel permission issue or a malformed blocks payload. Once all steps are green, click the Slack channel to confirm the message posted and that formatting looks correct on mobile and desktop. Fix any field alignment or text truncation issues in the format_message code step before deploying.
- 1Click 'Test Workflow' at the top of the canvas
- 2Watch each step's status indicator turn green sequentially
- 3Open your Slack channel and confirm the message rendered correctly
- 4Check the message on mobile Slack to confirm Block Kit renders cleanly
- 5Return to Pipedream and fix any formatting issues in the format_message step
Workflow Canvas > Deploy button (top-right)
Deploy the workflow
Click the blue 'Deploy' button in the top-right of the canvas. The yellow 'Draft' badge changes to green 'Active'. Pipedream will now execute this workflow automatically on your cron schedule. Verify the next scheduled run time shown in the trigger block matches your intention — for '0 8 * * 1-5' UTC, you should see the next weekday at 08:00 UTC listed. Set up a Pipedream error alert under Settings > Notifications so you get an email if the workflow fails silently on a given morning.
- 1Click the blue 'Deploy' button in the top-right corner
- 2Confirm the badge changes from yellow 'Draft' to green 'Active'
- 3Check the trigger block for the 'Next run' timestamp
- 4Go to Settings > Notifications and enable error email alerts
- 5Wait for the first scheduled run and confirm the Slack message arrives
Paste this into a single Node.js code step between your Close fetch steps and the Slack step. It handles pagination for pipelines over 200 deals, splits tasks into overdue vs. today buckets, formats currency correctly, and builds the full Block Kit payload in one pass. Reference it downstream in the Slack step as steps.build_digest.$return_value.blocks.
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 apiKey = steps.fetch_opportunities.$auth.api_key;
const authHeader = 'Basic ' + Buffer.from(apiKey + ':').toString('base64');
// Paginate Close opportunities if > 200 deals exist
let allOpps = [];
let skip = 0;
const limit = 200;
while (true) {
const res = await axios.get('https://api.close.com/api/v1/opportunity/', {
headers: { Authorization: authHeader },
params: {
status_type: 'active',
_limit: limit,
_skip: skip,
_fields: 'id,lead_name,value,status_label,user_name,close_date,updated',
},
});
const data = res.data?.data ?? [];
allOpps = allOpps.concat(data);
if (data.length < limit) break;
skip += limit;
}
// Pipeline totals
const pipelineTotal = allOpps.reduce((sum, o) => sum + (o.value || 0), 0) / 100;
const today = new Date();
today.setHours(0, 0, 0, 0);
const overdueDeals = allOpps.filter(o => o.close_date && new Date(o.close_date) < today);
// Group deals by rep
const byRep = {};
for (const opp of allOpps) {
const rep = opp.user_name || 'Unassigned';
if (!byRep[rep]) byRep[rep] = { count: 0, value: 0 };
byRep[rep].count++;
byRep[rep].value += (opp.value || 0) / 100;
}
// Split tasks
const rawTasks = steps.fetch_tasks.$return_value?.data ?? [];
const todayStr = today.toISOString().split('T')[0];
const overdueTasks = rawTasks.filter(t => t.due_date && t.due_date < todayStr);
const todayTasks = rawTasks.filter(t => t.due_date && t.due_date === todayStr);
const fmt = (n) => n.toLocaleString('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
// Build Block Kit payload
const blocks = [
{
type: 'header',
text: { type: 'plain_text', text: `📊 Daily Pipeline Update — ${today.toDateString()}` },
},
{ type: 'divider' },
{
type: 'section',
fields: [
{ type: 'mrkdwn', text: `*Total Open Pipeline*\n${fmt(pipelineTotal)}` },
{ type: 'mrkdwn', text: `*Active Deals*\n${allOpps.length}` },
{ type: 'mrkdwn', text: `*Overdue Deals*\n${overdueDeals.length}` },
{ type: 'mrkdwn', text: `*Tasks Due Today*\n${todayTasks.length}` },
],
},
{ type: 'divider' },
{
type: 'section',
text: { type: 'mrkdwn', text: '*Pipeline by Rep*' },
},
...Object.entries(byRep).map(([rep, data]) => ({
type: 'section',
text: {
type: 'mrkdwn',
text: `• *${rep}*: ${data.count} deals — ${fmt(data.value)}`,
},
})),
{ type: 'divider' },
{
type: 'section',
text: { type: 'mrkdwn', text: `*Overdue Tasks (${overdueTasks.length})*` },
},
...overdueTasks.slice(0, 10).map(t => ({
type: 'section',
text: {
type: 'mrkdwn',
text: `⚠️ ${t.type} — *${(t.lead_name || 'Unknown').slice(0, 40)}* | ${t.assigned_to || 'Unassigned'} | Due: ${t.due_date}`,
},
})),
{ type: 'divider' },
{
type: 'section',
text: { type: 'mrkdwn', text: `*Due Today (${todayTasks.length})*` },
},
...todayTasks.slice(0, 10).map(t => ({
type: 'section',
text: {
type: 'mrkdwn',
text: `📋 ${t.type} — *${(t.lead_name || 'Unknown').slice(0, 40)}* | ${t.assigned_to || 'Unassigned'}`,
},
})),
];
return { blocks, pipelineTotal, dealCount: allOpps.length };
},
});Scaling Beyond 200+ active opportunities in Close pipeline+ Records
If your volume exceeds 200+ active opportunities in Close pipeline records, apply these adjustments.
Use pagination for large pipelines
Close's API returns a maximum of 200 records per request. The pro tip code handles this with a while loop incrementing the _skip parameter until fewer than 200 records return. Without this, teams with 200+ active deals will get incomplete pipeline totals in their digest.
Cap Slack message rows to avoid hitting Slack's block limit
Slack Block Kit payloads are capped at 50 blocks per message. If you have many overdue tasks or deals, use .slice(0, 10) on each list before building blocks — as shown in the pro tip code. For larger lists, post a truncated summary and include a direct link to the Close report.
Watch Pipedream execution time for large datasets
Pipedream times out Node.js steps after 60 seconds on the free tier and 300 seconds on paid plans. Paginating through 1,000+ deals while building Block Kit can approach this limit. If you're seeing timeout errors, split the data fetch and the formatting into separate steps to distribute the execution time.
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 any developer capacity at all. The scheduled trigger is rock-solid, the Node.js step handles Close's pagination quirk in 10 lines, and you can format Block Kit payloads exactly how you want without fighting a visual builder. The one scenario where you'd pick something else: if the person maintaining this workflow will never touch code and needs to hand it off to a non-technical manager — in that case, Zapier's simpler step model is easier to explain.
Pipedream's free tier gives you 10,000 credits/month. This workflow uses 4 steps per run. Pipedream charges 1 credit per step execution, so each morning run costs 4 credits. At 22 weekday runs/month, that's 88 credits/month — well under the free limit. You'd need to run this workflow 28 times per day before approaching the free tier ceiling. Make's free tier also covers this at zero cost, but Make charges per operation and counts each API call separately, so a paginated Close fetch (5 requests) costs 5 operations vs. Pipedream's 1 step credit. At current pricing, Pipedream is cheaper for this use case by roughly $0 — both are free at this volume.
Make has a better visual debugger for inspecting intermediate data — if you're building this for the first time and the Close response confuses you, Make's inspector shows each field in a cleaner UI than Pipedream's JSON panel. Zapier's pre-built Close and Slack actions are faster to configure for simple setups, but Zapier can't handle Close API pagination without a paid Code step, which adds cost. n8n runs this entirely on your own infrastructure if data privacy is a concern — Close customer data never leaves your server. Power Automate is the wrong tool here unless your team is already deep in the Microsoft 365 ecosystem; its Slack and Close connectors are thin and the scheduler is less predictable. Pipedream wins because pagination, formatting, and posting are all one workflow with no plugin dependencies and a free execution budget that fits this use case exactly.
Three things you'll hit after setup. First, Close's 'value' field comes back in cents — a $25,000 deal returns as 2500000. Missing this makes your pipeline total look like you're running a hedge fund. Divide by 100 before any display. Second, the Close Tasks API returns due_date as a date string in 'YYYY-MM-DD' format, but the Opportunities API returns close_date in the same format — both compare cleanly with JavaScript's string comparison, which makes overdue detection simple, but only if you don't accidentally compare against a JavaScript Date object with a timezone offset attached. Stick to string comparison: 'due_date < todayStr' where todayStr is today's ISO date string. Third, Slack will silently drop your message if the blocks array exceeds 50 items. No error, no warning — the post just doesn't happen. Always cap list lengths with .slice() before building the payload.
Ideas for what to build next
- →Add per-rep Slack DMs alongside the channel post — Extend the workflow with a Slack 'Send Direct Message' step that loops through the byRep data and sends each rep only their own deals and tasks — reduces noise for reps who don't need to see the full team view.
- →Post a weekly performance summary on Fridays — Add a second scheduled workflow with a Friday-only cron expression that pulls Close's won/lost deals from the past 7 days and posts a win/loss ratio and revenue closed to the same Slack channel.
- →Trigger a real-time alert when a deal goes overdue — Build a separate Pipedream workflow using Close's webhook for opportunity updates — fire a Slack alert the moment a deal's close date passes without a status change, rather than waiting for the morning digest.
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