{
  "id": "EeqqXkRfJ6ADiRgm",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AWS Azure GCP Multi-Cloud Cost Monitoring & Alerts for Budget Control",
  "tags": [],
  "nodes": [
    {
      "id": "b172287e-8522-4204-af8c-a85554e1b9f8",
      "name": "Cron Trigger",
      "type": "n8n-nodes-base.cron",
      "position": [
        140,
        -180
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9a9bbc21-a699-499e-8c49-1e93ae8304ff",
      "name": "AWS Billing Fetch",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        360,
        -380
      ],
      "parameters": {
        "url": "https://ce.us-east-1.amazonaws.com/",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": []
        },
        "genericAuthType": "httpBasicAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Amz-Target",
              "value": "AWSInsightsIndexService.GetCostAndUsage"
            },
            {
              "name": "Content-Type",
              "value": "application/x-amz-json-1.1"
            }
          ]
        }
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "df146231-83a9-4a21-abcd-d614aeed73d2",
      "name": "Azure Billing Fetch",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        360,
        -180
      ],
      "parameters": {
        "url": "https://management.azure.com/subscriptions/{{ $vars.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CostManagement/query?api-version=2021-10-01",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "genericAuthType": "oAuth1Api",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "oAuth1Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "cc6d124d-c8fe-4da7-ab36-46d5f4d896bf",
      "name": "GCP Billing Fetch",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        360,
        20
      ],
      "parameters": {
        "url": "https://cloudbilling.googleapis.com/v1/billingAccounts/{{ $vars.GCP_BILLING_ACCOUNT_ID }}/services",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth1Api",
        "queryParameters": {
          "parameters": [
            {
              "name": "filter",
              "value": "usage_start_time >= \"{{ $now.minus({hours: 1}).toISO() }}\" AND usage_start_time < \"{{ $now.toISO() }}\""
            }
          ]
        }
      },
      "credentials": {
        "oAuth1Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "51f29b8b-cbc0-41e4-8116-1768cc411073",
      "name": "Data Parser",
      "type": "n8n-nodes-base.code",
      "position": [
        580,
        -180
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst mergedData = [];\n\nfor (const item of items) {\n  const platform = item.json.platform || 'unknown';\n  const cost = item.json.cost || item.json.totalCost || 0;\n  const resourceId = item.json.resourceId || item.json.service || 'unknown';\n  \n  mergedData.push({\n    platform,\n    cost: parseFloat(cost),\n    resourceId,\n    timestamp: new Date().toISOString(),\n    owner: item.json.tags?.owner || item.json.owner || 'untagged'\n  });\n}\n\nreturn mergedData.map(data => ({ json: data }));"
      },
      "typeVersion": 2
    },
    {
      "id": "6eb4ef65-cdc4-43eb-86f4-00a063b50e90",
      "name": "Cost Spike Detector",
      "type": "n8n-nodes-base.code",
      "position": [
        800,
        -180
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst alerts = [];\nconst COST_THRESHOLD = parseFloat($vars.COST_THRESHOLD || '50');\nconst SPIKE_MULTIPLIER = parseFloat($vars.SPIKE_MULTIPLIER || '2.0');\n\nfor (const item of items) {\n  const cost = item.json.cost;\n  const platform = item.json.platform;\n  const resourceId = item.json.resourceId;\n  \n  // Simple spike detection - compare with threshold\n  if (cost > COST_THRESHOLD) {\n    alerts.push({\n      type: 'threshold_exceeded',\n      platform,\n      resourceId,\n      currentCost: cost,\n      threshold: COST_THRESHOLD,\n      owner: item.json.owner,\n      severity: cost > (COST_THRESHOLD * 2) ? 'HIGH' : 'MEDIUM'\n    });\n  }\n}\n\nreturn alerts.map(alert => ({ json: alert }));"
      },
      "typeVersion": 2
    },
    {
      "id": "ee98766c-e7e2-4f2c-8d25-9b25a8d9ef24",
      "name": "Owner Identifier",
      "type": "n8n-nodes-base.if",
      "position": [
        1020,
        -180
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "owner-check",
              "operator": {
                "type": "string",
                "operation": "equals",
                "rightType": "manual"
              },
              "leftValue": "={{ $json.owner }}",
              "rightValue": "untagged"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "8eb36fe2-846e-47db-9771-38648146a629",
      "name": "Auto-Tag Resource",
      "type": "n8n-nodes-base.code",
      "position": [
        1240,
        -180
      ],
      "parameters": {
        "jsCode": "// Auto-tagging logic based on platform\nconst item = $input.first().json;\nconst platform = item.platform;\nconst resourceId = item.resourceId;\n\nlet tagCommand = '';\n\nswitch(platform) {\n  case 'aws':\n    tagCommand = `aws ec2 create-tags --resources ${resourceId} --tags Key=CostAlert,Value=true Key=AlertTime,Value=${new Date().toISOString()}`;\n    break;\n  case 'azure':\n    tagCommand = `az resource tag --ids ${resourceId} --tags CostAlert=true AlertTime=${new Date().toISOString()}`;\n    break;\n  case 'gcp':\n    tagCommand = `gcloud compute instances add-labels ${resourceId} --labels=cost-alert=true,alert-time=${Date.now()}`;\n    break;\n}\n\nreturn [{ json: { ...item, tagCommand } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d07764c6-fc5b-4614-ad39-b9373b67daaa",
      "name": "Alert Sender On Email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1460,
        -380
      ],
      "parameters": {
        "text": "=\ud83d\udea8 **Cost Alert** \ud83d\udea8|**Platform:** {{ $json.platform }}**Resource:** {{ $json.resourceId }}**Current Cost:** ${{ $json.currentCost }}**Threshold:** ${{ $json.threshold }}**Owner:** {{ $json.owner }}**Severity:** {{ $json.severity }}**Time:** {{ $json.timestamp }}*Auto-tagging command:*```{{ $json.tagCommand }}```",
        "options": {},
        "subject": "\ud83d\udea8 **Cost Alert** \ud83d\udea8",
        "toEmail": "user@example.com,user@example.com",
        "fromEmail": "user@example.com",
        "emailFormat": "text"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "becc8559-a46a-4d31-a2f9-9b92d2de2d55",
      "name": "Alert Sender On WhatsApp",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        1460,
        -180
      ],
      "parameters": {
        "textBody": "=\ud83d\udea8 **Cost Alert** \ud83d\udea8|**Platform:** {{ $json.platform }}**Resource:** {{ $json.resourceId }}**Current Cost:** ${{ $json.currentCost }}**Threshold:** ${{ $json.threshold }}**Owner:** {{ $json.owner }}**Severity:** {{ $json.severity }}**Time:** {{ $json.timestamp }}*Auto-tagging command:*```{{ $json.tagCommand }}```",
        "operation": "send",
        "phoneNumberId": "=+919999888877",
        "additionalFields": {},
        "recipientPhoneNumber": "+1234567890,+1234567890,+1234567890"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7cfa7945-ad77-46aa-9942-30a27bc77d55",
      "name": "Alert Sender On Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1460,
        20
      ],
      "parameters": {
        "text": "\ud83d\udea8 **Cost Alert** \ud83d\udea8\n\n**Platform:** {{ $json.platform }}\n**Resource:** {{ $json.resourceId }}\n**Current Cost:** ${{ $json.currentCost }}\n**Threshold:** ${{ $json.threshold }}\n**Owner:** {{ $json.owner }}\n**Severity:** {{ $json.severity }}\n**Time:** {{ $json.timestamp }}\n\n*Auto-tagging command:*\n```{{ $json.tagCommand }}```",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "{{ $vars.SLACK_CHANNEL_ID }}"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "e3274f83-533e-4cc9-af50-cb50e7ba5db4",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        620,
        -620
      ],
      "parameters": {
        "color": 6,
        "width": 700,
        "height": 300,
        "content": "## **How It Works**\n\n1. **Hourly Cron Trigger** \u2013 Starts the workflow every hour to fetch updated billing data.\n2. **AWS Billing Fetch** \u2013 Retrieves latest cost and usage data via AWS Cost Explorer API.\n3. **Azure Billing Fetch** \u2013 Retrieves subscription cost data from Azure Cost Management API.\n4. **GCP Billing Fetch** \u2013 Retrieves project-level spend data using GCP Cloud Billing API.\n5. **Data Parser** \u2013 Combines and cleans data from all three clouds into a unified format.\n6. **Cost Spike Detector** \u2013 Identifies unusual spending patterns or budget overruns.\n7. **Owner Identifier** \u2013 Matches resources to their respective owners or teams.\n8. **Auto-Tag Resource** \u2013 Tags the affected resource for quick identification and follow-up.\n9. **Alert Sender** \u2013 Sends notifications through Email, WhatsApp, and Slack with detailed cost reports."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "3e35fbfb-6c60-4cf3-a680-bc0fb7e7239e",
  "connections": {
    "Data Parser": {
      "main": [
        [
          {
            "node": "Cost Spike Detector",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cron Trigger": {
      "main": [
        [
          {
            "node": "AWS Billing Fetch",
            "type": "main",
            "index": 0
          },
          {
            "node": "Azure Billing Fetch",
            "type": "main",
            "index": 0
          },
          {
            "node": "GCP Billing Fetch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Owner Identifier": {
      "main": [
        [
          {
            "node": "Auto-Tag Resource",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Auto-Tag Resource",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AWS Billing Fetch": {
      "main": [
        [
          {
            "node": "Data Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auto-Tag Resource": {
      "main": [
        [
          {
            "node": "Alert Sender On Slack",
            "type": "main",
            "index": 0
          },
          {
            "node": "Alert Sender On WhatsApp",
            "type": "main",
            "index": 0
          },
          {
            "node": "Alert Sender On Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GCP Billing Fetch": {
      "main": [
        [
          {
            "node": "Data Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Azure Billing Fetch": {
      "main": [
        [
          {
            "node": "Data Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cost Spike Detector": {
      "main": [
        [
          {
            "node": "Owner Identifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Sender On Email": {
      "main": [
        []
      ]
    }
  }
}