

How to Send Lost Deal Alerts from Zoho CRM to Slack with n8n
When a deal is marked Lost in Zoho CRM, n8n fires a webhook, pulls the reason code and competitor field, and posts a formatted alert to a Slack management channel within seconds.
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 10-100 person companies who need instant visibility into lost deals without logging into Zoho CRM throughout the day.
Not ideal for
Teams losing fewer than 5 deals per week — a daily digest email from Zoho CRM's built-in reports is simpler and requires no tooling.
Sync type
real-timeUse case type
notificationReal-World Example
A 25-person B2B SaaS company's sales team marks deals lost in Zoho CRM with reason codes like 'Price' or 'Lost to Competitor' and a competitor name field. Before this workflow, the VP of Sales checked Zoho CRM once a day and missed competitive losses to a specific rival for two weeks before spotting a pattern. Now a Slack alert hits #sales-leadership within 30 seconds of a rep marking a deal lost, including the competitor name and reason code, so the VP can respond the same day.
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 n8n
Copy the pre-built n8n blueprint and paste it straight into n8n. 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 | |
| Stage | Stage | |
| Loss Reason | Loss_Reason | |
| Amount | Amount | |
| Deal Owner | Owner | |
| Deal ID | id | |
3 optional fields▸ show
| Competitor | Competitor |
| Closing Date | Closing_Date |
| Account Name | Account_Name |
Step-by-Step Setup
n8n Canvas > + Node > Webhook
Create a Workflow in n8n and Add a Webhook Trigger
Open your n8n instance and click the orange 'New Workflow' button in the top right. On the blank canvas, click the '+' node and search for 'Webhook'. Select the Webhook trigger node. In the right-hand panel, set the HTTP Method to POST and note the generated webhook URL — you'll paste this into Zoho CRM in the next step. Leave Authentication set to None for now; you can add header auth later.
- 1Click 'New Workflow' in the top right of your n8n dashboard
- 2Click the '+' icon on the blank canvas to open the node selector
- 3Search for 'Webhook' and select the Webhook trigger
- 4Set HTTP Method to POST in the right panel
- 5Copy the Test URL shown — you will use it in Zoho CRM
Zoho CRM > Setup > Automation > Actions > Webhooks > New Webhook
Configure a Zoho CRM Webhook on Deal Stage Change
In Zoho CRM, go to Setup > Automation > Actions > Webhooks and click 'New Webhook'. Name it 'Lost Deal Notification'. Paste your n8n webhook URL into the URL to Notify field. Set the method to POST and the format to JSON. Under Parameters, add the deal fields you want to forward: Deal Name, Stage, Closing Date, Amount, Loss Reason, Competitor, and Owner Name. Save the webhook.
- 1Navigate to Setup > Automation > Actions > Webhooks
- 2Click 'New Webhook' in the top right
- 3Name it 'Lost Deal n8n Notification'
- 4Paste your n8n Test URL into the 'URL to Notify' field
- 5Set Method to POST and Body Type to JSON
- 6Add parameters: Deal_Name, Stage, Closing_Date, Amount, Loss_Reason, Competitor, Owner
Zoho CRM > Setup > Automation > Workflow Rules > Create Rule
Create a Zoho CRM Workflow Rule to Trigger on Lost Stage
Still in Zoho CRM, go to Setup > Automation > Workflow Rules and click 'Create Rule'. Set the module to Deals. Set the trigger to 'Field Update' and choose the Stage field. Set the condition so Stage equals 'Closed Lost'. Under Actions, click 'Add Action', choose Webhook, and select the webhook you created in Step 2. Save and activate the rule.
- 1Go to Setup > Automation > Workflow Rules
- 2Click 'Create Rule'
- 3Set Module to Deals and Rule Trigger to 'Field Update'
- 4Choose the Stage field and set condition: Stage equals 'Closed Lost'
- 5Under Actions, click 'Add Action' and select Webhook
- 6Choose your 'Lost Deal n8n Notification' webhook and save
n8n Canvas > Webhook Node > Listen for Test Event
Test the Webhook by Updating a Deal in Zoho CRM
Go back to n8n and click 'Listen for Test Event' on your Webhook node. Then open Zoho CRM, find a test deal, and manually change its Stage to 'Closed Lost'. Within a few seconds, n8n should receive the payload. Click the Webhook node in n8n to inspect the incoming data in the Output panel on the right side. Confirm that fields like Deal_Name, Loss_Reason, and Competitor appear in the JSON body.
- 1Click the Webhook node on the n8n canvas
- 2Click 'Listen for Test Event' in the node panel
- 3Open Zoho CRM in a second browser tab
- 4Find any test deal and change Stage to 'Closed Lost'
- 5Return to n8n and confirm the payload appeared in the Output tab
n8n Canvas > + Node after Webhook > Code
Add a Code Node to Format the Deal Data
Click the '+' button after the Webhook node and add a Code node. This is where you extract and clean the fields from the raw Zoho payload. Zoho nests the webhook body inside body, so you need to pull from $input.item.json.body or the equivalent path shown in your Output tab from Step 4. Paste the transformation code from the Pro Tip section below. The code normalizes the amount to a dollar string, handles missing competitor fields gracefully, and builds the final object for the Slack message.
- 1Click '+' after the Webhook node
- 2Search for 'Code' and select the Code node
- 3Set Language to JavaScript
- 4Paste the transformation code from the Pro Tip section
- 5Click 'Test Step' to confirm the output object looks correct
Paste this into the Code node (Step 5) between the Webhook and IF nodes. It handles Zoho's string-formatted amounts, null competitor fields, date reformatting, and constructs the full Slack message text with a direct link to the deal. Replace YOUR_ORG_ID with your Zoho CRM organization ID, found in Setup > Developer Space > API > Org ID.
JavaScript — Code Node// n8n Code Node — Lost Deal Formatter▸ Show code
// n8n Code Node — Lost Deal Formatter // Runs once per deal. Handles Zoho webhook payload normalization. const item = $input.item.json;
... expand to see full code
// n8n Code Node — Lost Deal Formatter
// Runs once per deal. Handles Zoho webhook payload normalization.
const item = $input.item.json;
// Zoho sends Amount as a locale-formatted string like '48,000.00'
const rawAmount = item.Amount || item.body?.Amount || '0';
const numericAmount = parseFloat(String(rawAmount).replace(/,/g, ''));
const formattedAmount = numericAmount.toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 0
});
// Handle missing competitor gracefully
const competitor = (item.Competitor || item.body?.Competitor || '').trim();
const competitorDisplay = competitor.length > 0 ? competitor : 'Not specified';
// Reformat Zoho date from YYYY-MM-DD to human-readable
const rawDate = item.Closing_Date || item.body?.Closing_Date || '';
let formattedDate = 'N/A';
if (rawDate) {
const d = new Date(rawDate + 'T00:00:00');
formattedDate = d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
}
// Extract core fields with fallback to body-nested structure (Zoho varies)
const dealName = item.Deal_Name || item.body?.Deal_Name || 'Unknown Deal';
const lossReason = item.Loss_Reason || item.body?.Loss_Reason || 'No reason provided';
const ownerName = item.Owner || item.body?.Owner || 'Unknown';
const accountName = item.Account_Name || item.body?.Account_Name || '';
const dealId = item.id || item.body?.id || '';
// Build Zoho CRM deep link — replace YOUR_ORG_ID
const orgId = 'YOUR_ORG_ID';
const dealUrl = dealId
? `https://crm.zoho.com/crm/${orgId}/tab/Potentials/${dealId}`
: 'https://crm.zoho.com';
// Build Slack message text
const accountLine = accountName ? `🏢 ${accountName}\n` : '';
const slackMessage = [
`🔴 *Deal Lost: ${dealName}*`,
`${accountLine}💰 ${formattedAmount} | 👤 ${ownerName}`,
`❌ Reason: ${lossReason} | Competitor: *${competitorDisplay}*`,
`📅 Expected Close: ${formattedDate}`,
`🔗 <${dealUrl}|View Deal in Zoho CRM>`
].join('\n');
return [{
json: {
dealName,
lossReason,
competitor: competitorDisplay,
ownerName,
accountName,
amount: formattedAmount,
numericAmount,
closingDate: formattedDate,
dealUrl,
slackMessage
}
}];n8n Canvas > + Node after Code > IF
Add an IF Node to Filter Out Test or Junk Deals
Click '+' after the Code node and add an IF node. Set the condition to check that dealName does not contain 'TEST' and that amount is greater than 0. This prevents your Slack channel from flooding with test records that reps create during CRM demos or training. Connect the True branch to the next step and leave the False branch unconnected — n8n will simply stop execution for filtered records.
- 1Click '+' after the Code node and select IF
- 2Add Condition 1: dealName does not contain 'TEST' (case insensitive)
- 3Add Condition 2: amount is greater than 0
- 4Set Combine Conditions to AND
- 5Leave the False output branch unconnected
n8n Canvas > + Node > Slack > Credentials > Create New
Connect Your Slack Account in n8n
Click '+' on the True branch of the IF node and add a Slack node. In the node panel, click the Credential dropdown and select 'Create New'. n8n will open the Slack OAuth flow — click 'Connect' and log in to your Slack workspace. You need to authorize the chat:write scope so n8n can post messages. After authorizing, the credential will appear with a green Connected status.
- 1Click '+' on the True output of the IF node
- 2Search for 'Slack' and select the Slack node
- 3Set Resource to Message and Operation to Send
- 4Click the Credential field and select 'Create New Credential'
- 5Complete the OAuth flow in the popup window
- 6Confirm the green Connected badge appears in the credential selector
n8n Canvas > Slack Node > Channel + Message fields
Configure the Slack Message with Deal Fields
In the Slack node, set the Channel to your management channel (e.g. #sales-leadership). Set Send As to Bot. In the Message field, switch to Expression mode by clicking the small grey '{}' toggle. Build the message using the output fields from your Code node. Use Block Kit formatting with a header, deal amount, reason code, competitor name, and owner — the exact template is in the Pro Tip section. This gives the message structure and makes it scannable in Slack.
- 1Set Channel to your target Slack channel (e.g. #sales-leadership)
- 2Set Send As to Bot
- 3Click the Message field and toggle to Expression mode using the '{}' icon
- 4Paste your Block Kit JSON or plain-text message template using {{ $json.dealName }} syntax
- 5Click 'Test Step' to send a real test message to Slack
n8n Canvas > Node Menu > Settings > Error Workflow
Add an Error Handler Node
Click the three-dot menu on any node in the workflow and select 'Add Error Workflow' or attach a second Slack node to the Error output of your main Slack node. Configure it to post to a #workflow-errors channel with the error message and the deal name that caused the failure. This prevents silent failures — without it, a Slack API rate limit or a malformed field will cause the workflow to fail with no notification.
- 1Click the three-dot menu on the Slack node
- 2Select 'Settings'
- 3Toggle on 'Continue On Fail' if you want non-critical errors to pass through
- 4Go to Workflow Settings > Error Workflow and assign a dedicated error-handling workflow
- 5Alternatively, add a second Slack node on the error branch posting to #workflow-errors
n8n Canvas > Webhook Node > Production URL | Zoho CRM > Setup > Webhooks
Switch Webhook to Production URL and Activate
Go back to your Webhook node and copy the Production URL (not the Test URL). Return to Zoho CRM at Setup > Automation > Actions > Webhooks, open your Lost Deal webhook, and replace the Test URL with the Production URL. Save. Back in n8n, click the toggle in the top right of the workflow canvas to set it to Active. The workflow will now fire automatically without you needing to click 'Listen for Test Event'.
- 1Open the Webhook node in n8n and copy the Production URL
- 2Go to Zoho CRM > Setup > Automation > Actions > Webhooks
- 3Open your Lost Deal webhook and replace the URL with the Production URL
- 4Save the Zoho webhook
- 5Return to n8n and click the Active toggle in the top-right of the canvas
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 n8n for this if your team self-hosts or has privacy requirements around CRM data leaving a SaaS platform. Zoho deal data — including deal size and competitor names — is sensitive, and routing it through n8n means it stays on your infrastructure rather than passing through Make's or Zapier's servers. n8n also gives you the Code node, which you genuinely need here: Zoho's webhook payload format is inconsistent across plan tiers and occasionally nests fields inside a body object versus at the top level, and handling that in pure no-code drag-and-drop tools is painful. The one scenario where you'd pick something else: if nobody on your team has touched a terminal or wants to maintain a self-hosted server, use Make instead — it handles this workflow with zero code and has a Zoho CRM module that handles auth more cleanly.
Cost math is simple. This workflow is single-record and webhook-triggered. One lost deal = one n8n execution. On n8n Cloud's Starter plan ($20/month), you get 2,500 executions. If your team loses 50 deals per month, that's 50 executions — you will never come close to the limit. On self-hosted n8n, executions are unlimited and the only cost is your server. A $6/month DigitalOcean droplet running n8n handles this with headroom for dozens of other workflows. Compare that to Zapier, where this workflow costs 2 Zaps (one for Zoho, one for Slack) and 1 task per deal — at $19.99/month for 750 tasks, 50 lost deals costs you about $1.33/month of your quota, which is fine until you add other Zaps and burn through the ceiling.
Make handles this workflow with fewer configuration steps than n8n — the Zoho CRM 'Watch Records' module and the Slack 'Create a Message' action are purpose-built and require no code. Make also has a cleaner UI for testing individual modules. Zapier's Zoho CRM trigger is reliable and the setup takes about 12 minutes, but you cannot do the amount-string parsing or null-competitor handling in Zap steps without a Code by Zapier step, which requires a paid plan. Power Automate has a Zoho CRM connector but it is a premium connector — $15/user/month on top of your Microsoft 365 plan — making it the most expensive option here by far for no additional capability. Pipedream gives you similar code flexibility to n8n with a hosted environment, which is appealing, but its Zoho CRM trigger support is thinner and requires more manual webhook wiring. n8n wins here because the Code node genuinely solves the data format problem, and self-hosting keeps CRM data off third-party servers.
Three things you will hit after go-live. First, Zoho CRM rate-limits outbound webhooks to 10 per minute per workflow rule. If your team closes a batch of deals at end-of-quarter, firings can queue and delay — expect 5-10 minute lag during high-volume periods, not the usual 15 seconds. Second, the Zoho webhook payload does not include the account's industry or the deal's age in pipeline, even if you add them to the parameter list — those fields return empty for reasons Zoho has not documented publicly. Fetch them with a separate Zoho CRM API call in an HTTP Request node if you need them. Third, Slack's Block Kit message formatting breaks silently if a deal name contains special characters like &, <, or > — Slack's API treats those as HTML entities. Run your dealName through a replace(/&/g, '&').replace(/</g, '<') in the Code node to prevent malformed messages.
Ideas for what to build next
- →Weekly Competitive Loss Digest — Add a scheduled n8n workflow that queries Zoho CRM's Reports API every Monday morning, aggregates losses by competitor from the past 7 days, and posts a ranked summary to Slack — so management sees trends, not just individual deal alerts.
- →Route Alerts by Deal Size — Extend the IF node to branch on deal amount: deals over $50K go to #exec-channel, deals under $50K go to #sales-leadership. This reduces noise for senior leadership without losing visibility into smaller losses.
- →Log Lost Deals to Google Sheets for Analysis — Add a Google Sheets node after the Slack node to append each lost deal as a row, including date, amount, reason, and competitor. After 90 days you will have a structured dataset to analyze win-rate trends by reason code without needing a BI tool.
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