This workflow follows the Discord → 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": "Deploy Gate",
"nodes": [
{
"parameters": {
"path": "deploy-gate",
"httpMethod": "POST",
"responseMode": "onReceived",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 1.1,
"position": [
0,
0
],
"id": "a1b2c3d4-0001-4000-8000-000000000001",
"name": "Webhook"
},
{
"parameters": {
"jsCode": "const body = $input.first().json.body || {};\nconst service = (body.service || '').trim();\nconst version = (body.version || '').trim();\nconst deployer = (body.deployer || 'unknown').trim();\nconst healthUrl = (body.healthUrl || '').trim();\n\nif (!service) {\n throw new Error('Missing required field: service');\n}\n\nreturn [{\n json: {\n service,\n version,\n deployer,\n healthUrl,\n timestamp: $now.toISO(),\n hour: $now.hour,\n weekday: $now.weekday\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
],
"id": "a1b2c3d4-0002-4000-8000-000000000002",
"name": "Validate Deploy"
},
{
"parameters": {
"operation": "availability",
"calendar": {
"__rl": true,
"mode": "id",
"value": "new17353@gmail.com"
},
"timeMin": "={{ $now }}",
"timeMax": "={{ $now.plus(1, 'hour') }}"
},
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1,
"position": [
440,
-160
],
"id": "a1b2c3d4-0003-4000-8000-000000000003",
"name": "Check Calendar",
"onError": "continueRegularOutput",
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "var items = $input.all();\nvar deployData = $('Validate Deploy').first().json;\nvar firstJson = (items[0] && items[0].json) ? items[0].json : {};\nvar error = firstJson.error;\n\nif (error) {\n return [{ json: { check: 'calendar', passed: true, reason: 'Calendar check failed, assuming clear', service: deployData.service } }];\n}\n\nvar hasBusy = false;\nfor (var i = 0; i < items.length; i++) {\n var j = (items[i] && items[i].json) ? items[i].json : {};\n if (j.status === 'busy' || j.busy === true || j.availability === 'busy') {\n hasBusy = true;\n break;\n }\n}\n\nvar reason = hasBusy ? 'Calendar shows busy in next 60 min' : 'No calendar conflicts in next 60 min';\nreturn [{ json: { check: 'calendar', passed: !hasBusy, reason: reason, service: deployData.service } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
-160
],
"id": "a1b2c3d4-0004-4000-8000-000000000004",
"name": "Parse Calendar"
},
{
"parameters": {
"operation": "getAll",
"returnAll": false,
"limit": 10,
"filters": {},
"options": {}
},
"type": "n8n-nodes-base.gmail",
"typeVersion": 1,
"position": [
440,
0
],
"id": "a1b2c3d4-0005-4000-8000-000000000005",
"name": "Check Emails",
"onError": "continueRegularOutput",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst deployData = $('Validate Deploy').first().json;\nconst error = items[0]?.json?.error;\n\nif (error) {\n return [{ json: { check: 'email', passed: true, reason: 'Gmail check failed, assuming no freeze', service: deployData.service } }];\n}\n\nvar freezeFound = false;\nvar freezeSubject = '';\nvar freezeKeywords = ['deploy freeze', 'code freeze', 'deployment freeze', 'release freeze', 'change freeze'];\n\nfor (var i = 0; i < items.length; i++) {\n var subject = (items[i].json.subject || '').toLowerCase();\n var snippet = (items[i].json.snippet || '').toLowerCase();\n var text = subject + ' ' + snippet;\n for (var k = 0; k < freezeKeywords.length; k++) {\n if (text.indexOf(freezeKeywords[k]) !== -1) {\n freezeFound = true;\n freezeSubject = items[i].json.subject || '';\n break;\n }\n }\n if (freezeFound) break;\n}\n\nvar reason = freezeFound ? 'Freeze email found: ' + freezeSubject : 'No deploy freeze emails found (' + items.length + ' checked)';\nreturn [{ json: { check: 'email', passed: !freezeFound, reason: reason, service: deployData.service } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
0
],
"id": "a1b2c3d4-0006-4000-8000-000000000006",
"name": "Parse Freeze Emails"
},
{
"parameters": {
"url": "={{ $json.healthUrl }}",
"options": {
"timeout": 5000,
"redirect": {
"redirect": {}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
440,
160
],
"id": "a1b2c3d4-0007-4000-8000-000000000007",
"name": "Check Service Health",
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const item = $input.first().json;\nconst deployData = $('Validate Deploy').first().json;\nvar error = item.error;\nvar healthUrl = deployData.healthUrl;\n\nif (!healthUrl) {\n return [{ json: { check: 'health', passed: true, reason: 'No health URL provided, skipping check', service: deployData.service } }];\n}\n\nif (error) {\n var msg = typeof error === 'object' ? (error.message || JSON.stringify(error)) : String(error);\n return [{ json: { check: 'health', passed: false, reason: 'Health check failed: ' + msg, service: deployData.service } }];\n}\n\nreturn [{ json: { check: 'health', passed: true, reason: 'Service responding OK at ' + healthUrl, service: deployData.service } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
160
],
"id": "a1b2c3d4-0008-4000-8000-000000000008",
"name": "Parse Health"
},
{
"parameters": {
"mode": "append",
"numberInputs": 3,
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
880,
0
],
"id": "a1b2c3d4-0009-4000-8000-000000000009",
"name": "Merge Checks"
},
{
"parameters": {
"jsCode": "var checks = $input.all();\nvar deployData = $('Validate Deploy').first().json;\nvar allPassed = true;\nvar failures = [];\nvar warnings = [];\nvar NL = String.fromCharCode(10);\n\nfor (var i = 0; i < checks.length; i++) {\n var c = checks[i].json;\n if (!c.passed) {\n allPassed = false;\n failures.push(c.check + ': ' + c.reason);\n }\n}\n\nvar hour = deployData.hour;\nvar weekday = deployData.weekday;\nvar isWeekend = weekday === 6 || weekday === 7;\nvar isLateNight = hour < 6 || hour >= 22;\n\nif (isWeekend) warnings.push('Weekend deployment');\nif (isLateNight) warnings.push('Late night deployment (hour: ' + hour + ')');\n\nvar decision = 'approve';\nif (failures.length > 0) {\n decision = 'deny';\n} else if (warnings.length > 0) {\n decision = 'review';\n}\n\nvar lines = [];\nlines.push('**Deploy Gate: ' + deployData.service + ' v' + deployData.version + '**');\nlines.push('Deployer: ' + deployData.deployer);\nlines.push('Time: ' + deployData.timestamp);\nlines.push('');\n\nfor (var j = 0; j < checks.length; j++) {\n var ch = checks[j].json;\n var icon = ch.passed ? '\\u2705' : '\\u274c';\n lines.push(icon + ' ' + ch.check + ': ' + ch.reason);\n}\n\nif (warnings.length > 0) {\n lines.push('');\n lines.push('\\u26a0\\ufe0f Warnings:');\n for (var w = 0; w < warnings.length; w++) {\n lines.push(' - ' + warnings[w]);\n }\n}\n\nlines.push('');\nlines.push('Decision: **' + decision.toUpperCase() + '**');\n\nvar report = lines.join(NL);\nreturn [{ json: { decision: decision, report: report, service: deployData.service, version: deployData.version, deployer: deployData.deployer, failureCount: failures.length, warningCount: warnings.length } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1100,
0
],
"id": "a1b2c3d4-0010-4000-8000-000000000010",
"name": "Evaluate Decision"
},
{
"parameters": {
"mode": "rules",
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cond-approve",
"leftValue": "={{ $json.decision }}",
"rightValue": "approve",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputLabel": "Approve"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cond-deny",
"leftValue": "={{ $json.decision }}",
"rightValue": "deny",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputLabel": "Deny"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cond-review",
"leftValue": "={{ $json.decision }}",
"rightValue": "review",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputLabel": "Review"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
1320,
0
],
"id": "a1b2c3d4-0011-4000-8000-000000000011",
"name": "Route Decision"
},
{
"parameters": {
"mode": "manual",
"assignments": {
"assignments": [
{
"id": "set-approve-1",
"name": "emoji",
"value": "=\\u2705",
"type": "string"
},
{
"id": "set-approve-2",
"name": "status",
"value": "APPROVED",
"type": "string"
},
{
"id": "set-approve-3",
"name": "message",
"value": "={{ $json.report }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1540,
-160
],
"id": "a1b2c3d4-0012-4000-8000-000000000012",
"name": "Set Approved"
},
{
"parameters": {
"mode": "manual",
"assignments": {
"assignments": [
{
"id": "set-deny-1",
"name": "emoji",
"value": "=\\u274c",
"type": "string"
},
{
"id": "set-deny-2",
"name": "status",
"value": "DENIED",
"type": "string"
},
{
"id": "set-deny-3",
"name": "message",
"value": "={{ $json.report }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1540,
0
],
"id": "a1b2c3d4-0013-4000-8000-000000000013",
"name": "Set Denied"
},
{
"parameters": {
"mode": "manual",
"assignments": {
"assignments": [
{
"id": "set-review-1",
"name": "emoji",
"value": "=\\u26a0\\ufe0f",
"type": "string"
},
{
"id": "set-review-2",
"name": "status",
"value": "NEEDS REVIEW",
"type": "string"
},
{
"id": "set-review-3",
"name": "message",
"value": "={{ $json.report }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1540,
160
],
"id": "a1b2c3d4-0014-4000-8000-000000000014",
"name": "Set Review"
},
{
"parameters": {
"authentication": "webhook",
"content": "={{ $json.message }}",
"options": {}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1760,
-160
],
"id": "a1b2c3d4-0015-4000-8000-000000000015",
"name": "Discord Approved",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"authentication": "webhook",
"content": "={{ $json.message }}",
"options": {}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1760,
0
],
"id": "a1b2c3d4-0016-4000-8000-000000000016",
"name": "Discord Denied",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"authentication": "webhook",
"content": "={{ $json.message }}",
"options": {}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1760,
160
],
"id": "a1b2c3d4-0017-4000-8000-000000000017",
"name": "Discord Review",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "var data = $input.first().json;\nreturn [{ json: { completedAt: $now.toISO(), service: data.service, version: data.version, deployer: data.deployer, decision: data.decision, status: data.status } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1980,
0
],
"id": "a1b2c3d4-0018-4000-8000-000000000018",
"name": "Log Result"
},
{
"parameters": {},
"type": "n8n-nodes-base.errorTrigger",
"typeVersion": 1,
"position": [
880,
-280
],
"id": "a1b2c3d4-0019-4000-8000-000000000019",
"name": "Error Trigger"
},
{
"parameters": {
"authentication": "webhook",
"content": "=\u274c Deploy Gate Error: {{ $json.execution.error.message }}",
"options": {}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1100,
-280
],
"id": "a1b2c3d4-0020-4000-8000-000000000020",
"name": "Error to Discord",
"credentials": {
"discordWebhookApi": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Validate Deploy",
"type": "main",
"index": 0
}
]
]
},
"Validate Deploy": {
"main": [
[
{
"node": "Check Calendar",
"type": "main",
"index": 0
},
{
"node": "Check Emails",
"type": "main",
"index": 0
},
{
"node": "Check Service Health",
"type": "main",
"index": 0
}
]
]
},
"Check Calendar": {
"main": [
[
{
"node": "Parse Calendar",
"type": "main",
"index": 0
}
]
]
},
"Check Emails": {
"main": [
[
{
"node": "Parse Freeze Emails",
"type": "main",
"index": 0
}
]
]
},
"Check Service Health": {
"main": [
[
{
"node": "Parse Health",
"type": "main",
"index": 0
}
]
]
},
"Parse Calendar": {
"main": [
[
{
"node": "Merge Checks",
"type": "main",
"index": 0
}
]
]
},
"Parse Freeze Emails": {
"main": [
[
{
"node": "Merge Checks",
"type": "main",
"index": 1
}
]
]
},
"Parse Health": {
"main": [
[
{
"node": "Merge Checks",
"type": "main",
"index": 2
}
]
]
},
"Merge Checks": {
"main": [
[
{
"node": "Evaluate Decision",
"type": "main",
"index": 0
}
]
]
},
"Evaluate Decision": {
"main": [
[
{
"node": "Route Decision",
"type": "main",
"index": 0
}
]
]
},
"Route Decision": {
"main": [
[
{
"node": "Set Approved",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Denied",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Review",
"type": "main",
"index": 0
}
]
]
},
"Set Approved": {
"main": [
[
{
"node": "Discord Approved",
"type": "main",
"index": 0
}
]
]
},
"Set Denied": {
"main": [
[
{
"node": "Discord Denied",
"type": "main",
"index": 0
}
]
]
},
"Set Review": {
"main": [
[
{
"node": "Discord Review",
"type": "main",
"index": 0
}
]
]
},
"Discord Approved": {
"main": [
[
{
"node": "Log Result",
"type": "main",
"index": 0
}
]
]
},
"Discord Denied": {
"main": [
[
{
"node": "Log Result",
"type": "main",
"index": 0
}
]
]
},
"Discord Review": {
"main": [
[
{
"node": "Log Result",
"type": "main",
"index": 0
}
]
]
},
"Error Trigger": {
"main": [
[
{
"node": "Error to Discord",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
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.
discordWebhookApigmailOAuth2googleCalendarOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Deploy Gate. Uses googleCalendar, gmail, httpRequest, discord. Webhook trigger; 20 nodes.
Source: https://github.com/new5558/auto-n8n-dev/blob/6a6e822188e2b4f0f7b32e1e5635e75a4dfea036/workflows/deploy-gate.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.
Receive inventory movements via webhook, validate data, update stock levels, and trigger automatic alerts when products need reordering.
Receive support tickets via webhook, categorize by priority, track SLA deadlines, notify your team on Slack, and send confirmation emails to customers.
This workflow is a fully automated AI matte painting generation system for VFX pipelines, designed to convert a single environment prompt into multiple cinematic background variations. It handles gene
Deliver coordinated messages through multiple channels with priority-based formatting, delivery tracking, and compliance logging.
Automate legal appointment booking end-to-end. Clients request a slot via webhook, Google Calendar checks availability, Stripe collects payment, and a confirmed calendar event is created automatically