

How to Send Zoho CRM Leads to Slack with n8n
Automatically posts a formatted Slack channel message every time a new lead is created in Zoho CRM, triggered via Zoho's webhook to n8n.
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 self-host n8n and want real-time Slack alerts with custom formatting and routing logic per lead source or territory.
Not ideal for
Teams without a server or cloud instance to host n8n — use Zapier or Make instead and skip the infrastructure overhead.
Sync type
real-timeUse case type
notificationReal-World Example
A 12-person B2B SaaS sales team routes inbound demo requests through Zoho CRM. Before this workflow, reps refreshed CRM manually every hour and routinely missed hot leads for 60–90 minutes. Now every new lead fires a Slack alert to #inbound-leads within 30 seconds, including lead source, phone number, and the owning rep's name so someone claims it immediately.
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 | ||
| First Name | First_Name | |
| Last Name | Last_Name | |
Email | ||
| Company | Company | |
| Lead Source | Lead_Source | |
| Lead Owner | Lead_Owner | |
3 optional fields▸ show
| Phone | Phone |
| Lead Status | Lead_Status |
| Annual Revenue | Annual_Revenue |
Step-by-Step Setup
n8n Dashboard > + New Workflow
Create a new workflow in n8n
Log into your n8n instance and click the orange '+' button in the top left of the canvas to create a new workflow. Name it something descriptive like 'Zoho CRM → Slack New Lead Alert'. You'll see an empty canvas with a 'Click to add first step' prompt in the center. All configuration happens here on this canvas view.
- 1Click the orange '+' button in the top left of the n8n dashboard
- 2Select 'Blank Workflow' from the options
- 3Click the pencil icon next to 'My Workflow' and rename it to 'Zoho CRM → Slack New Lead Alert'
- 4Click 'Save' in the top right
Canvas > + Add Node > Webhook
Add a Webhook trigger node
Click the '+' icon on the canvas to add your first node. Search for 'Webhook' and select it — this is the built-in n8n node, not a third-party one. Set the HTTP Method to POST and note the webhook URL that n8n generates. You'll paste this URL into Zoho CRM in the next step. Keep Authentication set to 'None' for initial testing; you can add header auth later.
- 1Click the '+' node icon on the empty canvas
- 2Type 'Webhook' in the search bar and click the Webhook node
- 3Set HTTP Method to 'POST'
- 4Copy the 'Webhook URL' shown in the node panel — you'll need this in the next step
- 5Click 'Save' on the node
Zoho CRM > Setup > Automation > Actions > Webhooks > + New Webhook
Configure Zoho CRM webhook to fire on new leads
Log into Zoho CRM and navigate to Setup > Automation > Actions > Webhooks. Click '+New Webhook'. Give it a name like 'n8n New Lead Alert'. Paste your n8n webhook URL into the URL to Notify field. Set Module to 'Leads' and leave the method as POST. Under Parameters, map the lead fields you want n8n to receive — at minimum: First Name, Last Name, Email, Phone, Lead Source, Lead Owner, and Company.
- 1In Zoho CRM, click the gear icon (Setup) in the top right
- 2Navigate to Automation > Actions > Webhooks
- 3Click '+ New Webhook'
- 4Paste your n8n Test Webhook URL into the 'URL to Notify' field
- 5Under 'Parameters', add fields: First Name, Last Name, Email, Phone, Lead Source, Lead Owner, Company
- 6Click 'Save'
Zoho CRM > Setup > Automation > Workflow Rules > + Create Rule
Create a Zoho Workflow Rule to trigger on lead creation
Still in Zoho CRM Setup, go to Automation > Workflow Rules and click '+ Create Rule'. Set Module to 'Leads' and choose trigger 'On a record action' > 'Create'. Skip conditions unless you want to filter by lead source or region. Under Actions, click '+' next to Webhooks and select the webhook you just created. Save and activate the rule.
- 1Go to Setup > Automation > Workflow Rules
- 2Click '+ Create Rule'
- 3Set Module to 'Leads'
- 4Set trigger to 'On a record action' and check 'Create'
- 5Under Actions section, click '+' next to 'Webhooks'
- 6Select the webhook you created in Step 3
- 7Click 'Save & Activate'
n8n Canvas > Webhook Node > Listen for Test Event
Test the webhook and inspect the incoming payload
Back in n8n, click 'Listen for Test Event' on your Webhook node. Then create a test lead in Zoho CRM — use a real-looking name like 'Jane Doe' at 'Acme Corp'. Within 30 seconds you should see the webhook payload appear in n8n's output panel on the right. Expand the JSON to confirm all your mapped fields are present. This data shape is what all downstream nodes will reference.
- 1Click on your Webhook node in n8n
- 2Click the 'Listen for Test Event' button in the node panel
- 3Switch to Zoho CRM and create a new Lead with full details (name, email, phone, company, lead source)
- 4Return to n8n — you should see the payload appear within 30 seconds
- 5Click through the JSON output to confirm all expected fields are present
Canvas > + Add Node > Edit Fields (Set)
Add a Set node to extract and format lead fields
Click '+' after the Webhook node and add a 'Edit Fields (Set)' node. This is where you extract the raw Zoho payload into clean variables for the Slack message. Map each field explicitly: set leadName as {{$json.body.First_Name}} + ' ' + {{$json.body.Last_Name}}, set email as {{$json.body.Email}}, set phone as {{$json.body.Phone}}, set company as {{$json.body.Company}}, set leadSource as {{$json.body.Lead_Source}}, and set ownerName as {{$json.body.Lead_Owner.name}}. Using a Set node here makes the Slack node much easier to read and maintain.
- 1Click '+' after the Webhook node on the canvas
- 2Search for 'Edit Fields' and select the 'Edit Fields (Set)' node
- 3Click '+ Add Field' and set Name: leadName, Value: {{$json.body.First_Name + ' ' + $json.body.Last_Name}}
- 4Add field: email = {{$json.body.Email}}
- 5Add field: phone = {{$json.body.Phone}}
- 6Add field: company = {{$json.body.Company}}
- 7Add field: leadSource = {{$json.body.Lead_Source}}
- 8Add field: ownerName = {{$json.body.Lead_Owner.name}}
Canvas > + Add Node > Slack > Credential > + Add Credential
Connect your Slack credential in n8n
Click '+' after the Set node and add a Slack node. In the node's Credential dropdown, click '+ Add Credential'. n8n will prompt you to create a Slack OAuth2 app or use a Bot Token. The easiest method for most teams is a Slack Bot Token: go to api.slack.com/apps, create a new app, add the chat:write and chat:write.public OAuth scopes, install it to your workspace, and copy the Bot User OAuth Token. Paste it into n8n's credential field.
- 1Click '+' after the Set node
- 2Search 'Slack' and select the Slack node
- 3Set Resource to 'Message' and Operation to 'Send'
- 4Click the Credential dropdown and select '+ Add Credential'
- 5Open api.slack.com/apps in a new tab and create a new app
- 6Under OAuth & Permissions, add scopes: chat:write and chat:write.public
- 7Click 'Install to Workspace', then copy the Bot User OAuth Token
- 8Paste the token into n8n's Slack credential field and click 'Save'
Canvas > Slack Node > Channel / Text fields
Configure the Slack message content
With the Slack node open, set Channel to the exact channel name or ID (e.g. #inbound-leads). Set the Text field to your notification message using the Set node's output variables. Use Slack's mrkdwn format for readability. A good format: '*New Lead:* {{$json.leadName}}\n*Company:* {{$json.company}}\n*Email:* {{$json.email}}\n*Phone:* {{$json.phone}}\n*Source:* {{$json.leadSource}}\n*Owner:* {{$json.ownerName}}'. You can also switch to Block Kit for richer formatting using the JSON/Blocks option in the Slack node.
- 1In the Slack node, set Channel to '#inbound-leads' (or your target channel)
- 2In the Text field, paste your formatted message template using {{$json.fieldName}} references
- 3Optionally toggle 'Blocks' on and paste Block Kit JSON for button-style formatting
- 4Set 'As User' to your bot name so messages look clean in channel
Canvas > Slack Node > (right-click) > Add Error Output
Add an error handler node for failed deliveries
Click the three dots on your Slack node and select 'Add Error Workflow' — or better, add a second branch using the error output pin. Connect the error output to a second Slack node that posts to a #workflow-errors channel (or sends you a direct message) with the error details. This catches Slack API failures, rate limit hits, or malformed payloads without silently dropping lead notifications. Use {{$json.message}} to surface the actual error text.
- 1Right-click the Slack node on the canvas
- 2Select 'Add Error Output' — a red error pin appears on the node
- 3Click '+' on the red error pin and add another Slack node
- 4Set this second Slack node to post to '#workflow-errors' or your own DM
- 5Set the text to: 'Lead notification failed: {{$json.message}} | Lead: {{$node["Edit Fields"].json.leadName}}'
n8n Canvas > Active Toggle (top right) | Zoho CRM > Setup > Automation > Actions > Webhooks
Activate the workflow and switch Zoho to the production webhook URL
Click the 'Active' toggle in the top right of the n8n canvas to activate your workflow. n8n will switch from the test webhook URL to the production webhook URL automatically. Go back to your Zoho CRM Webhook configuration (Setup > Automation > Actions > Webhooks) and replace the Test URL with the Production URL from your n8n Webhook node. The production URL format looks identical but uses /webhook/ instead of /webhook-test/ in the path.
- 1In n8n, click the 'Inactive' toggle in the top right — it turns green and reads 'Active'
- 2Copy the Production Webhook URL from the Webhook node (click the node to see it)
- 3In Zoho CRM, go to Setup > Automation > Actions > Webhooks
- 4Edit your webhook and replace the old URL with the Production URL
- 5Save the Zoho webhook
- 6Create one more test lead in Zoho CRM to confirm the live flow works end-to-end
This Code node replaces both the Set node and the Slack message formatting step. Paste it as a single Code node between your Webhook and Slack nodes. It handles the Lead Owner nested object, falls back gracefully if optional fields are missing, and builds a Slack Block Kit payload for a richer notification with a 'View in Zoho' button — assuming you store the Zoho Lead ID in your webhook parameters.
JavaScript — Code Node// n8n Code Node: Format Zoho Lead → Slack Block Kit message▸ Show code
// n8n Code Node: Format Zoho Lead → Slack Block Kit message // Place this between your Webhook node and Slack node // Requires: Zoho webhook params include Id, First_Name, Last_Name, Email,
... expand to see full code
// n8n Code Node: Format Zoho Lead → Slack Block Kit message
// Place this between your Webhook node and Slack node
// Requires: Zoho webhook params include Id, First_Name, Last_Name, Email,
// Phone, Company, Lead_Source, Lead_Owner (object), Lead_Status
const items = $input.all();
const results = [];
for (const item of items) {
const body = item.json.body || item.json;
// Safely extract nested Lead Owner name
const ownerName =
typeof body.Lead_Owner === 'object' && body.Lead_Owner !== null
? body.Lead_Owner.name || 'Unassigned'
: body.Lead_Owner || 'Unassigned';
const fullName = [body.First_Name, body.Last_Name].filter(Boolean).join(' ') || 'Unknown Lead';
const company = body.Company || 'No company';
const email = body.Email || 'No email';
const phone = body.Phone || 'No phone';
const source = body.Lead_Source || 'Unknown source';
const status = body.Lead_Status || 'Not Contacted';
const leadId = body.Id || '';
// Build Zoho CRM deep link (update YOUR_ZOHO_DOMAIN)
const zohoUrl = leadId
? `https://crm.zoho.com/crm/org/tab/Leads/${leadId}`
: 'https://crm.zoho.com';
// Slack Block Kit payload
const blocks = [
{
type: 'header',
text: {
type: 'plain_text',
text: `🟢 New Lead: ${fullName}`,
emoji: true
}
},
{
type: 'section',
fields: [
{ type: 'mrkdwn', text: `*Company:*\n${company}` },
{ type: 'mrkdwn', text: `*Source:*\n${source}` },
{ type: 'mrkdwn', text: `*Email:*\n${email}` },
{ type: 'mrkdwn', text: `*Phone:*\n${phone}` },
{ type: 'mrkdwn', text: `*Owner:*\n${ownerName}` },
{ type: 'mrkdwn', text: `*Status:*\n${status}` }
]
},
{
type: 'actions',
elements: [
{
type: 'button',
text: { type: 'plain_text', text: 'View in Zoho CRM', emoji: true },
url: zohoUrl,
action_id: 'view_lead'
}
]
}
];
results.push({
json: {
blocks: JSON.stringify(blocks),
fallbackText: `New Lead: ${fullName} from ${company} | ${email} | Owner: ${ownerName}`
}
});
}
return results;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 you self-host your stack, want zero per-task fees at scale, or need conditional routing logic that would cost extra on Zapier (e.g. send to different Slack channels based on lead source, territory, or deal size). n8n's Code node also means you can handle Zoho's nested Lead Owner object cleanly — one JavaScript expression instead of a multi-step workaround. The one scenario where you should pick something else: if your team has no one comfortable maintaining a Docker container or a cloud VM. A Zoho webhook misfiring at 2am is not fun to debug if your n8n instance is on a personal laptop.
Cost math is straightforward. Each lead creation fires one webhook and one Slack message — that's one n8n execution per lead. n8n Cloud's Starter plan is $20/month and includes 2,500 executions. At 100 new leads per month, you're spending $0.008 per lead notification. At 2,000 leads/month you'd hit the Starter limit but the Pro plan at $50/month covers 10,000 executions. Compare that to Zapier: 2,000 leads/month at 1 Zap step each = 2,000 tasks, which sits at the $49/month Starter tier — roughly equivalent. The real cost gap opens if you add logic nodes (IF, Set, error handler): Zapier counts each step as a task, so a 3-step Zap costs 6,000 tasks for 2,000 leads. On n8n, multi-node workflows cost the same as single-node ones per execution.
Make handles this use case cleanly and its webhook trigger fires in under 30 seconds, same as n8n. Make's scenario builder also has a built-in JSON parse module that handles Zoho's nested objects without a Code node — slight UX advantage. Zapier's Zoho CRM trigger uses polling (every 5–15 minutes on most plans), which means leads could sit unnotified for nearly 15 minutes — a real problem for fast-response sales teams. Power Automate has a Zoho CRM connector but it's a premium connector requiring a per-user license on top of your Microsoft plan; the Slack connector also has limited Block Kit support. Pipedream has excellent Zoho and Slack component support with sub-5-second latency, but adds cost complexity for teams who aren't developers. n8n is still the right call here if you want webhook speed, full code access, and predictable flat pricing as lead volume grows.
Three things you'll hit after setup. First: Zoho's webhook payload structure changes slightly depending on whether Lead Owner is set at the time of creation — if a lead is created with no owner, Lead_Owner comes through as null, not an empty object, which breaks a naive .name reference and posts 'undefined' into Slack. Guard against this with a null check in your Set node or Code node. Second: Zoho CRM enforces a webhook notification limit of 500 calls per day on some plans — check your Zoho edition in Setup > Company > Zoho Apps. If you're on the Standard plan, you may hit this ceiling during campaign launches. Third: Slack's chat.postMessage API rate-limits to 1 message per second per channel. If 10 leads come in within 5 seconds (e.g. a webinar just ended), n8n will fire 10 near-simultaneous requests and some will get rate-limited. Add a Wait node set to 1.1 seconds between the Set node and Slack node — it adds a tiny delay but guarantees delivery.
Ideas for what to build next
- →Route leads to different Slack channels by source — Add an IF or Switch node after the Set node to send Web Form leads to #inbound-web, cold outreach leads to #inbound-outbound, and so on. This prevents high-volume sources from burying high-priority leads in a single channel.
- →Add a Slack interactive button to claim the lead — Use Slack's Interactivity feature with n8n's Slack Trigger to let reps click 'Claim Lead' directly in the notification — the workflow can then update the Lead Owner field in Zoho CRM via the Zoho node without the rep opening CRM at all.
- →Send a daily lead digest instead of per-lead pings — Add a second n8n workflow on a schedule trigger (e.g. 8am daily) that queries Zoho CRM via the Zoho node for all leads created in the past 24 hours and posts a single summary message — useful for teams overwhelmed by per-lead noise.
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