This workflow follows the HTTP Request → 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 →
{
"nodes": [
{
"id": "sticky-ask",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-920,
-200
],
"parameters": {
"content": "## The ask\n- Job closes in the field software, the customer gets the rating text within a minute",
"height": 140,
"width": 440,
"color": 4
}
},
{
"id": "sticky-routing",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-920,
380
],
"parameters": {
"content": "## The routing\n- A 4 or 5 gets the Google link, then a referral ask three days later\n- A 1 to 3 pings #reviews and puts a one-hour call task on Dana's list",
"height": 160,
"width": 440,
"color": 5
}
},
{
"id": "wh-job-done",
"name": "The field software says a job is done",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-880,
0
],
"parameters": {
"httpMethod": "POST",
"path": "demo/job-completed",
"responseMode": "responseNode",
"options": {}
}
},
{
"id": "code-job-tidy",
"name": "Tidy up the job details",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-660,
0
],
"parameters": {
"jsCode": "// Field software webhooks arrive flat or wrapped in a data object.\n// Check both shapes for the customer and the job.\nconst outer = $json.body && typeof $json.body === 'object' ? $json.body : $json;\nconst raw = outer.data && typeof outer.data === 'object' ? outer.data : outer;\n\nconst pick = (...keys) => {\n for (const k of keys) {\n const v = raw[k];\n if (v !== undefined && v !== null && String(v).trim() !== '') return String(v).trim();\n }\n return '';\n};\n\nconst name = pick('customerName', 'customer_name', 'name', 'customer') || 'there';\n\nlet phone = pick('customerPhone', 'customer_phone', 'phone', 'phoneNumber').replace(/[^\\d+]/g, '');\nif (phone && !phone.startsWith('+')) {\n phone = phone.length === 10 ? `+1${phone}` : `+${phone}`;\n}\n\nconst jobType = pick('jobType', 'job_type', 'serviceType', 'service') || 'service visit';\nconst techName = pick('techName', 'tech_name', 'technician', 'tech') || 'our tech';\n\nreturn {\n name,\n firstName: name.split(' ')[0],\n phone,\n jobType,\n techName,\n};"
}
},
{
"id": "ghl-upsert",
"name": "Save the customer in GoHighLevel",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-440,
0
],
"parameters": {
"method": "POST",
"url": "https://services.leadconnectorhq.com/contacts/upsert",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ locationId: 'bsHomeSvcDemo01', name: $json.name, phone: $json.phone, tags: ['survey-sent'] }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "sms-survey",
"name": "Ask the customer how we did",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-220,
0
],
"parameters": {
"method": "POST",
"url": "https://services.leadconnectorhq.com/conversations/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ type: 'SMS', contactId: $json.contact?.id || $json.id, message: 'Hey ' + $('Tidy up the job details').item.json.firstName + ', this is Blue Summit. Thanks for having ' + $('Tidy up the job details').item.json.techName + ' out today. Quick one: 1 to 5, how did we do?' }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "respond-job",
"name": "Tell the field software we got it",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
0,
0
],
"parameters": {
"respondWith": "json",
"responseBody": "{\n \"status\": \"received\"\n}",
"options": {}
}
},
{
"id": "wh-survey-reply",
"name": "The customer texts back their rating",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-880,
600
],
"parameters": {
"httpMethod": "POST",
"path": "demo/survey-reply",
"responseMode": "responseNode",
"options": {}
}
},
{
"id": "code-read-rating",
"name": "Read the rating from their reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-660,
600
],
"parameters": {
"jsCode": "// The reply can arrive flat or wrapped in a data object.\nconst outer = $json.body && typeof $json.body === 'object' ? $json.body : $json;\nconst raw = outer.data && typeof outer.data === 'object' ? outer.data : outer;\n\nconst pick = (...keys) => {\n for (const k of keys) {\n const v = raw[k];\n if (v !== undefined && v !== null && String(v).trim() !== '') return String(v).trim();\n }\n return '';\n};\n\nconst message = pick('message', 'text', 'Body', 'messageBody', 'body');\n\n// Take the first 1-5 digit anywhere in the reply, so \"5!\" and\n// \"I'd say 4\" both count. No digit means a person should look at it.\nconst match = String(message).match(/[1-5]/);\nconst rating = match ? parseInt(match[0], 10) : 0;\n\nlet phone = pick('phone', 'from', 'From', 'contactPhone').replace(/[^\\d+]/g, '');\nif (phone && !phone.startsWith('+')) {\n phone = phone.length === 10 ? `+1${phone}` : `+${phone}`;\n}\n\nconst contactId = pick('contactId', 'contact_id', 'id');\n\nreturn { rating, phone, contactId, message };"
}
},
{
"id": "respond-reply",
"name": "Confirm we got the reply",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
-440,
600
],
"parameters": {
"respondWith": "json",
"responseBody": "{\n \"status\": \"received\"\n}",
"options": {}
}
},
{
"id": "switch-rating",
"name": "How did they rate us?",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.4,
"position": [
-220,
600
],
"parameters": {
"mode": "rules",
"rules": {
"values": [
{
"outputKey": "Loved it",
"renameOutput": true,
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "rating-high",
"leftValue": "={{ $json.rating }}",
"rightValue": 4,
"operator": {
"type": "number",
"operation": "gte"
}
}
]
}
},
{
"outputKey": "Not happy",
"renameOutput": true,
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "rating-low-floor",
"leftValue": "={{ $json.rating }}",
"rightValue": 1,
"operator": {
"type": "number",
"operation": "gte"
}
},
{
"id": "rating-low-ceiling",
"leftValue": "={{ $json.rating }}",
"rightValue": 3,
"operator": {
"type": "number",
"operation": "lte"
}
}
]
}
},
{
"outputKey": "No rating",
"renameOutput": true,
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "rating-missing",
"leftValue": "={{ $json.rating }}",
"rightValue": 0,
"operator": {
"type": "number",
"operation": "equals"
}
}
]
}
}
]
},
"options": {}
}
},
{
"id": "sms-review-link",
"name": "Text them the Google review link",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
400
],
"parameters": {
"method": "POST",
"url": "https://services.leadconnectorhq.com/conversations/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ type: 'SMS', contactId: $('Read the rating from their reply').item.json.contactId, message: 'Glad to hear it, thanks. If you have a minute, a quick Google review goes a long way for us: https://blue-summit.example.com/review' }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "tag-happy",
"name": "Mark them as a happy customer",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
220,
400
],
"parameters": {
"method": "POST",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ tags: ['happy-customer'] }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "wait-3-days",
"name": "Wait 3 days",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
440,
400
],
"parameters": {
"amount": 3,
"unit": "days"
}
},
{
"id": "sms-referral",
"name": "Ask them to send a friend our way",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
660,
400
],
"parameters": {
"method": "POST",
"url": "https://services.leadconnectorhq.com/conversations/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ type: 'SMS', contactId: $('Read the rating from their reply').item.json.contactId, message: 'Hey, Blue Summit here. If you know anyone who needs their AC or plumbing looked at, send them our way. We take great care of referrals.' }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "tag-referral",
"name": "Note that we asked for a referral",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
880,
400
],
"parameters": {
"method": "POST",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ tags: ['referral-asked'] }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "tag-recovery",
"name": "Flag them for a recovery call",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
600
],
"parameters": {
"method": "POST",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ tags: ['unhappy-recovery'] }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "slack-unhappy",
"name": "Tell the team in #reviews",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.3,
"position": [
220,
600
],
"parameters": {
"resource": "message",
"operation": "post",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "name",
"value": "#reviews"
},
"text": "=Low score: {{ $('Read the rating from their reply').item.json.phone }} rated their job {{ $('Read the rating from their reply').item.json.rating }}/5. Their words: \"{{ $('Read the rating from their reply').item.json.message }}\". Dana has a task to call within the hour.",
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"id": "task-dana",
"name": "Put a call task on Dana's list",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
440,
600
],
"parameters": {
"method": "POST",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tasks",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ title: 'Call them today before this becomes a 1-star review', body: 'Rated the job ' + $('Read the rating from their reply').item.json.rating + '/5. Their words: ' + $('Read the rating from their reply').item.json.message + '. Phone: ' + $('Read the rating from their reply').item.json.phone, dueDate: new Date(Date.now() + 60 * 60 * 1000).toISOString(), completed: false }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "tag-human",
"name": "Mark this reply for a human",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
820
],
"parameters": {
"method": "POST",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $('Read the rating from their reply').item.json.contactId }}/tags",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Version",
"value": "2021-07-28"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ tags: ['needs-a-human'] }) }}",
"options": {}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"id": "slack-human",
"name": "Send their message to #reviews",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.3,
"position": [
220,
820
],
"parameters": {
"resource": "message",
"operation": "post",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "name",
"value": "#reviews"
},
"text": "=Survey reply we could not score, from {{ $('Read the rating from their reply').item.json.phone }}: \"{{ $('Read the rating from their reply').item.json.message }}\". Someone should read it and reply.",
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
}
],
"connections": {
"The field software says a job is done": {
"main": [
[
{
"node": "Tidy up the job details",
"type": "main",
"index": 0
}
]
]
},
"Tidy up the job details": {
"main": [
[
{
"node": "Save the customer in GoHighLevel",
"type": "main",
"index": 0
}
]
]
},
"Save the customer in GoHighLevel": {
"main": [
[
{
"node": "Ask the customer how we did",
"type": "main",
"index": 0
}
]
]
},
"Ask the customer how we did": {
"main": [
[
{
"node": "Tell the field software we got it",
"type": "main",
"index": 0
}
]
]
},
"The customer texts back their rating": {
"main": [
[
{
"node": "Read the rating from their reply",
"type": "main",
"index": 0
}
]
]
},
"Read the rating from their reply": {
"main": [
[
{
"node": "Confirm we got the reply",
"type": "main",
"index": 0
}
]
]
},
"Confirm we got the reply": {
"main": [
[
{
"node": "How did they rate us?",
"type": "main",
"index": 0
}
]
]
},
"How did they rate us?": {
"main": [
[
{
"node": "Text them the Google review link",
"type": "main",
"index": 0
}
],
[
{
"node": "Flag them for a recovery call",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark this reply for a human",
"type": "main",
"index": 0
}
]
]
},
"Text them the Google review link": {
"main": [
[
{
"node": "Mark them as a happy customer",
"type": "main",
"index": 0
}
]
]
},
"Mark them as a happy customer": {
"main": [
[
{
"node": "Wait 3 days",
"type": "main",
"index": 0
}
]
]
},
"Wait 3 days": {
"main": [
[
{
"node": "Ask them to send a friend our way",
"type": "main",
"index": 0
}
]
]
},
"Ask them to send a friend our way": {
"main": [
[
{
"node": "Note that we asked for a referral",
"type": "main",
"index": 0
}
]
]
},
"Flag them for a recovery call": {
"main": [
[
{
"node": "Tell the team in #reviews",
"type": "main",
"index": 0
}
]
]
},
"Tell the team in #reviews": {
"main": [
[
{
"node": "Put a call task on Dana's list",
"type": "main",
"index": 0
}
]
]
},
"Mark this reply for a human": {
"main": [
[
{
"node": "Send their message to #reviews",
"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.
httpHeaderAuthslackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Review-Reputation-Engine. Uses httpRequest, slack. Webhook trigger; 21 nodes.
Source: https://github.com/mcruz1799/automation-examples/blob/main/claude-code/02-automation-file-factory/skills/n8n/section-templates/review-reputation-engine.json — 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.
HR teams, IT Operations, and System Administrators managing employee onboarding at scale. It’s perfect if you use Odoo 18 to trigger account requests and need Redmine + GitLab accounts created instant
This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS
Backbrief: transcripts (Zoom webhook -> Slack + vault). Uses httpRequest, slack. Webhook trigger; 52 nodes.
This workflow automates end-to-end research analysis by coordinating multiple AI models—including NVIDIA NIM (Llama), OpenAI GPT-4, and Claude to analyze uploaded documents, extract insights, and gene
Are you tired of the repetitive dance between git push, creating a pull request in GitHub, updating the corresponding task in JIRA, and then manually notifying your team in Slack, or Notion?