This workflow corresponds to n8n.io template #13351 — we link there as the canonical source.
This workflow follows the HubSpot → Slack recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Contact Job Change & Promotion Enrichment with Lusha",
"nodes": [
{
"id": "d3b6db4c-54f2-47b4-aba0-c73d3bc5c380",
"name": "\ud83d\udccb Job Change & Promotion Enrichment",
"type": "n8n-nodes-base.stickyNote",
"position": [
-100,
-520
],
"parameters": {
"width": 860,
"height": 500,
"content": "## Contact Job Change & Promotion Detection with Lusha\n\n**Who it's for:** AEs & CSMs tracking champions and key contacts\n\n**What it does:** Automatically detects when contacts change jobs or get promoted. Uses **bulk enrichment** to re-enrich all contacts in one API call, then compares against CRM data to detect changes. Updates CRM records and triggers follow-ups.\n\n### How it works\n1. Runs daily on a schedule\n2. Reads existing contacts from CRM\n3. Bulk re-enriches all contacts with Lusha in one call\n4. Compares new vs. stored job/company data for each contact\n5. Detects changes \u2192 updates CRM + alerts reps\n\n### Setup\n1. Install the Lusha community node\n2. Configure CRM credentials\n3. Add Lusha API credentials\n4. Set the schedule (recommended: daily)\n5. Configure Slack channel for alerts"
},
"typeVersion": 1
},
{
"id": "552714d6-caf9-41e4-ac38-b26f4232a344",
"name": "\ud83d\udcc5 1. Daily CRM Pull",
"type": "n8n-nodes-base.stickyNote",
"position": [
-30,
70
],
"parameters": {
"color": 7,
"width": 480,
"height": 270,
"content": "A daily schedule trigger pulls your existing contacts from HubSpot for re-enrichment.\n\n**Nodes:** Schedule Trigger \u2192 HubSpot Get Contacts\n\n\ud83d\udca1 Adjust the contact limit based on your Lusha API plan and contact volume."
},
"typeVersion": 1
},
{
"id": "e891a936-da50-4470-8de1-7c6747d0f056",
"name": "\ud83d\udd04 2. Bulk Re-Enrich with Lusha",
"type": "n8n-nodes-base.stickyNote",
"position": [
510,
70
],
"parameters": {
"color": 7,
"width": 560,
"height": 270,
"content": "All contacts are formatted and sent to the Lusha Bulk Enrichment API in a single call. Returns the latest job title, company, seniority, phone, and email for each contact.\n\n**Nodes:** Format for Bulk \u2192 Lusha Bulk Enrich\n\n\ud83d\udcd6 [Lusha API docs](https://www.lusha.com/docs/)"
},
"typeVersion": 1
},
{
"id": "120ec35b-f801-4b6c-a846-66409bd94e95",
"name": "\ud83d\udce4 3. Detect Changes & Alert Reps",
"type": "n8n-nodes-base.stickyNote",
"position": [
1100,
70
],
"parameters": {
"color": 7,
"width": 600,
"height": 300,
"content": "A code node compares fresh Lusha data against stored CRM records to detect job title or company changes. Changed contacts trigger a CRM update and a Slack notification to the assigned rep.\n\n**Nodes:** Detect Changes \u2192 Has Changes? \u2192 Update CRM + Slack Alert\n\n\ud83d\udca1 Customize the Slack channel and message format to match your team's workflow."
},
"typeVersion": 1
},
{
"id": "073cfe02-3b46-4e42-a820-4b2da66f01d0",
"name": "Daily Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
0,
340
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"typeVersion": 1
},
{
"id": "091724db-c942-4093-8056-b2a9926d917c",
"name": "Get CRM Contacts",
"type": "n8n-nodes-base.hubspot",
"position": [
280,
340
],
"parameters": {
"limit": 100,
"resource": "contact",
"operation": "getAll",
"returnAll": false,
"additionalFields": {
"formSubmissionMode": "none"
}
},
"credentials": {
"hubspotOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "84a9d045-ae01-41c3-a332-4baec95e6acf",
"name": "Format for Bulk Enrichment",
"type": "n8n-nodes-base.code",
"position": [
560,
340
],
"parameters": {
"jsCode": "// Format ALL CRM contacts for Lusha Bulk Enrichment API\nconst items = $input.all();\nlet contactIdCounter = 1;\n\nconst contacts = items\n .filter(item => item.json.properties?.email)\n .map(item => ({\n contactId: String(contactIdCounter++),\n email: item.json.properties.email\n }));\n\nconst payload = {\n contacts,\n metadata: {}\n};\n\nreturn [{ json: { contactsPayload: JSON.stringify(payload) } }];"
},
"typeVersion": 2
},
{
"id": "24be2214-9d2c-4d31-b7a4-b7487d375651",
"name": "Re-Enrich All in Bulk",
"type": "@lusha-org/n8n-nodes-lusha.lusha",
"position": [
840,
340
],
"parameters": {
"bulkType": "json",
"operation": "enrichBulk",
"contactsPayloadJson": "={{ $json.contactsPayload }}",
"contactBulkAdditionalOptions": {}
},
"credentials": {
"lushaApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "f75c1e22-1e3b-4596-9ba8-233bc6d6cebb",
"name": "Detect Changes",
"type": "n8n-nodes-base.code",
"position": [
1120,
340
],
"parameters": {
"jsCode": "// Compare bulk-enriched Lusha data with CRM records\n// Match by email to detect job/company changes\nconst items = $input.all();\nconst crmContacts = $('Get CRM Contacts').all();\n\n// Build email \u2192 CRM record lookup\nconst crmByEmail = {};\nfor (const c of crmContacts) {\n const email = (c.json.properties?.email || '').toLowerCase();\n if (email) crmByEmail[email] = c.json;\n}\n\nconst results = [];\nfor (const item of items) {\n const lusha = item.json;\n const email = (lusha.primaryEmail || '').toLowerCase();\n const crm = crmByEmail[email] || {};\n\n const currentTitle = (crm.properties?.jobtitle || '').toLowerCase();\n const currentCompany = (crm.properties?.company || '').toLowerCase();\n const newTitle = (lusha.jobTitle || '').toLowerCase();\n const newCompany = (lusha.companyName || '').toLowerCase();\n\n const changes = [];\n if (newCompany && currentCompany && newCompany !== currentCompany) {\n changes.push({ field: 'company', from: crm.properties?.company, to: lusha.companyName });\n }\n if (newTitle && currentTitle && newTitle !== currentTitle) {\n changes.push({ field: 'jobTitle', from: crm.properties?.jobtitle, to: lusha.jobTitle });\n }\n\n results.push({\n json: {\n contactId: crm.id || '',\n email: crm.properties?.email || lusha.primaryEmail,\n firstName: crm.properties?.firstname || lusha.firstName,\n lastName: crm.properties?.lastname || lusha.lastName,\n hasChanges: changes.length > 0,\n changes,\n newJobTitle: lusha.jobTitle,\n newCompany: lusha.companyName,\n newSeniority: lusha.seniority,\n newPhone: lusha.primaryPhone,\n checkedAt: new Date().toISOString()\n }\n });\n}\n\nreturn results;"
},
"typeVersion": 2
},
{
"id": "db01889e-ae71-4b5f-9364-b90c3ce81eeb",
"name": "Has Job Changes?",
"type": "n8n-nodes-base.if",
"position": [
1400,
340
],
"parameters": {
"conditions": {
"combinator": "and",
"conditions": [
{
"id": "61adf9d1-8f4d-4713-8b82-26c6a61e24ad",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.hasChanges }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "5d4afdd9-f88f-497f-8856-26c3c1caaff0",
"name": "Update CRM Record",
"type": "n8n-nodes-base.hubspot",
"position": [
1680,
200
],
"parameters": {
"resource": "contact",
"contactId": "={{ $json.contactId }}",
"operation": "update",
"updateFields": {
"phone": "={{ $json.newPhone }}",
"company": "={{ $json.newCompany }}",
"jobtitle": "={{ $json.newJobTitle }}"
}
},
"credentials": {
"hubspotOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "51c03567-3da4-452b-8afb-ff2b8b438e3e",
"name": "Alert Rep on Slack",
"type": "n8n-nodes-base.slack",
"position": [
1680,
400
],
"parameters": {
"text": "=\ud83d\udd04 *Job Change Detected*\n\n*{{ $json.firstName }} {{ $json.lastName }}*\n\ud83d\udce7 {{ $json.email }}\n\n{{ $json.changes.map(c => `\u2022 ${c.field}: \"${c.from}\" \u2192 \"${c.to}\"`).join('\\n') }}\n\n_Updated CRM record automatically._",
"channel": "#job-changes",
"otherOptions": {}
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2
}
],
"connections": {
"Daily Schedule": {
"main": [
[
{
"node": "Get CRM Contacts",
"type": "main",
"index": 0
}
]
]
},
"Detect Changes": {
"main": [
[
{
"node": "Has Job Changes?",
"type": "main",
"index": 0
}
]
]
},
"Get CRM Contacts": {
"main": [
[
{
"node": "Format for Bulk Enrichment",
"type": "main",
"index": 0
}
]
]
},
"Has Job Changes?": {
"main": [
[
{
"node": "Update CRM Record",
"type": "main",
"index": 0
},
{
"node": "Alert Rep on Slack",
"type": "main",
"index": 0
}
],
[]
]
},
"Re-Enrich All in Bulk": {
"main": [
[
{
"node": "Detect Changes",
"type": "main",
"index": 0
}
]
]
},
"Format for Bulk Enrichment": {
"main": [
[
{
"node": "Re-Enrich All in Bulk",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
hubspotOAuth2ApilushaApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
A daily schedule pulls your existing contacts from HubSpot All contacts are bulk-enriched with Lusha in a single API call for efficiency A code node compares current Lusha data against CRM records to detect job title or company changes Changed contacts trigger a CRM update and a…
Source: https://n8n.io/workflows/13351/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A daily schedule pulls your target accounts from HubSpot All companies are bulk-enriched with Lusha in a single API call A code node detects growth signals: headcount increase, revenue growth, and fun
Runs every 6 hours to pull contacts needing a data refresh from HubSpot All contacts are bulk-enriched with Lusha in a single API call Each contact is scored against your ICP criteria (seniority, comp
Sales managers and team leads Business development representatives Marketing teams managing lead generation CRM administrators and sales operations Account executives and sales representatives Sales e
Triggers when a contact property changes in HubSpot (e.g., added to a sequence) Lusha enriches the contact with verified email, direct phone, and seniority A prospect record is built and validated — c
How it works Use this workflow to regularly re-check contacts from HubSpot and notify your team in Slack when risky records are found. This ensures your CRM stays clean and your sender reputation rema