This workflow corresponds to n8n.io template #12852 — we link there as the canonical source.
This workflow follows the Gmail → Google Sheets 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 →
{
"id": "ZBcrVGqCZTFn34Gjsryiw",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Proactive company budget controller Bexio and GoogleSheets",
"tags": [],
"nodes": [
{
"id": "9d0bc3d2-3f08-4c12-a423-360f8d1d5b0e",
"name": "Set Offset",
"type": "n8n-nodes-base.set",
"position": [
1232,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "21fa8709-a9bc-45d4-8dbb-ad9789367221",
"name": "offset",
"type": "number",
"value": "={{$json[\"new_offset\"] || 0}}"
}
]
}
},
"executeOnce": true,
"typeVersion": 3.4
},
{
"id": "7c5f7c4a-25d9-4098-9804-e767f60c1468",
"name": "Add Offset",
"type": "n8n-nodes-base.set",
"position": [
2000,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c2d5d63e-a2b0-4bad-a9fd-faa3eb65810f",
"name": "new_offset",
"type": "number",
"value": "={{ $('Set Offset').item.json.offset + $('Batch Size').item.json.batchSize}}"
}
]
}
},
"executeOnce": true,
"typeVersion": 3.4
},
{
"id": "bf4aa503-c994-4704-a073-8d8051392328",
"name": "Update Records",
"type": "n8n-nodes-base.googleSheets",
"position": [
1664,
160
],
"parameters": {
"columns": {
"value": {
"ID": "={{ $json.id }}",
"Date": "={{ DateTime.fromISO($json.date).toFormat('yyyy-MM-dd') }}",
"Amount": "={{ $json.amount }}",
"Debit ID": "={{ $json.debit_account_id }}",
"Credit ID": "={{ $json.credit_account_id }}",
"Sync Date": "={{ DateTime.now().toFormat('yyyy-MM-dd') }}",
"Currency ID": "={{ $json.currency_id }}",
"Description": "={{ $json.description }}",
"Date Formated": "={{ DateTime.fromISO($json.date).toFormat('MM yyyy') }}",
"Year Formatted": "={{ DateTime.fromISO($json.date).toFormat('yyyy') }}",
"Conversion factor": "={{ $json.currency_factor }}",
"Amount in basic currency": "={{ $json.base_currency_amount }}"
},
"schema": [
{
"id": "ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Description",
"type": "string",
"display": true,
"required": false,
"displayName": "Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Debit ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Debit ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Credit ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Credit ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Amount",
"type": "string",
"display": true,
"required": false,
"displayName": "Amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Currency ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Currency ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Conversion factor",
"type": "string",
"display": true,
"required": false,
"displayName": "Conversion factor",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Amount in basic currency",
"type": "string",
"display": true,
"required": false,
"displayName": "Amount in basic currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Year Formatted",
"type": "string",
"display": true,
"required": false,
"displayName": "Year Formatted",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date Formated",
"type": "string",
"display": true,
"required": false,
"displayName": "Date Formated",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Sync Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Sync Date",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit#gid=0",
"cachedResultName": "Journal"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit?usp=drivesdk",
"cachedResultName": "Accounting journal (n8n template)"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "e1378ea8-6d9d-4133-89c8-84be927c0845",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
0
],
"parameters": {
"color": 7,
"width": 416,
"height": 464,
"content": "## Initial settings"
},
"typeVersion": 1
},
{
"id": "37b9dee9-5c1b-412d-b1a7-c90ee4bd977d",
"name": "Delay",
"type": "n8n-nodes-base.wait",
"position": [
1840,
160
],
"parameters": {
"amount": 2
},
"executeOnce": true,
"typeVersion": 1.1
},
{
"id": "1348be14-dcb8-45fe-a9f4-84eec811ee73",
"name": "Get Records",
"type": "n8n-nodes-base.httpRequest",
"position": [
1456,
160
],
"parameters": {
"url": "=https://api.bexio.com/3.0/accounting/journal",
"options": {
"response": {
"response": {}
}
},
"sendQuery": true,
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "from",
"value": "2025-01-01"
},
{
"name": "to",
"value": "2025-12-31"
},
{
"name": "=limit",
"value": "=1000"
},
{
"name": "=offset",
"value": "={{ $json.offset }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/json"
}
]
},
"nodeCredentialType": "httpBearerAuth"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 4.2
},
{
"id": "7ba55437-f07f-4532-ac7c-d090b6cfaf8d",
"name": "Batch Size",
"type": "n8n-nodes-base.set",
"position": [
736,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ebdf097d-9e7e-452b-9376-b5a796fd2239",
"name": "batchSize",
"type": "number",
"value": 1000
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3ba9d765-3124-4c7f-9f34-686e60a45b1d",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
0
],
"parameters": {
"color": 7,
"width": 1440,
"height": 464,
"content": "## Update accounting records Bexio to Google Sheets"
},
"typeVersion": 1
},
{
"id": "6ceb6bf9-822a-4b64-8c41-936d3f4a4388",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-208,
0
],
"parameters": {
"width": 640,
"height": 1088,
"content": "**This n8n template allows you to automatically monitor your company's budget by comparing live Bexio accounting data against targets defined in Google Sheets, sending automated weekly email reports.**\n\nFinancial overspending often goes unnoticed until it's too late. This workflow transforms reactive accounting into **proactive management** by automatically calculating monthly actuals and flagging budget overages in real-time, eliminating the need for manual spreadsheet updates.\n\n## How it works\n* Data Extraction: Uses a recursive pagination loop to fetch all journal entries from the Bexio API.\n* Financial Logic: Aggregates costs per account by merging and calculating the delta between Debits and Credits.\n* Budget Comparison: Reads your target thresholds from Google Sheets and compares them against calculated monthly actuals.\n* Automated Reporting: Generates a summary report and sends it via Gmail periodically.\n\n## Setup steps\n- [ ] Credentials: Connect your Bexio (Bearer Token), Google Sheets (OAuth2), and Gmail accounts.\n- [ ] Spreadsheet Config: Clone the template and set you metrics and monthly budgets in the \"Budgets\" sheet. The \"Accounts\" sheet contains sample records. The records will be populated from Bexio automatically. \n- [ ] Gmail: Enter an email address for reporting purposes in the field \"To\" inside Gmail node.\n\n## Customization tips\n* Switch the Gmail node for Slack or Microsoft Teams for instant push notifications.\n* Change schedule to bi-weekly or daily according to your needs. \n\n## Requirements\n* Bexio account with API access.\n* Google Sheets for budget storage.\n* Gmail account for sending reports."
},
"typeVersion": 1
},
{
"id": "b6ed1653-a432-4d09-9ede-51a50fb7c89f",
"name": "Read Budgets",
"type": "n8n-nodes-base.googleSheets",
"position": [
656,
880
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1462771045,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit#gid=1462771045",
"cachedResultName": "Budgets"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit?usp=drivesdk",
"cachedResultName": "Accounting journal (n8n template)"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "735a28d8-530d-4874-9df6-5b1a1ccf803e",
"name": "Get Debits",
"type": "n8n-nodes-base.googleSheets",
"position": [
1200,
1280
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json['Account ID'] }}",
"lookupColumn": "Debit ID"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit#gid=0",
"cachedResultName": "Journal"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit?usp=drivesdk",
"cachedResultName": "Accounting journal (n8n template)"
},
"combineFilters": "OR"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "14df45e7-63d2-49dc-a320-2b29e54a8b23",
"name": "Get Credits",
"type": "n8n-nodes-base.googleSheets",
"position": [
1200,
1456
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json['Account ID'] }}",
"lookupColumn": "Credit ID"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit#gid=0",
"cachedResultName": "Journal"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ZnaXFqOhcrgMptM2K8k-W0VZTxgyL99_D569GiwTZZk/edit?usp=drivesdk",
"cachedResultName": "Accounting journal (n8n template)"
},
"combineFilters": "OR"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7,
"alwaysOutputData": true
},
{
"id": "003f5228-4279-45bb-92fb-4dffcb17bee9",
"name": "Calculate Credits",
"type": "n8n-nodes-base.code",
"position": [
1360,
1280
],
"parameters": {
"jsCode": "// detect year from first item or default to current year\nconst year = items[0]?.json[\"Date Formated\"]?.split(\" \")[1] || new Date().getFullYear();\n\n// initialize 12 months with 0\nconst totals = Object.fromEntries(\n Array.from({ length: 12 }, (_, i) => [\n `${String(i + 1).padStart(2, \"0\")} ${year}`, 0\n ])\n);\n\n// sum amounts if input is not empty\nfor (const { json } of items || []) {\n const key = json[\"Date Formated\"];\n if (key && totals.hasOwnProperty(key)) {\n totals[key] += Number(json[\"Amount in basic currency\"]) || 0;\n }\n}\n\n// return 1 item with all months\nreturn [{ json: Object.fromEntries(\n Object.entries(totals).map(([month, total]) => [month, +total.toFixed(2)])\n) }];\n"
},
"typeVersion": 2
},
{
"id": "216b8051-60c8-4b8a-8ccb-aa73d294d8d0",
"name": "Calculate debit",
"type": "n8n-nodes-base.code",
"position": [
1360,
1456
],
"parameters": {
"jsCode": "// detect year from first item or default to current year\nconst year = items[0]?.json[\"Date Formated\"]?.split(\" \")[1] || new Date().getFullYear();\n\n// initialize 12 months with 0\nconst totals = Object.fromEntries(\n Array.from({ length: 12 }, (_, i) => [\n `${String(i + 1).padStart(2, \"0\")} ${year}`, 0\n ])\n);\n\n// sum amounts if input is not empty\nfor (const { json } of items || []) {\n const key = json[\"Date Formated\"];\n if (key && totals.hasOwnProperty(key)) {\n totals[key] += Number(json[\"Amount in basic currency\"]) || 0;\n }\n}\n\n// return 1 item with all months\nreturn [{ json: Object.fromEntries(\n Object.entries(totals).map(([month, total]) => [month, +total.toFixed(2)])\n) }];\n"
},
"typeVersion": 2
},
{
"id": "5ef10109-0ad8-41aa-aa24-3c5b4bd35af2",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
912,
880
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "0b90b1b0-ff9c-4dec-bb75-7fb5fd2f2ec7",
"name": "Merge Credits/Debits",
"type": "n8n-nodes-base.merge",
"position": [
1568,
1296
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "4d9c877c-8219-4527-b1e1-ccc9d99fb49c",
"name": "Calculate Costs",
"type": "n8n-nodes-base.code",
"position": [
1712,
1296
],
"parameters": {
"jsCode": "const [credit, debit] = items.map(i => i.json);\n\nconst result = Object.fromEntries(\n Object.keys(credit).map(month => [month, +(credit[month] - (debit[month] || 0)).toFixed(2)])\n);\n\nreturn [{ json: result }];\n"
},
"typeVersion": 2
},
{
"id": "a10b7090-106b-4368-87f6-d7c26e492bf9",
"name": "Add Budgets",
"type": "n8n-nodes-base.merge",
"position": [
1904,
912
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "57d20597-f0b1-482e-95f8-6a9e1a9a519d",
"name": "Check Budgets",
"type": "n8n-nodes-base.code",
"position": [
2064,
912
],
"parameters": {
"jsCode": "const actuals = items[1].json;\nconst budget = items[0].json;\n\n// dynamic key from Metric\nconst key = items[0].json.Metric || \"messages\";\n\n// generate messages if actual > budget\nlet result = Object.keys(budget)\n .filter(month => actuals[month] > budget[month])\n .map(month => `Budget exceeded in ${month} - budget: ${budget[month]}, actual: ${actuals[month]}`);\n\n// fallback if empty\nif (result.length === 0) {\n result = [\"All costs within the budget\"];\n}\n\n// return single item with dynamic key\nreturn [{ json: { [key]: result } }];"
},
"typeVersion": 2
},
{
"id": "187500f9-204f-439f-a489-eb74f6ba5ba0",
"name": "Compose Report",
"type": "n8n-nodes-base.code",
"position": [
1184,
544
],
"parameters": {
"jsCode": "const input = items.map(i => i.json);\n\nlet body = \"Budget Report:\\n\\n\";\n\nfor (const section of input) {\n for (const [metric, messages] of Object.entries(section)) {\n body += `${metric}:\\n`;\n for (const msg of messages) {\n body += `- ${msg}\\n`;\n }\n body += \"\\n\"; // add extra line between sections\n }\n}\n\n// return single item with email body\nreturn [{ json: { email_body: body.trim() } }];\n"
},
"typeVersion": 2
},
{
"id": "1f8f1484-d9e0-409b-881d-edbb189246e8",
"name": "Send Report",
"type": "n8n-nodes-base.gmail",
"position": [
1360,
544
],
"parameters": {
"message": "={{ $json.email_body }}",
"options": {
"appendAttribution": false
},
"subject": "=Budget Report {{ $now.format(\"dd/LL/yyyy\") }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "0d8d55ea-7c9c-4765-8c7f-ba70df930756",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
1200
],
"parameters": {
"color": 7,
"width": 1872,
"height": 464,
"content": "## Calculate costs for each period based on accounting records"
},
"typeVersion": 1
},
{
"id": "6e98e233-a25c-498c-848a-954e335ce469",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
480
],
"parameters": {
"color": 7,
"width": 1872,
"height": 272,
"content": "## Send final reports"
},
"typeVersion": 1
},
{
"id": "01b2caf9-8ec9-45a5-bf36-cb86834e71b9",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
784
],
"parameters": {
"color": 7,
"width": 1872,
"height": 384,
"content": "## Compare budgets to actual costs"
},
"typeVersion": 1
},
{
"id": "a823f709-c1ef-45c6-a766-e7d829ddafc5",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
576,
160
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks"
}
]
}
},
"typeVersion": 1.3
},
{
"id": "87f7206e-cfc5-4c2e-b4f5-6d646b830b5f",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-208,
1120
],
"parameters": {
"color": 5,
"width": 640,
"height": 544,
"content": "## Example report\n\nBudget Report:\n\nIT costs:\n- Budget exceeded in 04 2025 - budget: 200, actual: 420\n\n\nRentals:\n- All costs within the budget\n\n\nYour custom metric\n- Report if budget exceeded any month"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "d246032d-d458-4ca2-b58c-84135e775407",
"connections": {
"Delay": {
"main": [
[
{
"node": "Add Offset",
"type": "main",
"index": 0
}
]
]
},
"Add Offset": {
"main": [
[
{
"node": "Set Offset",
"type": "main",
"index": 0
},
{
"node": "Read Budgets",
"type": "main",
"index": 0
}
]
]
},
"Batch Size": {
"main": [
[
{
"node": "Set Offset",
"type": "main",
"index": 0
}
]
]
},
"Get Debits": {
"main": [
[
{
"node": "Calculate Credits",
"type": "main",
"index": 0
}
]
]
},
"Set Offset": {
"main": [
[
{
"node": "Get Records",
"type": "main",
"index": 0
}
]
]
},
"Add Budgets": {
"main": [
[
{
"node": "Check Budgets",
"type": "main",
"index": 0
}
]
]
},
"Get Credits": {
"main": [
[
{
"node": "Calculate debit",
"type": "main",
"index": 0
}
]
]
},
"Get Records": {
"main": [
[
{
"node": "Update Records",
"type": "main",
"index": 0
}
]
]
},
"Read Budgets": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Check Budgets": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Compose Report": {
"main": [
[
{
"node": "Send Report",
"type": "main",
"index": 0
}
]
]
},
"Update Records": {
"main": [
[
{
"node": "Delay",
"type": "main",
"index": 0
}
]
]
},
"Calculate Costs": {
"main": [
[
{
"node": "Add Budgets",
"type": "main",
"index": 1
}
]
]
},
"Calculate debit": {
"main": [
[
{
"node": "Merge Credits/Debits",
"type": "main",
"index": 1
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Compose Report",
"type": "main",
"index": 0
}
],
[
{
"node": "Add Budgets",
"type": "main",
"index": 0
},
{
"node": "Get Debits",
"type": "main",
"index": 0
},
{
"node": "Get Credits",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Batch Size",
"type": "main",
"index": 0
}
]
]
},
"Calculate Credits": {
"main": [
[
{
"node": "Merge Credits/Debits",
"type": "main",
"index": 0
}
]
]
},
"Merge Credits/Debits": {
"main": [
[
{
"node": "Calculate Costs",
"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.
gmailOAuth2googleSheetsOAuth2ApihttpBearerAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n template allows you to automatically monitor your company's budget by comparing live Bexio accounting data against targets defined in Google Sheets, sending automated weekly email reports. It also exports your financial data from Bexio into a flexible spreadsheet…
Source: https://n8n.io/workflows/12852/ — 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.
Automatically extract structured information from emails using AI-powered document analysis. This workflow processes emails from specified domains, classifies them by type, and extracts structured dat
What This Flow Does
This workflow streamlines HR outreach by fetching contact data, validating emails, enforcing daily sending limits, and sending personalized emails with attachments, all while logging activity. Read HR
Activate this workflow once and every Friday at 5PM it automatically pulls your week's meeting data from Fireflies, calculates seven metrics, and emails a formatted report to your manager inbox. It tr
This workflow automatically monitors solar energy production every 2 hours by fetching data from the Energidataservice API. If the energy output falls below a predefined threshold, it instantly notifi