This workflow follows the Gmail → HTTP Request 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": "Pinapp \u2014 Diagnostic Lead Pipeline",
"meta": {
"description": "Importer dans n8n Cloud. Webhook POST JSON (formulaire pinapp.fr). Variables : NOTION_DB_LEADS_ID, SLACK_WEBHOOK_URL. Credentials : Notion OAuth2, Gmail (ou SMTP). Apr\u00e8s activation, coller l\u2019URL webhook dans index.html (PINAPP_WEBHOOK_URL)."
},
"nodes": [
{
"id": "wh-diag",
"name": "Webhook Diagnostic",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
],
"parameters": {
"httpMethod": "POST",
"path": "pinapp-diagnostic",
"responseMode": "responseNode",
"options": {}
}
},
{
"id": "code-validate",
"name": "Validate & Score",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
300
],
"parameters": {
"jsCode": "const item = $input.first().json;\nconst data = item.body && typeof item.body === 'object' ? item.body : item;\n\nif (data.website && String(data.website).trim() !== '') {\n return [{ json: { _phase: 'spam', _received_at: new Date().toISOString() } }];\n}\n\nconst required = ['prenom', 'nom', 'email', 'secteur', 'budget', 'description', 'rgpd'];\nconst missing = required.filter((f) => !data[f] || (typeof data[f] === 'string' && !String(data[f]).trim()));\nif (missing.length) {\n return [{ json: { _phase: 'invalid', _error: 'missing_fields', _missing: missing } }];\n}\n\nconst email = String(data.email || '');\nif (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n return [{ json: { _phase: 'invalid', _error: 'invalid_email' } }];\n}\n\nconst projets = Array.isArray(data.projet) ? data.projet : data.projet ? [data.projet] : [];\nif (!projets.length) {\n return [{ json: { _phase: 'invalid', _error: 'missing_projet' } }];\n}\n\nlet score = 0;\nconst budget = String(data.budget || '');\nif (/gt25k/.test(budget)) score += 40;\nelse if (/10k-25k/.test(budget)) score += 30;\nelse if (/5k-10k/.test(budget)) score += 20;\nelse if (/2k-5k/.test(budget)) score += 10;\n\nif (data.urgence === 'asap') score += 25;\nelse if (data.urgence === '1-3m') score += 15;\nelse if (data.urgence === '3-6m') score += 5;\n\nif (projets.length >= 3) score += 25;\nelse if (projets.length === 2) score += 15;\nelse if (projets.length === 1) score += 5;\n\nif (data.description && String(data.description).length > 300) score += 10;\nif (data.entreprise) score += 5;\nif (data.telephone) score += 5;\nif (data.site_actuel) score += 5;\n\nlet tier = 'cold';\nif (score >= 75) tier = 'hot';\nelse if (score >= 45) tier = 'warm';\n\nconst slackEmoji = tier === 'hot' ? '\ud83d\udd25' : tier === 'warm' ? '\u26a1' : '\u2744\ufe0f';\n\nconst payload = {\n ...data,\n projet: projets,\n _phase: 'lead',\n _server_score: score,\n _tier: tier,\n _projets_str: projets.join(', '),\n _received_at: new Date().toISOString(),\n _slack_emoji: slackEmoji,\n};\n\nreturn [{ json: payload }];"
}
},
{
"id": "if-spam",
"name": "Is spam?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
720,
300
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "spam",
"leftValue": "={{ $json._phase }}",
"rightValue": "spam",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
}
}
},
{
"id": "if-invalid",
"name": "Is invalid?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
960,
420
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "inv",
"leftValue": "={{ $json._phase }}",
"rightValue": "invalid",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
}
}
},
{
"id": "notion-lead",
"name": "Create Notion Lead",
"type": "n8n-nodes-base.notion",
"typeVersion": 2,
"position": [
1180,
200
],
"parameters": {
"resource": "databasePage",
"operation": "create",
"databaseId": "={{ $env.NOTION_DB_LEADS_ID }}",
"title": "={{ $json.prenom }} {{ $json.nom }} \u2014 {{ $json.secteur }}",
"propertiesUi": {
"propertyValues": [
{
"key": "Email|email",
"emailValue": "={{ $json.email }}"
},
{
"key": "T\u00e9l\u00e9phone|phone_number",
"phoneValue": "={{ $json.telephone || '' }}"
},
{
"key": "Entreprise|rich_text",
"textContent": "={{ $json.entreprise || '' }}"
},
{
"key": "Secteur|select",
"selectValue": "={{ $json.secteur }}"
},
{
"key": "Projets|multi_select",
"multiSelectValue": "={{ $json._projets_str }}"
},
{
"key": "Budget|select",
"selectValue": "={{ $json.budget }}"
},
{
"key": "Urgence|select",
"selectValue": "={{ $json.urgence || 'non-precise' }}"
},
{
"key": "Score|number",
"numberValue": "={{ $json._server_score }}"
},
{
"key": "Tier|select",
"selectValue": "={{ $json._tier }}"
},
{
"key": "Source|select",
"selectValue": "={{ $json.source || 'non-precise' }}"
},
{
"key": "Description|rich_text",
"textContent": "={{ $json.description }}"
},
{
"key": "Statut|select",
"selectValue": "Nouveau"
}
]
},
"options": {}
},
"notesInFlow": true,
"notes": "Mapper les propertyValues aux noms/types exacts de la base Notion (voir docs/LEAD_FLOW.md)."
},
{
"id": "gmail-confirm",
"name": "Email confirmation prospect",
"type": "n8n-nodes-base.gmail",
"typeVersion": 1,
"position": [
1400,
200
],
"parameters": {
"operation": "send",
"toList": "={{ $('Validate & Score').item.json.email }}",
"subject": "=Bien re\u00e7u, {{ $('Validate & Score').item.json.prenom }} \u2014 on revient sous 24h \u00b7 Pinapp",
"message": "=Bonjour {{ $('Validate & Score').item.json.prenom }},\n\nNous avons bien re\u00e7u votre demande. Nous revenons vers vous sous 24h ouvr\u00e9es \u00e0 {{ $('Validate & Score').item.json.email }}.\n\nR\u00e9cap : secteur {{ $('Validate & Score').item.json.secteur }} \u00b7 projets {{ $('Validate & Score').item.json._projets_str }} \u00b7 budget {{ $('Validate & Score').item.json.budget }}.\n\nEn attendant : https://pinapp.fr/realisations/ et https://pinapp.fr/#formations\n\nLauralie & Micha\u00ebl \u2014 Pinapp\ncontact@pinapp.fr"
}
},
{
"id": "http-slack",
"name": "Slack Notif",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1620,
200
],
"parameters": {
"method": "POST",
"url": "={{ $env.SLACK_WEBHOOK_URL }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ text: $('Validate & Score').item.json._slack_emoji + ' Nouveau lead Pinapp \u2014 ' + $('Validate & Score').item.json._tier + ' (' + $('Validate & Score').item.json._server_score + '/100)\\n' + $('Validate & Score').item.json.prenom + ' ' + $('Validate & Score').item.json.nom + ' \u00b7 ' + $('Validate & Score').item.json.email }) }}",
"options": {
"timeout": 10000
}
}
},
{
"id": "resp-ok",
"name": "Webhook OK",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1840,
200
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, message: 'Re\u00e7u, on revient sous 24h', reference: $('Validate & Score').item.json._received_at }) }}"
}
},
{
"id": "resp-spam",
"name": "Webhook OK silent",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
960,
120
],
"parameters": {
"respondWith": "json",
"responseBody": "={\"success\":true,\"message\":\"Re\u00e7u\"}"
}
},
{
"id": "resp-err",
"name": "Webhook Error",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1180,
520
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: false, error: $json._error || 'invalid_data' }) }}",
"options": {
"responseCode": 400
}
}
}
],
"connections": {
"Webhook Diagnostic": {
"main": [
[
{
"node": "Validate & Score",
"type": "main",
"index": 0
}
]
]
},
"Validate & Score": {
"main": [
[
{
"node": "Is spam?",
"type": "main",
"index": 0
}
]
]
},
"Is spam?": {
"main": [
[
{
"node": "Webhook OK silent",
"type": "main",
"index": 0
}
],
[
{
"node": "Is invalid?",
"type": "main",
"index": 0
}
]
]
},
"Is invalid?": {
"main": [
[
{
"node": "Webhook Error",
"type": "main",
"index": 0
}
],
[
{
"node": "Create Notion Lead",
"type": "main",
"index": 0
}
]
]
},
"Create Notion Lead": {
"main": [
[
{
"node": "Email confirmation prospect",
"type": "main",
"index": 0
}
]
]
},
"Email confirmation prospect": {
"main": [
[
{
"node": "Slack Notif",
"type": "main",
"index": 0
}
]
]
},
"Slack Notif": {
"main": [
[
{
"node": "Webhook OK",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Pinapp — Diagnostic Lead Pipeline. Uses notion, gmail, httpRequest. Webhook trigger; 10 nodes.
Source: https://github.com/lauraliedaguzay-lang/pinapp-site/blob/572daf3ea3ae48e0b147a5156f120d5e42b6255b/n8n-workflows/diagnostic-pinapp.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.
This workflow automates bulk email campaigns with built-in validation, deliverability protection, and smart send-time optimization.
This workflow acts as an instant SDR that replies to new inbound leads across multiple channels in real time. It first captures and normalizes all incoming lead data into a unified structure. The work
A comprehensive n8n workflow template for streamlining influencer application processing with real-time social media data validation, intelligent scoring algorithms, and automated onboarding workflows
Cana V2 Lead Processor. Uses httpRequest, gmail, dataTable. Webhook trigger; 20 nodes.
AI Lead Qualification & Follow-Up. Uses httpRequest, slack, googleSheets, gmail. Webhook trigger; 18 nodes.