

How to Send Daily Sales Digests from Zoho CRM to Slack with Pipedream
A scheduled Pipedream workflow queries Zoho CRM for daily deal and pipeline data, formats a summary, and posts it 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 who want a no-touch daily Slack report built on real Zoho CRM pipeline data without paying for a BI tool.
Not ideal for
Teams that need live deal alerts the moment a record changes — use a webhook-triggered workflow instead.
Sync type
scheduledUse case type
reportingReal-World Example
A 12-person SaaS sales team runs this every weekday at 8 AM to post yesterday's closed deals, total pipeline value, and stage breakdown to #sales-digest in Slack. Before this workflow, the sales manager pulled a Zoho CRM report manually each morning and copy-pasted numbers into Slack — a 15-minute task that got skipped on busy days. Now the digest arrives automatically with zero manual effort.
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 | ||
| Deal Name | Deal_Name | |
| Deal Stage | Stage | |
| Amount | Amount | |
| Closing Date | Closing_Date | |
| Created Time | Created_Time | |
4 optional fields▸ show
| Account Name | Account_Name |
| Owner | Owner |
| Probability | Probability |
| Lead Source | Lead_Source |
Step-by-Step Setup
pipedream.com > Workflows > New Workflow
Create a new Pipedream workflow
Go to pipedream.com and click 'New Workflow' in the top-right corner of your dashboard. You'll land on a blank canvas with a trigger slot at the top and a prompt to add steps below. Give the workflow a name like 'Zoho CRM Daily Sales Digest' using the pencil icon at the top — this matters when you have multiple workflows and need to find this one fast.
- 1Click 'New Workflow' in the top-right of the Pipedream dashboard
- 2Click the pencil icon next to 'My Workflow' and rename it to 'Zoho CRM Daily Sales Digest'
- 3Click 'Save' to confirm the name
Workflow Canvas > Add a Trigger > Schedule > Daily
Set a daily schedule trigger
Click 'Add a trigger' and search for 'Schedule'. Select 'Schedule' from the Pipedream-native sources list — this is built into Pipedream, no app connection needed. Choose 'Daily' from the interval options and set the time to 8:00 AM in your team's local timezone. Pipedream runs triggers in UTC by default, so convert your local time carefully — if your team is in US Eastern, 8 AM ET is 13:00 UTC.
- 1Click 'Add a trigger' on the workflow canvas
- 2Type 'Schedule' in the search box and select the Pipedream-native Schedule source
- 3Select 'Daily' as the interval
- 4Set the time field to your target UTC equivalent of 8:00 AM local time
- 5Click 'Save and continue'
Workflow Canvas > + Add Step > Zoho CRM > Run API Request > Connect Account
Connect your Zoho CRM account
Click '+ Add step' below the trigger and search for 'Zoho CRM'. Select the 'Run API Request' action — this gives you the most flexibility to build a custom COQL query rather than being limited to preset actions. In the step panel, click 'Connect Account' and follow the OAuth flow. You'll be redirected to Zoho's login page, asked to approve scopes, and returned to Pipedream with a green connected badge.
- 1Click '+ Add step' below the Schedule trigger
- 2Search for 'Zoho CRM' and select it from the app list
- 3Choose the 'Run API Request' action
- 4Click 'Connect Account' in the step configuration panel
- 5Complete the Zoho OAuth flow and return to Pipedream
Workflow Canvas > Zoho CRM Step > Run API Request > Method + URL + Body
Query Zoho CRM for today's deal data
In the 'Run API Request' step, set the Method to GET and the URL to the Zoho CRM COQL endpoint: https://www.zohoapis.com/crm/v3/coql. Switch to the 'Body' tab and set Content-Type to application/json. You'll write a COQL SELECT query that pulls deals closed today, total pipeline value by stage, and count of new deals opened in the last 24 hours. The query runs against Zoho's search API and returns a paginated JSON array of deal records.
- 1Set Method to POST (COQL queries use POST, not GET)
- 2Set URL to https://www.zohoapis.com/crm/v3/coql
- 3Click the 'Body' tab and set type to 'Raw JSON'
- 4Paste your COQL query JSON into the body field
- 5Click 'Test' to confirm the response returns deal records
Workflow Canvas > + Add Step > Run Node.js code
Add a Node.js step to process the deal data
Click '+ Add step' and select 'Run Node.js code'. This is where you transform the raw Zoho API response into a structured digest. You'll parse the deal array, calculate totals (closed revenue, average deal size, pipeline by stage), and build the data object that feeds the Slack message. Reference the previous step's output using steps.zoho_crm.data — Pipedream passes data between steps automatically via the steps object.
- 1Click '+ Add step' below the Zoho CRM step
- 2Select 'Run Node.js code' from the step type options
- 3Paste your transformation code into the code editor
- 4Click 'Test' to run the step and see the output in the results panel
Workflow Canvas > + Add Step > Slack > Send a Message > Connect Account
Connect your Slack account
Click '+ Add step' and search for 'Slack'. Choose the 'Send a Message' action. Click 'Connect Account' and complete the Slack OAuth flow — you'll be asked which workspace to authorize and which scopes to grant. Pipedream needs the chat:write scope at minimum. If you want to post to private channels, the bot also needs to be invited to that channel manually in Slack before the workflow runs.
- 1Click '+ Add step' below the Node.js code step
- 2Search for 'Slack' and select it from the app list
- 3Choose 'Send a Message' as the action
- 4Click 'Connect Account' and complete the Slack OAuth flow
- 5Select your workspace and approve the requested scopes
Workflow Canvas > Slack Step > Send a Message > Channel + Blocks
Configure the Slack message with Block Kit
In the Slack step, set the Channel field to your target channel name (e.g., #sales-digest). Leave the Text field blank and use the Blocks field instead — Slack's Block Kit gives you headers, dividers, and formatted sections that make the digest readable. Paste your Block Kit JSON into the Blocks field, referencing the Node.js step output using double-curly Pipedream template syntax like {{steps.nodejs.$return_value.totalClosedValue}}. Test the step to preview the message layout.
- 1Set the Channel field to #sales-digest (or your channel name)
- 2Leave the Text field blank
- 3Click the Blocks field and paste your Block Kit JSON
- 4Reference previous step data using {{steps.nodejs.$return_value.fieldName}} syntax
- 5Click 'Test' to send a test message to Slack and verify formatting
Workflow Canvas > + Add Step > Run Node.js code (Error Handler)
Add error handling with a fallback notification
Click '+ Add step' and select 'Run Node.js code' again. Use this step to catch errors from earlier steps and send a plain-text fallback Slack message if the Zoho query or data processing failed. Check steps.zoho_crm.$return_value for null or empty data arrays before proceeding. This prevents silent failures where the workflow runs but posts nothing — which is worse than a visible error.
- 1Click '+ Add step' below the Slack message step
- 2Select 'Run Node.js code'
- 3Write a conditional check for empty or null data from the Zoho step
- 4If data is missing, use $.send.http to call Slack's API directly with an error alert
- 5Click 'Test' to confirm the fallback logic works
Workflow Canvas > Run (top toolbar)
Test the full workflow end-to-end
Click 'Run' at the top of the workflow canvas to trigger a manual test run. Watch each step's status indicator — green checkmark means it passed, red X means it failed and you need to check that step's logs. Open Slack and confirm the digest message appeared in the correct channel with correct data. Check that deal values, stage names, and dates match what you see in Zoho CRM's own reports.
- 1Click 'Run' in the top toolbar of the workflow canvas
- 2Watch each step's status indicator update in real time
- 3Click any step with a red X to open its error log
- 4Switch to Slack and verify the digest message appears in #sales-digest
- 5Cross-check one deal value against Zoho CRM's built-in reports to confirm accuracy
Workflow Canvas > Deploy (top-right button)
Deploy and enable the workflow
Once the test run is clean, click 'Deploy' in the top-right corner of the workflow canvas. Pipedream changes the workflow state from 'Development' to 'Active'. The Schedule trigger will now fire automatically at your configured time each day. Check back the next morning to confirm the first scheduled run succeeded — look at the workflow's event history tab to see the run log and confirm all steps passed.
- 1Click 'Deploy' in the top-right corner
- 2Confirm the status badge changes from 'Development' to 'Active'
- 3Navigate to the 'Events' tab on the workflow page
- 4The following morning, check the Events tab to confirm the scheduled run completed
- 5Open Slack to verify the digest posted at the correct time
This Node.js step fetches Zoho CRM deal data via COQL, calculates digest metrics, and returns a structured object ready for the Slack Block Kit message. Paste this into the 'Run Node.js code' step that sits between your Zoho CRM API step and your Slack step.
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 zohoData = steps.zoho_crm.$return_value;
if (!zohoData || !zohoData.data || zohoData.data.length === 0) {
console.log('No deal data returned from Zoho CRM. Sending fallback alert.');
return {
hasData: false,
message: '⚠️ No deal data returned from Zoho CRM today. Check the API step logs.',
};
}
const deals = zohoData.data;
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD in UTC
// Closed Won deals with today's closing date
const closedToday = deals.filter(
(d) => d.Stage === 'Closed Won' && d.Closing_Date === today
);
// New deals created in last 24 hours
const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
const newDeals = deals.filter((d) => new Date(d.Created_Time) >= oneDayAgo);
// Total closed revenue today
const totalClosedRevenue = closedToday.reduce(
(sum, d) => sum + (parseFloat(d.Amount) || 0),
0
);
// Weighted pipeline across all open deals
const weightedPipeline = deals
.filter((d) => d.Stage !== 'Closed Won' && d.Stage !== 'Closed Lost')
.reduce(
(sum, d) =>
sum + ((parseFloat(d.Amount) || 0) * (parseFloat(d.Probability) || 0)) / 100,
0
);
// Stage breakdown
const stageMap = {};
deals.forEach((d) => {
if (!stageMap[d.Stage]) stageMap[d.Stage] = { count: 0, total: 0 };
stageMap[d.Stage].count += 1;
stageMap[d.Stage].total += parseFloat(d.Amount) || 0;
});
const stageBreakdown = Object.entries(stageMap)
.map(([stage, { count, total }]) =>
`${stage}: ${count} deal${count !== 1 ? 's' : ''} ($${total.toLocaleString()})`
)
.join(' | ');
// Top deal by amount
const topDeal = [...closedToday].sort((a, b) => b.Amount - a.Amount)[0];
const topDealText = topDeal
? `${topDeal.Deal_Name} — $${parseFloat(topDeal.Amount).toLocaleString()} (${topDeal.Owner?.name || 'Unknown'})`
: 'No deals closed today';
// Format date for display
const digestDate = new Date().toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
});
return {
hasData: true,
digestDate,
totalClosedRevenue: `$${totalClosedRevenue.toLocaleString()}`,
closedDealCount: closedToday.length,
newDealsOpened: newDeals.length,
topDeal: topDealText,
stageBreakdown,
weightedPipeline: `$${Math.round(weightedPipeline).toLocaleString()}`,
};
},
});Scaling Beyond 200+ deals matching your daily COQL query+ Records
If your volume exceeds 200+ deals matching your daily COQL query records, apply these adjustments.
Paginate COQL results
Zoho's COQL API returns a maximum of 200 records per request. Check the info.more_records boolean in the response — if true, re-run the query with OFFSET 200, OFFSET 400, etc. in a while loop inside your Node.js step until more_records is false, then merge all pages before calculating totals.
Cache results mid-run with $.flow.suspend
For very large deal volumes requiring 5+ paginated requests, Pipedream's execution timeout (30 seconds on the free tier, up to 300 seconds on paid plans) can cut the run short. Use Pipedream's built-in $.flow.suspend and rerun pattern, or break the aggregation into two separate scheduled workflows chained via a datastore key.
Use Zoho CRM's built-in reports API for pre-aggregated data
If your deal volume is consistently over 500/day, skip raw deal queries entirely and call Zoho's Reports API endpoint instead — it returns pre-aggregated totals per stage, which is a single API call regardless of deal count. The endpoint is GET /crm/v2/analytics/{report_id} and returns summary data directly.
Watch your Zoho API daily quota
Pagination loops burn through API calls fast — 5 pages of 200 records each costs 5 API calls per digest run. On a Standard plan with 500 daily calls, that leaves only 100 calls for other integrations. Monitor usage in Zoho CRM under Setup > Developer Space > APIs > API Dashboard.
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 someone comfortable reading JavaScript, you want full control over how deal data is formatted and filtered, and you don't want to pay for a separate BI or reporting tool. Pipedream's Node.js code steps mean you can calculate weighted pipeline, filter by owner region, and format currency in a single 40-line function — no formula language to learn, no UI drag-and-drop limitations. The one case where you'd pick something else: if nobody on the team can read a code step at all, Make's scenario-based approach is easier to hand off to a non-technical ops person.
Pipedream's credit model for scheduled workflows is predictable. A daily digest workflow running once per day uses roughly 5-8 credits per run depending on step count (each step costs 1 credit). At 365 runs per year, that's around 2,000-3,000 credits annually. Pipedream's free tier gives you 10,000 credits per month, so a single daily digest is effectively free. The Basic plan ($29/month) covers up to 100,000 credits — enough for dozens of workflows. By comparison, Zapier charges $19.99/month for 750 tasks, and each step in a Zap counts as a task, meaning a 6-step digest workflow eats 6 tasks per run. At daily frequency, that's 180 tasks/month — well within Zapier's paid tiers, but you hit the ceiling faster as you add more automations.
Make's scenario builder is easier for building the stage-breakdown table visually — you can see the data structure at each node without running test code, which speeds up debugging for non-developers. Zapier has a pre-built 'Digest' action that batches events before sending, which is useful if you want to accumulate deal events throughout the day rather than query at a fixed time. n8n gives you the same Node.js flexibility as Pipedream but is self-hosted, which matters if your Zoho CRM data can't leave your infrastructure for compliance reasons. Power Automate has native Dataverse connectors but Zoho CRM support is thin — you'd be routing through a third-party connector. Pipedream is still the right call here because the combination of a native Zoho CRM app, native Slack app, and unrestricted Node.js in between gives you the cleanest pipeline with no data transformation workarounds.
Three things you'll hit after the first week: First, Zoho's COQL date filtering uses the deal's Closing_Date field, which stores dates in the account's configured timezone — if your Zoho org is set to IST but your Pipedream schedule runs at midnight UTC, your 'today' query catches records from two different calendar days depending on timezone math. Test this explicitly. Second, Slack's Block Kit message limit is 50 blocks per message — if your stage breakdown generates more than ~20 stages, you'll exceed this and get a silent truncation. Paginate across two messages or collapse small stages into an 'Other' bucket. Third, Zoho's API occasionally returns deal Owner as a nested object with an id field rather than a name — especially on older records. Always extract Owner.name with a null-safe fallback like Owner?.name ?? 'Unassigned' or you'll see 'undefined' in the digest for those deals.
Ideas for what to build next
- →Add a Weekly Pipeline Review Digest — Build a second workflow on a Monday morning schedule that queries 7-day deal movement, win rate, and average deal size — post it to #sales-leadership as a weekly summary alongside the daily digest.
- →Trigger Deal-Level Alerts in Real Time — Complement the digest with a webhook-triggered workflow that fires instantly when a Zoho deal moves to 'Closed Won' or 'Proposal Sent', posting a one-deal alert to Slack so reps don't wait until morning for big news.
- →Route Digest to Multiple Channels by Region — If your team covers multiple regions, add conditional logic in the Node.js step to filter deals by Owner territory and post separate digests to #sales-emea and #sales-us with their respective numbers.
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