This workflow follows the Emailsend → 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": "Flow 5 - Mini AI Summary",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 2
}
]
}
},
"name": "Cron Trigger (Every 2 minutes)",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"url": "={{$env.BACKEND_API_URL}}/api/forecasts/latest",
"authentication": "none",
"options": {}
},
"name": "HTTP: Get Forecast Logs",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
460,
300
]
},
{
"parameters": {
"url": "={{$env.BACKEND_API_URL}}/api/tasks?status=in_progress",
"authentication": "none",
"options": {}
},
"name": "HTTP: Get Tasks",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
680,
300
]
},
{
"parameters": {
"functionCode": "// Build Summary Prompt\nconst forecasts = $node['HTTP: Get Forecast Logs'].json.forecasts || [];\nconst tasks = $input.first().json.tasks || [];\n\nconst highRiskForecasts = forecasts.filter(f => \n f.risk_level === 'high' || f.risk_level === 'critical'\n);\n\nconst inProgressTasks = tasks.filter(t => t.status === 'in_progress');\nconst doneTasks = tasks.filter(t => t.status === 'done');\n\nconst prompt = `T\u1ea1o b\u00e1o c\u00e1o t\u00f3m t\u1eaft ng\u1eafn g\u1ecdn (3-5 c\u00e2u) b\u1eb1ng ti\u1ebfng Vi\u1ec7t v\u1ec1 t\u00ecnh h\u00ecnh d\u1ef1 \u00e1n:\n\nD\u1ef1 \u0111o\u00e1n r\u1ee7i ro: ${forecasts.length} tasks \u0111\u01b0\u1ee3c ph\u00e2n t\u00edch\nTasks \u0111ang th\u1ef1c hi\u1ec7n: ${inProgressTasks.length} tasks\n\nChi ti\u1ebft:\n- Tasks c\u00f3 r\u1ee7i ro cao: ${highRiskForecasts.length}\n- Tasks \u0111ang th\u1ef1c hi\u1ec7n: ${inProgressTasks.length}\n- Tasks ho\u00e0n th\u00e0nh: ${doneTasks.length}\n- T\u1ed5ng tasks: ${tasks.length}\n\nFormat: V\u0103n b\u1ea3n s\u00fac t\u00edch, d\u1ec5 hi\u1ec3u, highlight \u0111i\u1ec3m quan tr\u1ecdng. S\u1eed d\u1ee5ng emoji n\u1ebfu ph\u00f9 h\u1ee3p.`;\n\nreturn {\n json: {\n prompt: prompt,\n stats: {\n total_forecasts: forecasts.length,\n high_risk_count: highRiskForecasts.length,\n in_progress_count: inProgressTasks.length,\n done_count: doneTasks.length,\n total_tasks: tasks.length\n }\n }\n};"
},
"name": "Function: Build Summary Prompt",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
900,
300
]
},
{
"parameters": {
"url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key={{$env.GEMINI_API_KEY}}",
"authentication": "none",
"method": "POST",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "contents",
"value": "=[{\"parts\":[{\"text\":\"{{$json.prompt}}\"}]}]"
}
]
},
"options": {}
},
"name": "HTTP: Gemini API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1120,
300
]
},
{
"parameters": {
"functionCode": "// Parse Summary\nconst response = $input.first().json;\nlet summary = 'Kh\u00f4ng th\u1ec3 t\u1ea1o b\u00e1o c\u00e1o t\u00f3m t\u1eaft';\n\ntry {\n const text = response.candidates[0].content.parts[0].text;\n summary = text.trim();\n} catch (error) {\n console.log('Error parsing AI response:', error);\n}\n\nconst stats = $node['Function: Build Summary Prompt'].json.stats;\n\nreturn {\n json: {\n summary: summary,\n stats: stats,\n generated_at: new Date().toISOString()\n }\n};"
},
"name": "Function: Parse Summary",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
1340,
300
]
},
{
"parameters": {
"fromEmail": "={{$env.EMAIL_FROM}}",
"toEmail": "={{$env.ADMIN_EMAIL}}",
"subject": "\ud83d\udcca B\u00e1o c\u00e1o t\u00f3m t\u1eaft h\u1ec7 th\u1ed1ng AI Deadline",
"emailType": "html",
"message": "=<html>\n<head>\n <style>\n body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }\n .container { max-width: 600px; margin: 0 auto; padding: 20px; }\n .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0; }\n .content { background: #f9f9f9; padding: 30px; }\n .stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin: 20px 0; }\n .stat-card { background: white; padding: 15px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }\n .stat-value { font-size: 32px; font-weight: bold; color: #667eea; }\n .stat-label { font-size: 14px; color: #666; margin-top: 5px; }\n .summary-box { background: white; padding: 20px; border-radius: 8px; margin-top: 20px; border-left: 4px solid #667eea; }\n .footer { text-align: center; padding: 20px; color: #666; font-size: 12px; border-radius: 0 0 10px 10px; background: #f9f9f9; }\n </style>\n</head>\n<body>\n <div class='container'>\n <div class='header'>\n <h1>\ud83d\udcca B\u00e1o c\u00e1o T\u00f3m t\u1eaft H\u1ec7 th\u1ed1ng</h1>\n <p>AI Deadline Forecasting Agent</p>\n </div>\n <div class='content'>\n <h2>Th\u1ed1ng k\u00ea T\u1ed5ng quan</h2>\n <div class='stats'>\n <div class='stat-card'>\n <div class='stat-value'>{{$json.stats.total_tasks}}</div>\n <div class='stat-label'>T\u1ed5ng Tasks</div>\n </div>\n <div class='stat-card'>\n <div class='stat-value'>{{$json.stats.in_progress_count}}</div>\n <div class='stat-label'>\u0110ang th\u1ef1c hi\u1ec7n</div>\n </div>\n <div class='stat-card'>\n <div class='stat-value'>{{$json.stats.done_count}}</div>\n <div class='stat-label'>Ho\u00e0n th\u00e0nh</div>\n </div>\n <div class='stat-card'>\n <div class='stat-value' style='color: #f56565;'>{{$json.stats.high_risk_count}}</div>\n <div class='stat-label'>R\u1ee7i ro cao</div>\n </div>\n </div>\n \n <div class='summary-box'>\n <h3>\ud83e\udd16 Ph\u00e2n t\u00edch t\u1eeb AI</h3>\n <p style='white-space: pre-wrap;'>{{$json.summary}}</p>\n </div>\n \n <p style='margin-top: 20px; color: #666; font-size: 12px;'>\n B\u00e1o c\u00e1o \u0111\u01b0\u1ee3c t\u1ea1o t\u1ef1 \u0111\u1ed9ng v\u00e0o: {{$json.generated_at}}\n </p>\n </div>\n <div class='footer'>\n <p>\u00a9 2024 AI Deadline Forecasting Agent</p>\n <p>Email n\u00e0y \u0111\u01b0\u1ee3c g\u1eedi t\u1ef1 \u0111\u1ed9ng t\u1eeb h\u1ec7 th\u1ed1ng n8n workflow</p>\n </div>\n </div>\n</body>\n</html>",
"options": {}
},
"name": "Send Email: Weekly Summary",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
1560,
300
],
"credentials": {
"smtp": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "={{$env.BACKEND_API_URL}}/api/webhooks/n8n/automation-log",
"authentication": "none",
"method": "POST",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "workflow_name",
"value": "Mini AI Summary"
},
{
"name": "status",
"value": "success"
},
{
"name": "input_data",
"value": "={{JSON.stringify($json.stats)}}"
},
{
"name": "output_data",
"value": "={{JSON.stringify({summary: $json.summary})}}"
}
]
},
"options": {}
},
"name": "HTTP: Log to Backend",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1780,
300
]
}
],
"connections": {
"Cron Trigger (Every 2 minutes)": {
"main": [
[
{
"node": "HTTP: Get Forecast Logs",
"type": "main",
"index": 0
}
]
]
},
"HTTP: Get Forecast Logs": {
"main": [
[
{
"node": "HTTP: Get Tasks",
"type": "main",
"index": 0
}
]
]
},
"HTTP: Get Tasks": {
"main": [
[
{
"node": "Function: Build Summary Prompt",
"type": "main",
"index": 0
}
]
]
},
"Function: Build Summary Prompt": {
"main": [
[
{
"node": "HTTP: Gemini API",
"type": "main",
"index": 0
}
]
]
},
"HTTP: Gemini API": {
"main": [
[
{
"node": "Function: Parse Summary",
"type": "main",
"index": 0
}
]
]
},
"Function: Parse Summary": {
"main": [
[
{
"node": "Send Email: Weekly Summary",
"type": "main",
"index": 0
}
]
]
},
"Send Email: Weekly Summary": {
"main": [
[
{
"node": "HTTP: Log to Backend",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "5",
"id": "5",
"tags": []
}
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.
smtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Flow 5 - Mini AI Summary. Uses httpRequest, emailSend. Scheduled trigger; 8 nodes.
Source: https://github.com/thanhtth1024/testsp/blob/29a6ff26307fe4ecb130e3165cfa1a0c1aeb988d/n8n-workflows/flow5-ai-summary.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.
Birthday Automation - Production (Fixed). Uses stopAndError, httpRequest, emailSend, bannerbear. Scheduled trigger; 86 nodes.
This workflow is an improvement of this workflow by Greg Brzezinka.
N8N-Self-Updater. Uses ssh, emailSend, httpRequest. Scheduled trigger; 27 nodes.
> An automated n8n workflow originally built for DigitalOcean-based n8n deployments, but fully compatible with any VPS or cloud hosting (e.g., AWS, Google Cloud, Hetzner, Linode, etc.) where n8n ru
What if you could spot a major sales problem—or a winning campaign—the very next morning, instead of weeks later? Imagine receiving a beautiful, data-rich alert directly in your inbox the moment your