Intermediate~15 min setupCommunication & CRMVerified April 2026
Slack logo
Zoho CRM logo

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

scheduled

Use case type

reporting

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

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

Zoho CRM account with API access enabled — requires at least a Standard plan. Enable API usage in Zoho CRM under Setup > Developer Space > APIs.
Zoho OAuth scopes: ZohoCRM.modules.deals.READ and ZohoCRM.settings.fields.READ — approve these during the Pipedream OAuth flow.
Slack workspace with permission to add apps — you need the 'Manage apps' permission in Slack, or ask your workspace admin to approve the Pipedream app.
Slack bot invited to the target channel — for private channels, type /invite @Pipedream in Slack before the workflow runs.
Pipedream account on the Basic plan or higher — the free tier allows 100 workflow invocations per day, which is enough for daily digests but not if you run tests heavily.

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Deal NameDeal_Name
Deal StageStage
AmountAmount
Closing DateClosing_Date
Created TimeCreated_Time
4 optional fields▸ show
Account NameAccount_Name
OwnerOwner
ProbabilityProbability
Lead SourceLead_Source

Step-by-Step Setup

1

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.

  1. 1Click 'New Workflow' in the top-right of the Pipedream dashboard
  2. 2Click the pencil icon next to 'My Workflow' and rename it to 'Zoho CRM Daily Sales Digest'
  3. 3Click 'Save' to confirm the name
What you should see: You should see a blank workflow canvas with a trigger slot labeled 'Add a trigger' and no steps added yet.
2

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.

  1. 1Click 'Add a trigger' on the workflow canvas
  2. 2Type 'Schedule' in the search box and select the Pipedream-native Schedule source
  3. 3Select 'Daily' as the interval
  4. 4Set the time field to your target UTC equivalent of 8:00 AM local time
  5. 5Click 'Save and continue'
What you should see: The trigger slot shows 'Schedule' with your configured time. You'll see a 'Next run' timestamp in the trigger panel confirming when it will first fire.
Common mistake — Pipedream schedule times are in UTC. If you enter 8:00 AM thinking it's local time but your team is in GMT-5, the digest posts at 3 AM. Double-check by looking at the 'Next run' timestamp and converting it back to local time before saving.
Pipedream
+
click +
search apps
Slack
SL
Slack
Set a daily schedule trigger
Slack
SL
module added
3

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.

  1. 1Click '+ Add step' below the Schedule trigger
  2. 2Search for 'Zoho CRM' and select it from the app list
  3. 3Choose the 'Run API Request' action
  4. 4Click 'Connect Account' in the step configuration panel
  5. 5Complete the Zoho OAuth flow and return to Pipedream
What you should see: The step panel shows a green connected badge with your Zoho CRM account email. The 'Run API Request' action fields appear below.
Common mistake — Zoho CRM has region-specific API endpoints: api.zoho.com for US, api.zoho.eu for EU, api.zoho.in for India. If your account was created in the EU, the default US endpoint will return a 401. Check your Zoho account region in Zoho's admin console before building the query.
Pipedream settings
Connection
Choose a connection…Add
click Add
Slack
Log in to authorize
Authorize Pipedream
popup window
Connected
green checkmark
4

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.

  1. 1Set Method to POST (COQL queries use POST, not GET)
  2. 2Set URL to https://www.zohoapis.com/crm/v3/coql
  3. 3Click the 'Body' tab and set type to 'Raw JSON'
  4. 4Paste your COQL query JSON into the body field
  5. 5Click 'Test' to confirm the response returns deal records
What you should see: The test response panel shows a JSON object with a 'data' array containing deal records and a 'info' object with count and pagination details.
Common mistake — COQL uses POST, not GET — this catches most people. Also, COQL has a hard limit of 200 records per response. If your team closes more than 200 deals per day, you need pagination logic in the next code step.
5

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.

  1. 1Click '+ Add step' below the Zoho CRM step
  2. 2Select 'Run Node.js code' from the step type options
  3. 3Paste your transformation code into the code editor
  4. 4Click 'Test' to run the step and see the output in the results panel
What you should see: The results panel shows a structured JSON object with fields like totalClosedValue, dealCount, stageBreakdown, and topDeal — ready to be passed to the Slack step.
6

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.

  1. 1Click '+ Add step' below the Node.js code step
  2. 2Search for 'Slack' and select it from the app list
  3. 3Choose 'Send a Message' as the action
  4. 4Click 'Connect Account' and complete the Slack OAuth flow
  5. 5Select your workspace and approve the requested scopes
What you should see: The step shows a green connected badge with your Slack workspace name. The Channel, Text, and Blocks fields appear below for configuration.
Common mistake — If you post to a private Slack channel, the workflow will fail with 'channel_not_found' even if the bot is authorized. You must manually type /invite @YourBotName in that Slack channel before the workflow runs — Pipedream's OAuth alone doesn't grant private channel access.
7

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.

  1. 1Set the Channel field to #sales-digest (or your channel name)
  2. 2Leave the Text field blank
  3. 3Click the Blocks field and paste your Block Kit JSON
  4. 4Reference previous step data using {{steps.nodejs.$return_value.fieldName}} syntax
  5. 5Click 'Test' to send a test message to Slack and verify formatting
What you should see: A formatted test message appears in your Slack channel with headers, deal counts, revenue totals, and a stage breakdown table visible.
Common mistake — Slack's Blocks field expects a JSON array, not an object. Wrapping your blocks in an object like {"blocks": [...]} instead of just [...] causes a 'invalid_blocks' error. Paste only the array.
8

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.

  1. 1Click '+ Add step' below the Slack message step
  2. 2Select 'Run Node.js code'
  3. 3Write a conditional check for empty or null data from the Zoho step
  4. 4If data is missing, use $.send.http to call Slack's API directly with an error alert
  5. 5Click 'Test' to confirm the fallback logic works
What you should see: When the Zoho data is empty or malformed, a plain-text Slack message like '⚠️ Sales digest failed to load — check Pipedream logs' posts to the channel instead of silence.
9

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.

  1. 1Click 'Run' in the top toolbar of the workflow canvas
  2. 2Watch each step's status indicator update in real time
  3. 3Click any step with a red X to open its error log
  4. 4Switch to Slack and verify the digest message appears in #sales-digest
  5. 5Cross-check one deal value against Zoho CRM's built-in reports to confirm accuracy
What you should see: All steps show green checkmarks. The Slack channel shows a formatted digest with today's date, deal count, total revenue, and stage breakdown.
Common mistake — If you run the workflow multiple times during testing, you'll post multiple digest messages to Slack. Temporarily redirect to a test channel like #bot-testing during QA — easier than deleting duplicate messages from the real channel.
Pipedream
▶ Deploy & test
executed
Slack
Zoho CRM
Zoho CRM
🔔 notification
received
10

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.

  1. 1Click 'Deploy' in the top-right corner
  2. 2Confirm the status badge changes from 'Development' to 'Active'
  3. 3Navigate to the 'Events' tab on the workflow page
  4. 4The following morning, check the Events tab to confirm the scheduled run completed
  5. 5Open Slack to verify the digest posted at the correct time
What you should see: The workflow status shows 'Active'. The Events tab shows a successful scheduled run entry the next morning, and the Slack channel has the digest posted at the time you configured.

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.

1

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.

2

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.

3

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.

4

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

VerdictWhy n8n for this workflow

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.

Cost

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.

Tradeoffs

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 DigestBuild 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 TimeComplement 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 RegionIf 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

Was this guide helpful?
Slack + Zoho CRM overviewPipedream profile →