DEV Community

Alex Kane
Alex Kane

Posted on

n8n for ClimateRiskTech & Carbon Markets SaaS: 5 Automations for EU ETS, CORSIA, Verra VCS, and CFTC

If your ClimateRiskTech or Carbon Markets SaaS platform routes EU ETS allowance data, voluntary carbon credit records, SEC climate disclosures, or CORSIA offset retirement data through Zapier, Make, or any cloud iPaaS — you have a compliance data residency problem that no security certification resolves.

This article gives you 5 production-ready n8n workflow templates built specifically for ClimateRiskTech and Carbon Markets SaaS vendors. Each workflow is import-ready JSON with tier segmentation, the right compliance clocks, and the self-hosting argument your enterprise customers are starting to ask about.

Why self-hosted n8n, not Zapier or Make?

Three architecture problems cloud iPaaS creates for carbon and climate platforms:

1. EU ETS verified emissions data outside your custody
EU ETS 2003/87/EC Art.14 requires verified emissions data from an accredited verifier. The April 30 allowance surrender clock runs against that verified number. If your automation pipeline routes verified emissions reports through Zapier's cloud — that data is now in a third-party system accessible via subpoena or regulator request before you know it exists.

2. CFTC voluntary carbon derivative same-day reporting gap
The CFTC has signaled that voluntary carbon derivatives meeting the definition of commodity swaps under CEA §2(c)(2)(D) require same-day T+0 reporting to a Swap Data Repository. If your trading platform routes swap execution data through a cloud iPaaS node — the reporting clock runs from the moment that node processes the trade, not from when your compliance team reviews it.

3. SEC 17 CFR §229.1500 climate disclosure audit trail
Large accelerated filers must disclose Scope 1 and Scope 2 GHG emissions beginning FY2025. The disclosure must be supported by an audit trail. If your carbon accounting platform routes Scope data through Zapier — the audit trail lives in Zapier's cloud. SEC examination requests for supporting documentation reach your vendor before they reach you.

The 7 ClimateRiskTech tiers

Tier Description
VOLUNTARY_CARBON_REGISTRY_SAAS FlowKit tier tag
CARBON_CREDIT_TRADING_SAAS FlowKit tier tag
CORPORATE_CARBON_ACCOUNTING_SAAS FlowKit tier tag
CLIMATE_RISK_ANALYTICS_SAAS FlowKit tier tag
EU_ETS_COMPLIANCE_SAAS FlowKit tier tag
AVIATION_CARBON_OFFSET_SAAS FlowKit tier tag
CLIMATERISKTECH_STARTUP FlowKit tier tag

The 7 compliance flags

Flag Description
SEC_CLIMATE_DISCLOSURE_SUBJECT Compliance flag
EU_ETS_COMPLIANCE_REQUIRED Compliance flag
CORSIA_ICAO_APPLICABLE Compliance flag
VCS_GOLD_STANDARD_REGISTRY Compliance flag
TCFD_DISCLOSURE_REQUIRED Compliance flag
CFTC_VOLUNTARY_CARBON_SUBJECT Compliance flag
SOC2_REQUIRED Compliance flag

Workflow 1: Tier-Segmented Customer Onboarding Drip

Day 0 welcome email varies by tier — EU ETS customers get the April 30 surrender clock note, CORSIA customers get the January 31 offset retirement deadline, corporate carbon accounting customers get the SEC 17 CFR §229.1500 FY2025 Scope disclosure note.

{
  "name": "ClimateRiskTech Tier-Segmented Customer Onboarding",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "climaterisktech-signup",
        "responseMode": "lastNode"
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Code - Classify Tier",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst tier = data.customer_tier || 'CLIMATERISKTECH_STARTUP';\nconst msgs = {\n  'VOLUNTARY_CARBON_REGISTRY_SAAS': 'Note: VCS Verra/Gold Standard credit issuance records routed through cloud iPaaS = data egress outside registry integrity boundary. CFTC CEA 2(c)(2)(D) voluntary carbon derivatives may require same-day SDR reporting.',\n  'CARBON_CREDIT_TRADING_SAAS': 'Note: CFTC voluntary carbon market oversight + SEC 17 CFR 229.1500 \u2014 trade execution and Scope 1/2/3 carbon inventory records routing through Zapier/Make = non-custodial records. EU MAR Art.2 market abuse monitoring applies to ETS allowance trading.',\n  'CORPORATE_CARBON_ACCOUNTING_SAAS': 'Note: SEC 17 CFR 229.1500 requires large accelerated filers to disclose Scope 1/2 GHG emissions from FY2025. Your platform holds the audit trail. Cloud iPaaS routing = records outside SOC2 boundary accessible via SEC examination.',\n  'CLIMATE_RISK_ANALYTICS_SAAS': 'Note: TCFD physical/transition risk assessments and scenario analysis outputs routed through cloud automation = confidential climate risk intelligence outside custody. SEC 229.1500 makes these disclosures material.',\n  'EU_ETS_COMPLIANCE_SAAS': 'Note: EU ETS allowance surrender April 30 \u2014 100 EUR/tonne penalty per missing allowance. EU MAR Art.2 market abuse monitoring applies to ETS trading. GDPR Art.44 cross-border data transfer issue for verified emissions data.',\n  'AVIATION_CARBON_OFFSET_SAAS': 'Note: CORSIA ICAO offset retirement January 31 deadline. Airlines must retire CORSIA Eligible Emissions Units equal to CO2 growth above 2019/2020 baseline. Non-compliance = route operating permit review by national aviation authority.',\n  'CLIMATERISKTECH_STARTUP': 'Welcome to FlowKit. Your onboarding is set up. Reach out anytime.'\n};\nreturn [{json: {customer_id: data.customer_id, email: data.email, company: data.company, tier, onboarding_note: msgs[tier] || msgs['CLIMATERISKTECH_STARTUP']}}];"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Gmail - Day 0 Welcome",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "={{$json.email}}",
        "subject": "={{$json.company}} is live on FlowKit \u2014 SEC/EU ETS/CORSIA compliance automations ready",
        "message": "={{$json.onboarding_note}}\n\nYour FlowKit workflows are ready to activate."
      },
      "position": [
        680,
        300
      ]
    },
    {
      "id": "4",
      "name": "Sheets - Log Onboarding",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "append",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "Onboarding!A:G",
        "dataMode": "autoMapInputData"
      },
      "position": [
        900,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Code - Classify Tier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Classify Tier": {
      "main": [
        [
          {
            "node": "Gmail - Day 0 Welcome",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Day 0 Welcome": {
      "main": [
        [
          {
            "node": "Sheets - Log Onboarding",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 2: SEC/EU ETS/CORSIA/CFTC Compliance Deadline Tracker

Daily 7AM scan of your compliance deadline spreadsheet. Classifies OVERDUE / CRITICAL (7d) / URGENT (14d) / WARNING (30d). Routes to Slack #compliance-ops and owner email.

12 deadline types tracked: EU_ETS_ALLOWANCE_SURRENDER_APR30 / CORSIA_OFFSET_RETIREMENT_JAN31 / SEC_CLIMATE_DISCLOSURE_10K (60d post-FY) / CFTC_VOLUNTARY_CARBON_SWAP_T0 (same-day) / EU_CSRD_ESRS_E1 (FY2026/2028) / TCFD_ANNUAL_DISCLOSURE / EU_ETS_VERIFIED_EMISSIONS_MARCH31 / GOLD_STANDARD_VINTAGE_EXPIRY (30d warning) / VCS_VERRA_VALIDATION_RENEWAL (5-year) / CORSIA_MONITORING_PLAN_ANNUAL / SOC2_TYPE2_RENEWAL / ANNUAL_PENTEST.

{
  "name": "ClimateRiskTech SEC/EU ETS/CORSIA/CFTC Compliance Deadline Tracker",
  "nodes": [
    {
      "id": "1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "readRows",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "ComplianceDeadlines!A:F"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Code - Triage",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const rows = $input.all().map(i => i.json);\nconst today = new Date();\nconst deadlines = [\n  {type:'EU_ETS_ALLOWANCE_SURRENDER_APR30',description:'EU ETS 2003/87/EC Art.12 allowance surrender April 30. Late: 100 EUR/tonne + registry notation.',clock:'APRIL_30_ANNUAL'},\n  {type:'CORSIA_OFFSET_RETIREMENT_JAN31',description:'CORSIA ICAO Annex 16 Vol.IV airline CO2 offset retirement January 31.',clock:'JANUARY_31_ANNUAL'},\n  {type:'SEC_CLIMATE_DISCLOSURE_10K',description:'SEC 17 CFR 229.1500 large accelerated filer Scope 1/2 emissions in 10-K from FY2025.',clock:'60_DAYS_POST_FY'},\n  {type:'CFTC_VOLUNTARY_CARBON_SWAP_T0',description:'CFTC CEA 2(c)(2)(D) voluntary carbon derivative SDR reporting T+0 same-day.',clock:'SAME_DAY'},\n  {type:'EU_CSRD_ESRS_E1',description:'EU CSRD ESRS E1 para.40 limited assurance FY2026, reasonable assurance FY2028.',clock:'90_DAYS_POST_FY'},\n  {type:'TCFD_ANNUAL_DISCLOSURE',description:'TCFD governance/strategy/risk/metrics annual \u2014 required by SEC 229.1500.',clock:'ANNUAL'},\n  {type:'EU_ETS_VERIFIED_EMISSIONS_MARCH31',description:'EU ETS 2003/87/EC Art.14 verified emissions report from accredited verifier March 31.',clock:'MARCH_31_ANNUAL'},\n  {type:'GOLD_STANDARD_VINTAGE_EXPIRY',description:'Gold Standard credit vintage expiry tracking \u2014 30-day warning before void.',clock:'30_DAYS_WARNING'},\n  {type:'VCS_VERRA_VALIDATION_RENEWAL',description:'VCS Standard v4.5 project validation renewal every 5 years.',clock:'5_YEAR'},\n  {type:'CORSIA_MONITORING_PLAN_ANNUAL',description:'ICAO CORSIA airline emissions monitoring plan annual submission.',clock:'ANNUAL'},\n  {type:'SOC2_TYPE2_RENEWAL',description:'SOC2 Type II annual audit renewal.',clock:'ANNUAL'},\n  {type:'ANNUAL_PENTEST',description:'Annual pentest for climate risk platform (SOC2 CC7.1).',clock:'ANNUAL'}\n];\nconst alerts = rows.map(row => {\n  const due = new Date(row.due_date);\n  const daysLeft = Math.ceil((due - today) / (1000 * 60 * 60 * 24));\n  let severity = 'NOTICE';\n  if (daysLeft <= 0) severity = 'OVERDUE';\n  else if (daysLeft <= 7) severity = 'CRITICAL';\n  else if (daysLeft <= 14) severity = 'URGENT';\n  else if (daysLeft <= 30) severity = 'WARNING';\n  return {...row, daysLeft, severity};\n}).filter(r => r.severity !== 'NOTICE');\nreturn alerts.map(a => ({json: a}));"
      },
      "position": [
        680,
        300
      ]
    },
    {
      "id": "4",
      "name": "IF - Alert Needed",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.severity}}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "position": [
        900,
        300
      ]
    },
    {
      "id": "5",
      "name": "Slack - Compliance Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "operation": "post",
        "channel": "#compliance-ops",
        "text": "={{$json.severity}} \u2014 {{$json.deadline_type}}: {{$json.description}} ({{$json.daysLeft}} days)"
      },
      "position": [
        1120,
        240
      ]
    },
    {
      "id": "6",
      "name": "Gmail - Owner Alert",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "={{$json.owner_email}}",
        "subject": "={{$json.severity}}: {{$json.deadline_type}} \u2014 {{$json.daysLeft}} days",
        "message": "={{$json.description}}"
      },
      "position": [
        1120,
        360
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets": {
      "main": [
        [
          {
            "node": "Code - Triage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Triage": {
      "main": [
        [
          {
            "node": "IF - Alert Needed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Alert Needed": {
      "main": [
        [
          {
            "node": "Slack - Compliance Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gmail - Owner Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 3: Carbon Registry and Trading API Health Monitor

Every 15 minutes — 5 endpoints checked in parallel: carbon registry API (VCS/Gold Standard issuance), EU ETS API (allowance transfer + verified emissions), CORSIA offset API (retirement tracking), climate risk API (TCFD scenario analysis), TCFD disclosure API (governance/metrics pipeline). Downtime near EU ETS April 30 or CORSIA January 31 deadlines creates direct compliance risk.

{
  "name": "Carbon Registry and Trading API Health Monitor",
  "nodes": [
    {
      "id": "1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/15 * * * *"
            }
          ]
        }
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "HTTP - Carbon Registry API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/carbon-registry/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        460,
        180
      ]
    },
    {
      "id": "3",
      "name": "HTTP - EU ETS API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/eu-ets/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        460,
        280
      ]
    },
    {
      "id": "4",
      "name": "HTTP - CORSIA Offset API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/corsia/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        460,
        380
      ]
    },
    {
      "id": "5",
      "name": "HTTP - Climate Risk API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/climate-risk/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        460,
        480
      ]
    },
    {
      "id": "6",
      "name": "HTTP - TCFD Disclosure API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/tcfd/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        460,
        580
      ]
    },
    {
      "id": "7",
      "name": "Code - Evaluate Health",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const endpoints = [\n  {name:'carbon_registry_api', note:'VCS/Gold Standard credit issuance \u2014 downtime = registry data gap, validation audit risk'},\n  {name:'eu_ets_api', note:'EU ETS allowance transfer + verified emissions \u2014 downtime near April 30 = surrender deadline risk'},\n  {name:'corsia_offset_api', note:'CORSIA offset retirement tracking \u2014 downtime near Jan 31 = route permit risk'},\n  {name:'climate_risk_api', note:'TCFD scenario analysis \u2014 downtime = SEC 229.1500 climate risk disclosure gap'},\n  {name:'tcfd_disclosure_api', note:'TCFD governance/metrics pipeline \u2014 downtime = disclosure integrity risk'}\n];\nconst results = $input.all().map((item, i) => ({\n  endpoint: endpoints[i].name,\n  status: item.json.status || (item.json.error ? 'DOWN' : 'UP'),\n  note: endpoints[i].note,\n  alert: !!(item.json.error || item.json.status === 'DOWN')\n}));\nreturn results.filter(r => r.alert).map(r => ({json: r}));"
      },
      "position": [
        680,
        380
      ]
    },
    {
      "id": "8",
      "name": "Slack - API Down Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "operation": "post",
        "channel": "#climate-platform-ops",
        "text": "API DOWN: {{$json.endpoint}} \u2014 {{$json.note}}"
      },
      "position": [
        900,
        380
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "HTTP - Carbon Registry API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - EU ETS API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - CORSIA Offset API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - Climate Risk API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - TCFD Disclosure API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - Carbon Registry API": {
      "main": [
        [
          {
            "node": "Code - Evaluate Health",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - EU ETS API": {
      "main": [
        [
          {
            "node": "Code - Evaluate Health",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - CORSIA Offset API": {
      "main": [
        [
          {
            "node": "Code - Evaluate Health",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - Climate Risk API": {
      "main": [
        [
          {
            "node": "Code - Evaluate Health",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - TCFD Disclosure API": {
      "main": [
        [
          {
            "node": "Code - Evaluate Health",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Evaluate Health": {
      "main": [
        [
          {
            "node": "Slack - API Down Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 4: ClimateRiskTech Compliance Incident Pipeline

Webhook-triggered incident classification with compliance clock lookup. 8 incident types:

  • EU_ETS_ALLOWANCE_SHORTFALL — April 30 hard deadline, 100 EUR/tonne + registry notation
  • CORSIA_OFFSET_RETIREMENT_FAILURE — January 31 hard deadline, ICAO route permit review
  • SEC_CLIMATE_DISCLOSURE_MATERIAL_CHANGE — 4 business days (Form 8-K), SEC 17 CFR §229.1500
  • CFTC_VOLUNTARY_CARBON_SWAP_UNREPORTED — T+0 same-day, CFTC CEA §2(c)(2)(D)
  • VCS_VERRA_REGISTRY_INTEGRITY_BREACH — Immediate suspension, credits unretirable
  • EU_MAR_CARBON_MARKET_ABUSE — 1 business day STR to national CA
  • TCFD_DISCLOSURE_DATA_INTEGRITY_FAILURE — Before annual filing, restatement risk
  • GENERAL — 24h triage
{
  "name": "ClimateRiskTech Compliance Incident Pipeline",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "climate-incident",
        "responseMode": "lastNode"
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Code - Classify Incident",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst clocks = {\n  'EU_ETS_ALLOWANCE_SHORTFALL': {deadline: 'April 30 hard deadline', clock: '100 EUR/tonne per missing allowance + EU ETS Registry public notation', regulator: 'EU ETS Registry / National Competent Authority', action: 'IMMEDIATE: calculate shortfall, procure allowances, escalate to C-suite'},\n  'CORSIA_OFFSET_RETIREMENT_FAILURE': {deadline: 'January 31 hard deadline', clock: 'ICAO notification to national aviation authority = route operating permit review', regulator: 'ICAO / National Aviation Authority', action: 'IMMEDIATE: identify shortfall, procure CORSIA Eligible Emissions Units, file corrective action plan'},\n  'SEC_CLIMATE_DISCLOSURE_MATERIAL_CHANGE': {deadline: '4 business days (Form 8-K)', clock: 'SEC 17 CFR 229.1500 + 240.13a-11 material climate event = Form 8-K filing. Late = SEC enforcement.', regulator: 'SEC Division of Corporation Finance', action: '4 BIZ DAYS: assess materiality, prepare 8-K, notify counsel, update carbon accounting records'},\n  'CFTC_VOLUNTARY_CARBON_SWAP_UNREPORTED': {deadline: 'T+0 same-day', clock: 'CFTC CEA 2(c)(2)(D) voluntary carbon derivative SDR reporting overdue. Late = CFTC enforcement.', regulator: 'CFTC / Swap Data Repository', action: 'SAME DAY: classify instrument, submit to SDR, document decision tree'},\n  'VCS_VERRA_REGISTRY_INTEGRITY_BREACH': {deadline: 'Immediate suspension', clock: 'VCS Standard v4.5 project suspension. Credits from suspended project = unretirable by buyers.', regulator: 'Verra VCS Registry', action: 'IMMEDIATE: notify Verra, freeze credit issuance, activate incident response'},\n  'EU_MAR_CARBON_MARKET_ABUSE': {deadline: '1 business day', clock: 'EU MAR Art.2 + EU ETS Directive suspicious ETS allowance trading = STR to national CA.', regulator: 'ESMA / National Competent Authority', action: '1 BIZ DAY: document suspicious activity, file STR, suspend implicated accounts'},\n  'TCFD_DISCLOSURE_DATA_INTEGRITY_FAILURE': {deadline: 'Before annual report filing', clock: 'SEC 229.1500 + TCFD restatement risk + SEC comment letter if material error in climate disclosure.', regulator: 'SEC / External Auditor', action: 'BEFORE FILING: validate Scope 1/2/3 data sources, check pipeline integrity, engage external verifier'},\n  'GENERAL': {deadline: 'Triage within 24h', clock: 'General climate platform incident', regulator: 'Internal', action: 'Assign to compliance team within 24h'}\n};\nconst type = data.incident_type || 'GENERAL';\nconst clock = clocks[type] || clocks['GENERAL'];\nreturn [{json: {incident_id: data.incident_id, incident_type: type, ...clock, reported_by: data.reported_by, timestamp: new Date().toISOString()}}];"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Slack - #compliance-critical",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "operation": "post",
        "channel": "#compliance-critical",
        "text": "CLIMATE INCIDENT: {{$json.incident_type}} | Clock: {{$json.clock}} | Action: {{$json.action}}"
      },
      "position": [
        680,
        200
      ]
    },
    {
      "id": "4",
      "name": "Gmail - CCO + GC",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "cco@yourcompany.com",
        "subject": "CLIMATE COMPLIANCE INCIDENT: {{$json.incident_type}}",
        "message": "Incident: {{$json.incident_type}}\nClock: {{$json.clock}}\nRegulator: {{$json.regulator}}\nRequired Action: {{$json.action}}\nReported by: {{$json.reported_by}}\nTimestamp: {{$json.timestamp}}"
      },
      "position": [
        680,
        320
      ]
    },
    {
      "id": "5",
      "name": "Sheets - Incident Log",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "append",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "IncidentLog!A:H",
        "dataMode": "autoMapInputData"
      },
      "position": [
        900,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Code - Classify Incident",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Classify Incident": {
      "main": [
        [
          {
            "node": "Slack - #compliance-critical",
            "type": "main",
            "index": 0
          },
          {
            "node": "Gmail - CCO + GC",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - #compliance-critical": {
      "main": [
        [
          {
            "node": "Sheets - Incident Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - CCO + GC": {
      "main": [
        [
          {
            "node": "Sheets - Incident Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 5: Weekly ClimateRiskTech KPI Dashboard

Monday 8AM — Postgres queries for active customers by tier, MRR with WoW%, open EU ETS shortfalls, open CORSIA failures, open SEC climate incidents, open CFTC swap unreported items. HTML email to CEO BCC CCO/CFO + Slack #go-to-market.

{
  "name": "Weekly ClimateRiskTech KPI Dashboard",
  "nodes": [
    {
      "id": "1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Postgres - Active Customers",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(*) as active_customers, COUNT(CASE WHEN tier='CORPORATE_CARBON_ACCOUNTING_SAAS' THEN 1 END) as corp_carbon, COUNT(CASE WHEN tier='EU_ETS_COMPLIANCE_SAAS' THEN 1 END) as eu_ets, COUNT(CASE WHEN tier='VOLUNTARY_CARBON_REGISTRY_SAAS' THEN 1 END) as vcm_registry, COUNT(CASE WHEN tier='AVIATION_CARBON_OFFSET_SAAS' THEN 1 END) as aviation_corsia, SUM(mrr_usd) as total_mrr FROM customers WHERE status='active'"
      },
      "position": [
        460,
        240
      ]
    },
    {
      "id": "3",
      "name": "Postgres - Compliance KPIs",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(CASE WHEN status='OPEN' AND type='EU_ETS_ALLOWANCE_SHORTFALL' THEN 1 END) as eu_ets_open, COUNT(CASE WHEN status='OPEN' AND type='CORSIA_OFFSET_RETIREMENT_FAILURE' THEN 1 END) as corsia_open, COUNT(CASE WHEN status='OPEN' AND type='SEC_CLIMATE_DISCLOSURE_MATERIAL_CHANGE' THEN 1 END) as sec_climate_open, COUNT(CASE WHEN status='OPEN' AND type='CFTC_VOLUNTARY_CARBON_SWAP_UNREPORTED' THEN 1 END) as cftc_open, SUM(CASE WHEN created_at > NOW() - INTERVAL '7 days' THEN 1 ELSE 0 END) as incidents_week FROM compliance_incidents"
      },
      "position": [
        460,
        380
      ]
    },
    {
      "id": "4",
      "name": "Code - Build KPI Report",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const customers = $('Postgres - Active Customers').first().json;\nconst compliance = $('Postgres - Compliance KPIs').first().json;\nconst prev = $getWorkflowStaticData('global');\nconst currMRR = customers.total_mrr || 0;\nconst prevMRR = prev.last_mrr || currMRR;\nconst mrrWoW = prevMRR ? (((currMRR - prevMRR) / prevMRR) * 100).toFixed(1) : '0.0';\nprev.last_mrr = currMRR;\n$setWorkflowStaticData('global', prev);\nconst criticalAlerts = [];\nif (compliance.eu_ets_open > 0) criticalAlerts.push('EU ETS SHORTFALL OPEN: ' + compliance.eu_ets_open + ' customers \u2014 100 EUR/tonne penalty risk');\nif (compliance.corsia_open > 0) criticalAlerts.push('CORSIA FAILURES: ' + compliance.corsia_open + ' \u2014 route permit risk');\nif (compliance.sec_climate_open > 0) criticalAlerts.push('SEC CLIMATE: ' + compliance.sec_climate_open + ' open \u2014 4 biz day 8-K clock');\nif (compliance.cftc_open > 0) criticalAlerts.push('CFTC SWAP UNREPORTED: ' + compliance.cftc_open + ' \u2014 same-day SDR overdue');\nconst html = '<h2>ClimateRiskTech Weekly KPI</h2><table border=1><tr><th>Metric</th><th>Value</th></tr><tr><td>Active Customers</td><td>' + customers.active_customers + '</td></tr><tr><td>Corp Carbon Accounting</td><td>' + customers.corp_carbon + '</td></tr><tr><td>EU ETS Compliance</td><td>' + customers.eu_ets + '</td></tr><tr><td>VCM Registry</td><td>' + customers.vcm_registry + '</td></tr><tr><td>Aviation/CORSIA</td><td>' + customers.aviation_corsia + '</td></tr><tr><td>MRR</td><td>$' + currMRR + ' (' + mrrWoW + '% WoW)</td></tr><tr><td>EU ETS Shortfalls Open</td><td>' + compliance.eu_ets_open + '</td></tr><tr><td>CORSIA Failures Open</td><td>' + compliance.corsia_open + '</td></tr><tr><td>SEC Climate Open</td><td>' + compliance.sec_climate_open + '</td></tr><tr><td>CFTC Swap Unreported</td><td>' + compliance.cftc_open + '</td></tr></table>' + (criticalAlerts.length ? '<h3 style=color:red>CRITICAL</h3><ul>' + criticalAlerts.map(a => '<li>' + a + '</li>').join('') + '</ul>' : '');\nreturn [{json: {html, mrrWoW, ...customers, ...compliance}}];"
      },
      "position": [
        680,
        300
      ]
    },
    {
      "id": "5",
      "name": "Gmail - CEO BCC CCO",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "ceo@yourcompany.com",
        "bcc": "cco@yourcompany.com",
        "subject": "ClimateRiskTech Weekly KPI \u2014 MRR {{$json.mrrWoW}}% WoW",
        "message": "={{$json.html}}",
        "options": {
          "appendAttribution": false
        }
      },
      "position": [
        900,
        240
      ]
    },
    {
      "id": "6",
      "name": "Slack - #go-to-market",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "operation": "post",
        "channel": "#go-to-market",
        "text": "Weekly KPI: {{$json.active_customers}} customers | MRR ${{$json.total_mrr}} ({{$json.mrrWoW}}% WoW) | EU ETS open: {{$json.eu_ets_open}} | CORSIA: {{$json.corsia_open}}"
      },
      "position": [
        900,
        360
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Postgres - Active Customers",
            "type": "main",
            "index": 0
          },
          {
            "node": "Postgres - Compliance KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres - Active Customers": {
      "main": [
        [
          {
            "node": "Code - Build KPI Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres - Compliance KPIs": {
      "main": [
        [
          {
            "node": "Code - Build KPI Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Build KPI Report": {
      "main": [
        [
          {
            "node": "Gmail - CEO BCC CCO",
            "type": "main",
            "index": 0
          },
          {
            "node": "Slack - #go-to-market",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Self-hosting comparison

Requirement Cloud iPaaS (Zapier/Make) Self-hosted n8n
EU ETS verified emissions data residency Data transits vendor cloud Stays inside your infrastructure
CFTC swap reporting audit trail Partial — vendor logs Complete — your database
SEC 17 CFR §229.1500 Scope data custody Vendor holds supporting data Your SOC2 boundary
CORSIA offset retirement records Accessible to vendor via subpoena Under your legal privilege
VCS/Gold Standard registry data External custody Internal custody
EU GDPR Art.44 cross-border transfer Requires SCCs per Zapier DPA Resolved by data residency

Get all 5 workflows

These workflows are available individually and as part of the FlowKit n8n Automation Bundle at stripeai.gumroad.com

The bundle includes 14 automation templates covering ClimateRiskTech, FinTech, HealthTech, LegalTech, HR Tech, and 9 other verticals — $97 for the complete set.

Drop a comment if you want the EU ETS allowance surrender calculator as a standalone workflow.

Top comments (0)