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

How to Send Zoho CRM Deal Stage Updates to Slack with Pipedream

Fires a Slack message to your team channel the moment a deal moves to a new pipeline stage in Zoho CRM, using Pipedream's webhook trigger and a Node.js formatting step.

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 instant Slack notifications when deals change stages — with custom message formatting they control in code.

Not ideal for

Teams that need zero-code setup; use Zapier instead if nobody on the team is comfortable reading a few lines of Node.js.

Sync type

real-time

Use case type

notification

Real-World Example

💡

A 12-person SaaS sales team fires a message into #deals-updates every time a Zoho CRM deal moves from 'Proposal Sent' to 'Negotiation'. Before this, reps checked Zoho manually between calls and often found out about stage changes hours late. Now the whole team sees wins in real time and the manager can jump in immediately when a deal stalls at 'Decision Maker Engaged' for more than a day.

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 on Standard plan or above — required for webhook/API access to the Deals module
Zoho CRM user with read access to the Deals module and permission to authorize OAuth apps
Slack workspace where you have permission to add apps and post to the target channel
Pipedream account — free tier works for low volume (under ~3,000 deal updates/month)
Slack channel already created (e.g. #deals-updates) and the Pipedream bot invited if the channel is private

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Deal NameDeal_Name
StageStage
Deal OwnerOwner.name
5 optional fields▸ show
AmountAmount
Account NameAccount_Name
Closing DateClosing_Date
Modified TimeModified_Time
Lead SourceLead_Source

Step-by-Step Setup

1

pipedream.com > Workflows > New Workflow

Create a new Pipedream workflow

Go to pipedream.com and sign in. Click the blue 'New Workflow' button in the top-right corner of the dashboard. You'll land on the workflow canvas with an empty trigger slot at the top. Give the workflow a name — something like 'Zoho Deal Stage → Slack' — by clicking the pencil icon next to the default title.

  1. 1Sign in at pipedream.com
  2. 2Click the blue 'New Workflow' button in the top right
  3. 3Click the pencil icon next to the default workflow title
  4. 4Type a name like 'Zoho Deal Stage → Slack' and press Enter
What you should see: You see an empty workflow canvas with a single grey trigger block labeled 'Add Trigger' at the top.
2

Workflow Canvas > Add Trigger > Zoho CRM > New Module Entry

Add the Zoho CRM trigger

Click the 'Add Trigger' block on the canvas. Search for 'Zoho CRM' in the app search box. Select 'Zoho CRM' from the results, then choose the 'New Module Entry' event — this fires whenever a record is created or updated in any Zoho CRM module. You'll set the module to 'Deals' in the next configuration panel.

  1. 1Click the grey 'Add Trigger' block
  2. 2Type 'Zoho CRM' in the search box
  3. 3Select 'Zoho CRM' from the app list
  4. 4Choose 'New Module Entry' as the trigger event
  5. 5Set the 'Module' dropdown to 'Deals'
What you should see: The trigger block shows 'Zoho CRM — New Module Entry' with a grey 'Connect Account' button visible below the module selector.
Common mistake — Zoho CRM does not expose a native 'stage changed' webhook. The 'New Module Entry' trigger fires on any deal update. You'll filter for stage changes in a code step — skipping this filter means your Slack channel gets spammed on every field edit.
Pipedream
+
click +
search apps
Slack
SL
Slack
Add the Zoho CRM trigger
Slack
SL
module added
3

Trigger Block > Connect Account > OAuth Popup > Zoho Sign In

Connect your Zoho CRM account

Click 'Connect Account' under the trigger configuration. Pipedream opens an OAuth popup pointing to Zoho's login page. Sign in with the Zoho account that has CRM access. After authorizing, the popup closes and Pipedream confirms the connection. Make sure the account you connect has at minimum read access to the Deals module.

  1. 1Click the 'Connect Account' button in the trigger block
  2. 2Sign in to Zoho in the OAuth popup that appears
  3. 3Click 'Accept' to grant Pipedream access to your Zoho CRM data
  4. 4Confirm the popup closes and the account name appears in the trigger block
What you should see: The trigger block shows your Zoho account email address and a green connected indicator. The 'Connect Account' button is replaced by your account name.
Common mistake — If your Zoho org uses IP allowlisting, the OAuth flow will succeed but API calls will fail silently. Add Pipedream's outbound IP ranges to your Zoho allowlist before testing.
Pipedream settings
Connection
Choose a connection…Add
click Add
Slack
Log in to authorize
Authorize Pipedream
popup window
Connected
green checkmark
4

Trigger Block > Test Trigger > Event Inspector

Test the trigger and capture a sample event

Click 'Test Trigger' at the bottom of the trigger block. Pipedream starts listening for incoming events. Go to Zoho CRM, open any deal, and manually change its stage, then save. Return to Pipedream — within 30–60 seconds you should see a raw event appear in the trigger block's event inspector. Click the event to expand it and verify the 'Stage' field is present in the payload.

  1. 1Click 'Test Trigger' in the trigger block
  2. 2Switch to Zoho CRM in another tab
  3. 3Open any deal and change its Stage field
  4. 4Save the deal and return to Pipedream
  5. 5Click the incoming event in the event inspector to expand the payload
What you should see: You see a JSON payload in the event inspector with fields including Deal_Name, Stage, Amount, Owner, and Account_Name visible at the top level.
Common mistake — If no event arrives after 90 seconds, check that your Zoho CRM plan includes webhook notifications — Zoho Standard plan and above supports this. The free plan does not fire outbound webhooks.
Pipedream
▶ Deploy & test
executed
Slack
Zoho CRM
Zoho CRM
🔔 notification
received
5

Workflow Canvas > + > Run Node.js Code

Add a Node.js code step to filter stage changes

Click the '+' button below the trigger to add a step. Select 'Run Node.js code'. This step will check whether the deal's stage actually changed — Zoho sends the full deal record on every update, not just a diff. You need to compare the current stage value against a list of stages you care about, and exit early if this isn't a stage-change event worth reporting.

  1. 1Click the '+' icon below the trigger block
  2. 2Select 'Run Node.js code' from the step options
  3. 3Rename the step to 'Filter Stage Change' by clicking the step title
What you should see: A Node.js code editor opens in the step block with a default async function template and access to the 'steps' object containing your trigger payload.
Common mistake — Filters are the most common place setups break. Double-check the field name and value exactly match what your app sends — a single capital letter difference will block everything.

Paste this into the Node.js code step (Step 5 on the canvas). It filters for watched stages, formats the Slack message with emoji and deal details, and exits early without error if the stage isn't one you care about. Update WATCHED_STAGES to match your exact Zoho pipeline stage names.

JavaScript — Code Stepexport default defineComponent({
▸ Show code
export default defineComponent({
  async run({ steps, $ }) {
    // Update these to match your exact Zoho CRM pipeline stage names

... expand to see full code

export default defineComponent({
  async run({ steps, $ }) {
    // Update these to match your exact Zoho CRM pipeline stage names
    const WATCHED_STAGES = [
      'Qualification',
      'Needs Analysis',
      'Value Proposition',
      'Proposal/Price Quote',
      'Negotiation/Review',
      'Closed Won',
      'Closed Lost',
    ];

    const deal = steps.trigger.event;

    const currentStage = deal?.Stage;
    const dealName = deal?.Deal_Name || 'Unnamed Deal';
    const ownerName = deal?.Owner?.name || 'Unknown Owner';
    const amount = deal?.Amount
      ? `$${Number(deal.Amount).toLocaleString('en-US')}`
      : 'No amount set';
    const accountName = deal?.Account_Name || 'No account';
    const closingDate = deal?.Closing_Date
      ? new Date(deal.Closing_Date).toLocaleDateString('en-US', {
          month: 'short', day: 'numeric', year: 'numeric',
        })
      : 'No close date';

    // Exit early if this stage isn't in our watch list
    if (!currentStage || !WATCHED_STAGES.includes(currentStage)) {
      $.flow.exit(`Stage '${currentStage}' is not in WATCHED_STAGES — skipping notification.`);
    }

    // Choose emoji based on stage
    const stageEmoji = currentStage === 'Closed Won'
      ? '🎉'
      : currentStage === 'Closed Lost'
      ? '❌'
      : '🔄';

    // Build the Slack message
    const slackMessage = [
      `${stageEmoji} *Deal Stage Update*`,
      `*${dealName}* → ${currentStage}`,
      `💰 ${amount} | 🏢 ${accountName}`,
      `👤 Owner: ${ownerName} | 📅 Close: ${closingDate}`,
    ].join('\n');

    return {
      dealName,
      stage: currentStage,
      owner: ownerName,
      amount,
      accountName,
      closingDate,
      slackMessage,
    };
  },
});
Slack
SL
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Zoho CRM
ZO
notified
6

Node.js Code Step > Editor

Write the stage filter and message builder logic

Paste the code from the Pro Tip section into the Node.js editor. This code reads the deal's current Stage from the trigger payload, checks whether it's a stage you want to notify on, formats a Slack message with deal name, owner, amount, and stage, and exports it for the next step. If the stage isn't in your watch list, it calls $.flow.exit() to stop the workflow without counting as a failed run.

  1. 1Click inside the code editor in the step block
  2. 2Select all existing code and delete it
  3. 3Paste the code from the Pro Tip section below
  4. 4Update the WATCHED_STAGES array to match your actual Zoho pipeline stage names
  5. 5Click 'Test' to run the step against your sample event
What you should see: The step output panel shows a formatted object with fields: dealName, stage, owner, amount, accountName, and slackMessage — all populated from your sample deal data.
Common mistake — Stage names in Zoho CRM are case-sensitive. 'Negotiation' and 'negotiation' are different values. Copy stage names directly from Zoho's pipeline settings to avoid silent mismatches.
7

Workflow Canvas > + > Slack > Send a Message

Add the Slack step

Click '+' below the code step and search for 'Slack'. Select the 'Send a Message' action. Click 'Connect Account' and authenticate with your Slack workspace via OAuth. Pipedream will request the chat:write scope — this is the minimum needed to post messages. After connecting, select the destination channel from the dropdown.

  1. 1Click the '+' icon below the filter code step
  2. 2Search for 'Slack' and select it
  3. 3Choose 'Send a Message' as the action
  4. 4Click 'Connect Account' and authorize Pipedream in the Slack OAuth popup
  5. 5Select your target channel (e.g. #deals-updates) from the Channel dropdown
What you should see: The Slack step shows your workspace name, the selected channel, and an empty 'Text' field waiting for your message content.
Common mistake — If you pick a private Slack channel, you must manually invite the Pipedream bot to that channel first. The bot will not appear in the member list automatically after OAuth.
8

Slack Step > Text Field > Variable Picker > steps.filter_stage_change.slackMessage

Map the message content from the code step

In the Slack step's 'Text' field, click the variable picker (the lightning bolt icon) and navigate to the output of your Node.js code step. Select the 'slackMessage' property — this contains the fully formatted string your code built. You can also enable 'Blocks' for richer formatting, but plain text with the formatted string is enough for most teams.

  1. 1Click inside the 'Text' field in the Slack step
  2. 2Click the lightning bolt icon to open the variable picker
  3. 3Expand 'steps' > your Node.js step name
  4. 4Click 'slackMessage' to insert it as the message body
What you should see: The Text field shows a token like {{steps.filter_stage_change.$return_value.slackMessage}} and a preview of your formatted message appears below the field.
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.

Paste this into the Node.js code step (Step 5 on the canvas). It filters for watched stages, formats the Slack message with emoji and deal details, and exits early without error if the stage isn't one you care about. Update WATCHED_STAGES to match your exact Zoho pipeline stage names.

JavaScript — Code Stepexport default defineComponent({
▸ Show code
export default defineComponent({
  async run({ steps, $ }) {
    // Update these to match your exact Zoho CRM pipeline stage names

... expand to see full code

export default defineComponent({
  async run({ steps, $ }) {
    // Update these to match your exact Zoho CRM pipeline stage names
    const WATCHED_STAGES = [
      'Qualification',
      'Needs Analysis',
      'Value Proposition',
      'Proposal/Price Quote',
      'Negotiation/Review',
      'Closed Won',
      'Closed Lost',
    ];

    const deal = steps.trigger.event;

    const currentStage = deal?.Stage;
    const dealName = deal?.Deal_Name || 'Unnamed Deal';
    const ownerName = deal?.Owner?.name || 'Unknown Owner';
    const amount = deal?.Amount
      ? `$${Number(deal.Amount).toLocaleString('en-US')}`
      : 'No amount set';
    const accountName = deal?.Account_Name || 'No account';
    const closingDate = deal?.Closing_Date
      ? new Date(deal.Closing_Date).toLocaleDateString('en-US', {
          month: 'short', day: 'numeric', year: 'numeric',
        })
      : 'No close date';

    // Exit early if this stage isn't in our watch list
    if (!currentStage || !WATCHED_STAGES.includes(currentStage)) {
      $.flow.exit(`Stage '${currentStage}' is not in WATCHED_STAGES — skipping notification.`);
    }

    // Choose emoji based on stage
    const stageEmoji = currentStage === 'Closed Won'
      ? '🎉'
      : currentStage === 'Closed Lost'
      ? '❌'
      : '🔄';

    // Build the Slack message
    const slackMessage = [
      `${stageEmoji} *Deal Stage Update*`,
      `*${dealName}* → ${currentStage}`,
      `💰 ${amount} | 🏢 ${accountName}`,
      `👤 Owner: ${ownerName} | 📅 Close: ${closingDate}`,
    ].join('\n');

    return {
      dealName,
      stage: currentStage,
      owner: ownerName,
      amount,
      accountName,
      closingDate,
      slackMessage,
    };
  },
});
Slack fields
text
user
channel
ts
thread_ts
available as variables:
1.props.text
1.props.user
1.props.channel
1.props.ts
1.props.thread_ts
9

Workflow Canvas > Test Workflow Button

Test the full workflow end to end

Click 'Test Workflow' at the top of the canvas. Pipedream runs all steps against the sample event you captured earlier. Check the Slack step output — it should show a 200 OK response from Slack. Switch to your Slack channel and confirm the message arrived. The message should include the deal name, stage, owner name, and deal amount.

  1. 1Click the 'Test Workflow' button in the top toolbar
  2. 2Watch each step turn green as it executes
  3. 3Click the Slack step to see the raw API response
  4. 4Open your Slack channel to confirm the message appeared
What you should see: All steps show green checkmarks. The Slack channel shows a message like: '🎉 Deal moved to Negotiation — Acme Corp ($24,000) — Owner: Sarah Chen'.
10

Workflow Canvas > Deploy Button

Deploy the workflow

Click the grey 'Deploy' button in the top-right corner of the canvas. The button turns green and the workflow status changes to 'Active'. From this point, every Zoho CRM deal update triggers this workflow in real time. You can monitor executions in the 'Logs' tab on the left sidebar — each run shows inputs, outputs, and any errors per step.

  1. 1Click the grey 'Deploy' button in the top right
  2. 2Confirm the workflow status changes to 'Active' (green badge)
  3. 3Go to Zoho CRM and change a live deal's stage
  4. 4Check the Logs tab in Pipedream to see the live execution
  5. 5Confirm the Slack message appears in your channel within 10–20 seconds
What you should see: The workflow shows 'Active' status. The Logs tab shows a new execution entry within seconds of saving a deal stage change in Zoho CRM.
Common mistake — Pipedream's free tier allows 10,000 credits/month. Each workflow execution costs roughly 1–3 credits depending on step count. At high deal-update volume, you can hit this limit. Set up a credit usage alert in Settings > Billing before going live.

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 at least one person who can read Node.js — even just enough to edit a string. The real advantage here is the filter logic: Zoho doesn't have a native 'stage changed only' webhook event, so you need code to prevent your Slack channel from getting flooded on every deal field edit. Pipedream's Node.js step handles that in 10 lines. The other reason to pick Pipedream: webhook latency is 10–30 seconds total, which is better than Make's polling interval (minimum 1 minute on paid plans) for a notification use case where freshness matters. If nobody on the team can touch code at all, use Zapier — the filter step maps to a simple 'Filter' action with no code required.

Cost

Pipedream's free tier gives you 10,000 credits/month. This workflow costs roughly 2–3 credits per execution (trigger + code step + Slack step). At 3,000 deal updates/month — which is high for a 10-person sales team — you'd use about 9,000 credits and stay on the free tier. If you exceed the limit, Pipedream's Basic plan is $19/month for 100,000 credits. Zapier charges $49/month for 2,000 tasks — each task is one step, so this 3-step workflow burns 3 tasks per run, meaning 2,000 tasks covers only ~666 deal updates. Pipedream is cheaper by roughly $30/month at moderate volume.

Tradeoffs

Make has one clear edge here: its Zoho CRM module includes a 'Watch Records' trigger with field-change filtering baked into the UI — no code needed to isolate stage changes. That's a real advantage for no-code teams. Zapier's 'Updated Deal in Zoho CRM' trigger is simpler to configure but fires on any field change just like Pipedream, requiring a Filter step that non-technical users often misconfigure. n8n's Zoho CRM node requires self-hosting or cloud, which adds infrastructure overhead — not worth it for a single notification workflow. Power Automate has no native Zoho CRM connector, so you'd need a custom HTTP action and manual webhook registration, which is more work than Pipedream. Pipedream wins on the combination of real-time delivery, code flexibility, and cost — but if your team is entirely no-code, Make's UI filtering is the honest alternative.

Three things you'll hit after setup. First: Zoho CRM stage names are case-sensitive in the API payload, and they sometimes include slashes or special characters (e.g. 'Negotiation/Review'). Copy them exactly from Zoho Settings > Pipelines or your filter will silently skip notifications. Second: the Zoho OAuth token is tied to the user who authorized it. If that person leaves the company and their account is deactivated, every workflow run starts failing with 401 errors. Use a shared admin account or a dedicated API user for the OAuth connection. Third: if your team is actively working deals, the Zoho webhook fires on every save — including autosaves from Zoho mobile apps. A rep opening a deal on their phone can trigger a phantom notification. Add a minimum-time-in-stage check using Pipedream's $.data store if this becomes noise.

Ideas for what to build next

  • Add a Zoho Deal Link to Every MessageConstruct a direct URL to the deal in Zoho CRM using the deal ID from the payload (deal.id) and append it to the Slack message. This cuts the time from notification to action by removing the need to search for the deal manually.
  • Route Notifications to Stage-Specific ChannelsAdd a conditional branch in the workflow to post 'Closed Won' deals to #wins, stalled deals to #pipeline-review, and all others to #deals-updates. Pipedream's branch step handles this without extra code.
  • Build a Daily Deal Stage DigestCreate a second Pipedream workflow on a schedule trigger (e.g. 9am Monday) that queries the Zoho CRM API for all deals that changed stage in the past 7 days and posts a summary table to Slack — useful for managers who don't want real-time noise but need a weekly view.

Related guides

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