DEV Community

Alex Kane
Alex Kane

Posted on

n8n for HealthTech/Digital Health SaaS Vendors: 5 Automations for HIPAA Security Rule, 21st Century Cures Act, ONC TEFCA, and FDA SaMD Compliance

If your SaaS sells to hospitals, health systems, digital health platforms, or clinical analytics teams, your customers operate under some of the most complex compliance regimes in technology: HIPAA's Security Rule technical safeguards, the 21st Century Cures Act's information blocking prohibition, ONC TEFCA data-sharing requirements, CMS FHIR API mandates, and FDA Software as a Medical Device (SaMD) regulations.

When those customers route patient data — even metadata — through a cloud automation platform like Zapier or Make, they're creating compliance exposure they may not have assessed. This post walks through 5 n8n workflows that HealthTech SaaS vendors can use to automate compliance operations, with full workflow JSON you can import today.

The Hidden Compliance Risk: Your Cloud iPaaS as a HIPAA Business Associate

Before the workflows: if your platform processes, stores, or transmits Protected Health Information (PHI) on behalf of covered entities, your automation layer is subject to HIPAA's Business Associate Agreement requirements under 45 CFR §164.308(b)(1).

Cloud n8n, Zapier, and Make are business associates the moment PHI flows through them. That means:

  • BAA required before routing ePHI (45 CFR §164.308(b)(3))
  • Audit logs of PHI access by the workflow engine (45 CFR §164.312(b))
  • Encryption in transit and at rest for workflows handling ePHI (§164.312(a)(2)(iv))

Self-hosted n8n keeps PHI inside your authorization boundary. This matters for FedRAMP-aligned health systems, TEFCA QHIN participants, and FDA SaMD vendors where the workflow engine's change management must be documented under 21 CFR §820.30.

Customer Tiers

Tier Description Key Compliance Flags
LARGE_HEALTH_SYSTEM >500 beds, Epic/Cerner integration HIPAA_COVERED_ENTITY, ONC_CERTIFIED_HIT, HIPAA_BUSINESS_ASSOCIATE
REGIONAL_HOSPITAL 50–500 beds HIPAA_COVERED_ENTITY, NY_SHIELD_ACT_SUBJECT
DIGITAL_HEALTH_SAAS Telehealth, RPM, DTx platforms INFORMATION_BLOCKING_SUBJECT, CMS_INTEROP_API_REQUIRED, HIPAA_BUSINESS_ASSOCIATE
CLINICAL_ANALYTICS_SAAS AI diagnostics, ML clinical models FDA_SAMD_REGULATED, HIPAA_BUSINESS_ASSOCIATE
HEALTH_IT_VENDOR EHR/HIT vendors, ONC certification holders ONC_CERTIFIED_HIT, INFORMATION_BLOCKING_SUBJECT
HEALTH_PLAN_PAYER Insurance payers, FHIR API CMS_INTEROP_API_REQUIRED, HIPAA_COVERED_ENTITY
DIGITAL_THERAPEUTICS FDA 510(k) or De Novo cleared SaMD FDA_SAMD_REGULATED, NY_SHIELD_ACT_SUBJECT

Workflow 1: Tier-Segmented Onboarding Drip

Different customer tiers face different compliance clocks on day 1. A CLINICAL_ANALYTICS_SAAS customer needs to hear about FDA SaMD intended use documentation before they route model outputs anywhere. A DIGITAL_HEALTH_SAAS customer needs to understand §4004 information blocking risk before they connect their FHIR API.

This workflow routes new accounts to tier-specific onboarding emails at signup, covering the compliance context most relevant to each tier.

{
  "name": "HealthTech Tier-Segmented Onboarding Drip",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "healthtech-onboarding",
        "httpMethod": "POST"
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Extract Customer Tier",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const tier = $json.customer_tier || 'DIGITAL_HEALTH_SAAS';\nconst flags = $json.compliance_flags || [];\nconst account_id = $json.account_id;\nconst contact_email = $json.contact_email;\nconst company_name = $json.company_name || 'Your Organization';\nreturn [{ json: { tier, flags, account_id, contact_email, company_name } }];"
      },
      "position": [
        450,
        300
      ]
    },
    {
      "id": "3",
      "name": "Route by Tier",
      "type": "n8n-nodes-base.switch",
      "parameters": {
        "value": "={{ $json.tier }}",
        "rules": {
          "values": [
            {
              "value": "LARGE_HEALTH_SYSTEM"
            },
            {
              "value": "REGIONAL_HOSPITAL"
            },
            {
              "value": "DIGITAL_HEALTH_SAAS"
            },
            {
              "value": "CLINICAL_ANALYTICS_SAAS"
            },
            {
              "value": "HEALTH_IT_VENDOR"
            },
            {
              "value": "HEALTH_PLAN_PAYER"
            },
            {
              "value": "DIGITAL_THERAPEUTICS"
            }
          ]
        }
      },
      "position": [
        650,
        300
      ]
    },
    {
      "id": "4",
      "name": "Large Health System Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "={{ $json.contact_email }}",
        "subject": "HIPAA \u00a7164.312 + Epic/Cerner FHIR Integration \u2014 Your n8n Onboarding",
        "message": "Welcome {{ $json.company_name }}.\n\nAs a Large Health System (>500 beds), your n8n deployment touches HIPAA Security Rule 45 CFR \u00a7164.312 administrative, physical, and technical safeguards \u2014 including audit controls \u00a7164.312(b), encryption \u00a7164.312(a)(2)(iv), and access management \u00a7164.312(d).\n\nKey compliance timelines for your tier:\n\u2022 HIPAA breach notification to OCR: 60 days from discovery (45 CFR \u00a7164.412)\n\u2022 Risk analysis review: annual (45 CFR \u00a7164.308(a)(1))\n\u2022 Epic/Cerner SMART on FHIR: n8n workflows accessing FHIR R4 APIs must log all PHI access under \u00a7164.312(b)\n\u2022 ONC \u00a7170.315(g)(10): FHIR API must remain accessible \u2014 do not route through n8n in ways that block patient data access\n\nSelf-hosting recommendation: PHI flowing through your n8n instance requires a BAA. Cloud iPaaS vendors (Zapier, Make, n8n Cloud) are business associates under 45 CFR \u00a7164.308(b)(1) \u2014 verify BAA is in place before routing PHI.\n\nNext steps: Schedule HIPAA risk analysis walkthrough with our compliance team."
      },
      "position": [
        850,
        100
      ]
    },
    {
      "id": "5",
      "name": "Digital Health SaaS Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "={{ $json.contact_email }}",
        "subject": "21st Century Cures Act \u00a74004 + TEFCA QHIN \u2014 Your n8n Onboarding",
        "message": "Welcome {{ $json.company_name }}.\n\nAs a Digital Health SaaS vendor (telehealth, RPM, DTx), the 21st Century Cures Act \u00a74004 information blocking prohibition is your highest enforcement risk. ONC defines 8 exceptions; workflows that delay, restrict, or interfere with FHIR resource access \u2014 even inadvertently via n8n error handling \u2014 may constitute information blocking.\n\nKey compliance timelines for your tier:\n\u2022 Information blocking complaint response: 10 business days (ONC)\n\u2022 TEFCA QHIN data sharing attestation: annual\n\u2022 CMS FHIR API (45 CFR \u00a7170.315(g)(10)) compliance: continuous\n\u2022 HIPAA breach notification: 60 days from discovery\n\nSelf-hosting recommendation: n8n workflows that process FHIR resources from ONC-certified APIs become part of your information blocking analysis. Cloud n8n routes FHIR data through a third-party data center \u2014 ONC's 'actor' definition (45 CFR \u00a7171.102) may extend to your iPaaS vendor.\n\nNext steps: Map every FHIR API call in your current automation stack to the \u00a74004 exceptions matrix."
      },
      "position": [
        850,
        250
      ]
    },
    {
      "id": "6",
      "name": "Clinical Analytics SaaS Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "={{ $json.contact_email }}",
        "subject": "FDA SaMD 21 CFR Part 820 + Intended Use Documentation \u2014 Your n8n Onboarding",
        "message": "Welcome {{ $json.company_name }}.\n\nAs a Clinical Analytics SaaS vendor (AI diagnostics, ML models), your n8n automation workflows may be in scope for FDA Software as a Medical Device (SaMD) regulation under 21 CFR Part 820 Quality System Regulation \u2014 if they execute logic that influences clinical decisions.\n\nKey compliance timelines for your tier:\n\u2022 FDA SaMD annual performance summary: required for 510(k) cleared devices\n\u2022 Design control review: annual (21 CFR \u00a7820.30)\n\u2022 Corrective and Preventive Action (CAPA): 30 days for critical findings (\u00a7820.100)\n\u2022 HIPAA breach notification: 60 days\n\u2022 NY SHIELD Act security review: annual\n\nSelf-hosting recommendation: FDA's intended use doctrine \u2014 if your n8n workflow routes model output into a clinical decision path, that workflow may be considered part of the SaMD. Cloud iPaaS version changes without your control = \u00a7820.30 design change documentation gap.\n\nNext steps: Document intended use boundaries for all n8n workflows that touch clinical model output."
      },
      "position": [
        850,
        400
      ]
    },
    {
      "id": "7",
      "name": "Health IT Vendor Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "={{ $json.contact_email }}",
        "subject": "ONC Certification \u00a7170.315 + Information Blocking Actor Analysis \u2014 Your n8n Onboarding",
        "message": "Welcome {{ $json.company_name }}.\n\nAs a Health IT Vendor (EHR/HIT certification holder), n8n workflows that process, route, or transform data from ONC-certified modules are subject to \u00a7170.315 Certified Health IT criteria \u2014 particularly \u00a7170.315(g)(10) FHIR API access and \u00a7170.315(b) clinical information requirements.\n\nKey compliance timelines for your tier:\n\u2022 ONC annual surveillance: per certification\n\u2022 CMS interoperability API annual update: \u00a7170.315(g)(10)\n\u2022 Information blocking actor analysis: ongoing\n\u2022 HIPAA BAA with cloud iPaaS: required before routing ePHI\n\u2022 TEFCA QHIN participation attestation: annual\n\nSelf-hosting recommendation: ONC certification scope extends to systems that interface with certified modules. An n8n workflow that modifies or delays data from a \u00a7170.315-certified API may require you to re-evaluate your certification boundary.\n\nNext steps: Review \u00a7170.315 certification boundary documentation for all n8n integration points."
      },
      "position": [
        850,
        550
      ]
    },
    {
      "id": "8",
      "name": "Google Sheets Log",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "append",
        "spreadsheetId": "YOUR_SPREADSHEET_ID",
        "range": "Onboarding!A:F",
        "values": [
          [
            "={{ $json.account_id }}",
            "={{ $json.company_name }}",
            "={{ $json.tier }}",
            "={{ $json.flags.join(',') }}",
            "={{ new Date().toISOString() }}",
            "ONBOARDING_EMAIL_SENT"
          ]
        ]
      },
      "position": [
        1050,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Extract Customer Tier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Customer Tier": {
      "main": [
        [
          {
            "node": "Route by Tier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Tier": {
      "main": [
        [
          {
            "node": "Large Health System Email"
          }
        ],
        [
          {
            "node": "Regional Hospital Email"
          }
        ],
        [
          {
            "node": "Digital Health SaaS Email"
          }
        ],
        [
          {
            "node": "Clinical Analytics SaaS Email"
          }
        ],
        [
          {
            "node": "Health IT Vendor Email"
          }
        ],
        [
          {
            "node": "Health Plan Payer Email"
          }
        ],
        [
          {
            "node": "Digital Therapeutics Email"
          }
        ]
      ]
    },
    "Large Health System Email": {
      "main": [
        [
          {
            "node": "Google Sheets Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Digital Health SaaS Email": {
      "main": [
        [
          {
            "node": "Google Sheets Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clinical Analytics SaaS Email": {
      "main": [
        [
          {
            "node": "Google Sheets Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Health IT Vendor Email": {
      "main": [
        [
          {
            "node": "Google Sheets Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Setup: POST to the webhook with customer_tier, account_id, contact_email, company_name, and compliance_flags array. The Switch node routes to the correct Gmail node per tier. Extend by adding Slack DM to your CS team for HIGH_VALUE accounts.

Workflow 2: HIPAA / Cures Act / FDA SaMD Deadline Tracker

Twelve deadline types, daily urgency scoring, Slack alerts for CRITICAL/URGENT items, Gmail to CCO.

The 12 deadline types cover the full HealthTech compliance calendar:

Deadline Type Clock Law
HIPAA_BREACH_NOTIFICATION_60_DAY 60 days from discovery 45 CFR §164.412
HIPAA_BREACH_NOTIFICATION_MEDIA_60_DAY 60 days, media if >500 affected 45 CFR §164.412(a)
HIPAA_RISK_ANALYSIS_ANNUAL Annual 45 CFR §164.308(a)(1)
ONC_INFORMATION_BLOCKING_COMPLAINT_10_DAY 10 business days 21st Century Cures Act §4004
CMS_FHIR_API_ANNUAL_UPDATE Annual 45 CFR §170.315(g)(10)
FDA_SAMD_ANNUAL_PERFORMANCE_SUMMARY Annual 21 CFR Part 820
FDA_QMS_DESIGN_CONTROL_REVIEW_ANNUAL Annual 21 CFR §820.30
TEFCA_QHIN_ANNUAL_ATTESTATION Annual TEFCA Framework 2024
HIPAA_TRAINING_ANNUAL Annual 45 CFR §164.308(a)(5)
NY_SHIELD_ACT_ANNUAL_REVIEW Annual NY SHIELD Act §899-bb
NIST_CSF_HEALTHCARE_ANNUAL Annual NIST CSF + HIPAA crosswalk
HIPAA_AUDIT_CONTROL_QUARTERLY 90 days 45 CFR §164.312(b)
{
  "name": "HealthTech HIPAA/Cures Act/FDA SaMD Deadline Tracker",
  "nodes": [
    {
      "id": "1",
      "name": "Daily Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Fetch Deadline Items",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "read",
        "spreadsheetId": "YOUR_SPREADSHEET_ID",
        "range": "Deadlines!A:G"
      },
      "position": [
        450,
        300
      ]
    },
    {
      "id": "3",
      "name": "Check Urgency",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const today = new Date();\nconst items = $input.all().map(item => item.json);\nconst urgent = [];\n\nconst DEADLINE_TYPES = {\n  'HIPAA_BREACH_NOTIFICATION_60_DAY': { days: 60, law: '45 CFR \u00a7164.412', severity: 'CRITICAL', note: 'OCR notification required + media if >500 affected' },\n  'HIPAA_BREACH_NOTIFICATION_MEDIA_60_DAY': { days: 60, law: '45 CFR \u00a7164.412(a)', severity: 'CRITICAL', note: 'Media outlet notice if >500 residents of state or jurisdiction' },\n  'HIPAA_RISK_ANALYSIS_ANNUAL': { days: 365, law: '45 CFR \u00a7164.308(a)(1)', severity: 'HIGH', note: 'Documented risk analysis and risk management plan' },\n  'ONC_INFORMATION_BLOCKING_COMPLAINT_10_DAY': { days: 10, law: '21st Century Cures Act \u00a74004', severity: 'CRITICAL', note: 'ONC complaint response \u2014 10 business days, civil monetary penalty $1M/violation' },\n  'CMS_FHIR_API_ANNUAL_UPDATE': { days: 365, law: '45 CFR \u00a7170.315(g)(10)', severity: 'HIGH', note: 'SMART on FHIR API must remain accessible and updated annually' },\n  'FDA_SAMD_ANNUAL_PERFORMANCE_SUMMARY': { days: 365, law: '21 CFR Part 820 + FDA SaMD guidance', severity: 'HIGH', note: 'Annual performance summary for 510(k) cleared SaMD' },\n  'FDA_QMS_DESIGN_CONTROL_REVIEW_ANNUAL': { days: 365, law: '21 CFR \u00a7820.30', severity: 'HIGH', note: 'Design control review \u2014 document all workflow changes in SaMD scope' },\n  'TEFCA_QHIN_ANNUAL_ATTESTATION': { days: 365, law: 'TEFCA Framework 2024', severity: 'MEDIUM', note: 'Annual QHIN participation attestation and DURSA compliance review' },\n  'HIPAA_TRAINING_ANNUAL': { days: 365, law: '45 CFR \u00a7164.308(a)(5)', severity: 'MEDIUM', note: 'Annual HIPAA workforce training documentation' },\n  'NY_SHIELD_ACT_ANNUAL_REVIEW': { days: 365, law: 'NY SHIELD Act \u00a7899-bb', severity: 'MEDIUM', note: 'Reasonable security program review for NY residents private information' },\n  'NIST_CSF_HEALTHCARE_ANNUAL': { days: 365, law: 'NIST CSF + HIPAA crosswalk', severity: 'LOW', note: 'Annual NIST Cybersecurity Framework assessment mapped to HIPAA Security Rule' },\n  'HIPAA_AUDIT_CONTROL_QUARTERLY': { days: 90, law: '45 CFR \u00a7164.312(b)', severity: 'HIGH', note: 'Quarterly audit log review \u2014 hardware, software, procedural mechanisms' }\n};\n\nfor (const item of items) {\n  const type = item.deadline_type;\n  const due = new Date(item.due_date);\n  const daysLeft = Math.ceil((due - today) / (1000 * 60 * 60 * 24));\n  const meta = DEADLINE_TYPES[type] || { severity: 'MEDIUM', law: 'N/A', note: '' };\n  \n  let urgency = 'OK';\n  if (daysLeft < 0) urgency = 'OVERDUE';\n  else if (daysLeft <= 3) urgency = 'CRITICAL';\n  else if (daysLeft <= 14) urgency = 'URGENT';\n  else if (daysLeft <= 30) urgency = 'DUE_SOON';\n  \n  if (urgency !== 'OK') {\n    urgent.push({ ...item, daysLeft, urgency, severity: meta.severity, law: meta.law, note: meta.note });\n  }\n}\n\nreturn urgent.map(u => ({ json: u }));"
      },
      "position": [
        650,
        300
      ]
    },
    {
      "id": "4",
      "name": "IF Urgent",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.urgency }}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "position": [
        850,
        300
      ]
    },
    {
      "id": "5",
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#healthtech-compliance",
        "text": "={{ $json.urgency === 'CRITICAL' || $json.urgency === 'OVERDUE' ? '\ud83d\udea8' : '\u26a0\ufe0f' }} *{{ $json.urgency }}* | {{ $json.deadline_type }}\n*Account:* {{ $json.account_name }} ({{ $json.tier }})\n*Due:* {{ $json.due_date }} ({{ $json.daysLeft }} days)\n*Law:* {{ $json.law }}\n*Note:* {{ $json.note }}"
      },
      "position": [
        1050,
        200
      ]
    },
    {
      "id": "6",
      "name": "Gmail CCO Alert",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "compliance@yourcompany.com",
        "bcc": "cco@yourcompany.com",
        "subject": "={{ $json.urgency }}: {{ $json.deadline_type }} \u2014 {{ $json.account_name }}",
        "message": "Deadline Alert \u2014 {{ $json.deadline_type }}\n\nAccount: {{ $json.account_name }}\nTier: {{ $json.tier }}\nUrgency: {{ $json.urgency }}\nDays Remaining: {{ $json.daysLeft }}\nDue Date: {{ $json.due_date }}\nApplicable Law: {{ $json.law }}\nCompliance Note: {{ $json.note }}\n\nAction required immediately."
      },
      "position": [
        1050,
        400
      ]
    },
    {
      "id": "7",
      "name": "Update Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "update",
        "spreadsheetId": "YOUR_SPREADSHEET_ID",
        "range": "Deadlines!G:G",
        "values": [
          [
            "={{ $json.urgency }}"
          ]
        ]
      },
      "position": [
        1250,
        300
      ]
    }
  ],
  "connections": {
    "Daily Schedule": {
      "main": [
        [
          {
            "node": "Fetch Deadline Items"
          }
        ]
      ]
    },
    "Fetch Deadline Items": {
      "main": [
        [
          {
            "node": "Check Urgency"
          }
        ]
      ]
    },
    "Check Urgency": {
      "main": [
        [
          {
            "node": "IF Urgent"
          }
        ]
      ]
    },
    "IF Urgent": {
      "main": [
        [
          {
            "node": "Slack Alert"
          },
          {
            "node": "Gmail CCO Alert"
          }
        ],
        [
          {
            "node": "Update Sheets"
          }
        ]
      ]
    },
    "Slack Alert": {
      "main": [
        [
          {
            "node": "Update Sheets"
          }
        ]
      ]
    },
    "Gmail CCO Alert": {
      "main": [
        [
          {
            "node": "Update Sheets"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Setup: Maintain a Google Sheet Deadlines tab with columns: account_id, account_name, tier, deadline_type, due_date, status. Run daily at 7 AM. Urgency thresholds: OVERDUE (past), CRITICAL (≤3 days), URGENT (≤14 days), DUE_SOON (≤30 days).

Workflow 3: HealthTech API Health Monitor

Five endpoints, every 10 minutes, with compliance-specific annotations on each failure.

The critical insight: not all HealthTech downtime is equal. The FHIR API going down is a 21st Century Cures Act §4004 information blocking event — ONC's definition of information blocking includes practices that interfere with access to EHI. A patient portal outage is a CMS §170.315(e) failure. A HIPAA audit log API going down means PHI access is occurring without the audit trail required by 45 CFR §164.312(b).

Endpoint Compliance Risk on DOWN
fhir_api 21st Cures Act §4004 info blocking IMMINENT
hipaa_audit_log_api 45 CFR §164.312(b) PHI access log gap
patient_portal_api CMS §170.315(e) access — info blocking if prolonged
samd_monitoring_api FDA 21 CFR §820.80 device acceptance gap
phi_encryption_api HIPAA §164.312(a)(2)(iv) ePHI exposure risk
{
  "name": "HealthTech API Health Monitor",
  "nodes": [
    {
      "id": "1",
      "name": "Every 10 Minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/10 * * * *"
            }
          ]
        }
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Check FHIR API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://fhir.yourapp.com/fhir/R4/metadata",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        450,
        100
      ],
      "continueOnFail": true
    },
    {
      "id": "3",
      "name": "Check HIPAA Audit Log API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://audit.yourapp.com/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        450,
        250
      ],
      "continueOnFail": true
    },
    {
      "id": "4",
      "name": "Check Patient Portal API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://portal.yourapp.com/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        450,
        400
      ],
      "continueOnFail": true
    },
    {
      "id": "5",
      "name": "Check SaMD Monitoring API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://samd.yourapp.com/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        450,
        550
      ],
      "continueOnFail": true
    },
    {
      "id": "6",
      "name": "Check PHI Encryption API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://encrypt.yourapp.com/health",
        "method": "GET",
        "timeout": 5000
      },
      "position": [
        450,
        700
      ],
      "continueOnFail": true
    },
    {
      "id": "7",
      "name": "Evaluate Status",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const ENDPOINTS = [\n  { name: 'fhir_api', law: '21st Cures Act \u00a74004 info blocking IMMINENT risk', severity: 'CRITICAL' },\n  { name: 'hipaa_audit_log_api', law: '45 CFR \u00a7164.312(b) audit control \u2014 PHI access log gap', severity: 'CRITICAL' },\n  { name: 'patient_portal_api', law: 'CMS \u00a7170.315(e) patient access \u2014 information blocking if DOWN', severity: 'HIGH' },\n  { name: 'samd_monitoring_api', law: 'FDA 21 CFR \u00a7820.80 device acceptance \u2014 SaMD performance gap', severity: 'HIGH' },\n  { name: 'phi_encryption_api', law: 'HIPAA \u00a7164.312(a)(2)(iv) encryption \u2014 ePHI at rest/transit risk', severity: 'CRITICAL' }\n];\n\nconst results = $input.all();\nconst alerts = [];\n\nresults.forEach((item, i) => {\n  const ep = ENDPOINTS[i] || { name: 'unknown', law: 'unknown', severity: 'MEDIUM' };\n  const status = item.json.error ? 'DOWN' : (item.json.status >= 200 && item.json.status < 300 ? 'UP' : 'DEGRADED');\n  if (status !== 'UP') {\n    alerts.push({ endpoint: ep.name, status, law: ep.law, severity: ep.severity, ts: new Date().toISOString() });\n  }\n});\n\nif (alerts.length === 0) return [{ json: { status: 'ALL_OK', ts: new Date().toISOString() } }];\nreturn alerts.map(a => ({ json: a }));"
      },
      "position": [
        650,
        400
      ]
    },
    {
      "id": "8",
      "name": "IF Alert",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "notEqual",
              "value2": "ALL_OK"
            }
          ]
        }
      },
      "position": [
        850,
        400
      ]
    },
    {
      "id": "9",
      "name": "PagerDuty + Slack",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#healthtech-ops-critical",
        "text": "\ud83d\udea8 *{{ $json.severity }}* | {{ $json.endpoint }} DOWN\n*Compliance Risk:* {{ $json.law }}\n*Time:* {{ $json.ts }}\nImmediate action required \u2014 PHI availability and HIPAA audit controls at risk."
      },
      "position": [
        1050,
        300
      ]
    },
    {
      "id": "10",
      "name": "Email CTO + CISO",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "cto@yourcompany.com",
        "bcc": "ciso@yourcompany.com",
        "subject": "={{ $json.severity }}: {{ $json.endpoint }} DOWN \u2014 HIPAA/Cures Act Compliance Risk",
        "message": "ALERT: {{ $json.endpoint }} is {{ $json.status }}\n\nCompliance Risk: {{ $json.law }}\nSeverity: {{ $json.severity }}\nDetected: {{ $json.ts }}\n\nImmediate remediation required. PHI access controls and HIPAA audit trail integrity are at risk until this endpoint is restored."
      },
      "position": [
        1050,
        500
      ]
    }
  ],
  "connections": {
    "Every 10 Minutes": {
      "main": [
        [
          {
            "node": "Check FHIR API"
          },
          {
            "node": "Check HIPAA Audit Log API"
          },
          {
            "node": "Check Patient Portal API"
          },
          {
            "node": "Check SaMD Monitoring API"
          },
          {
            "node": "Check PHI Encryption API"
          }
        ]
      ]
    },
    "Check FHIR API": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check HIPAA Audit Log API": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check Patient Portal API": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check SaMD Monitoring API": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check PHI Encryption API": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Evaluate Status": {
      "main": [
        [
          {
            "node": "IF Alert"
          }
        ]
      ]
    },
    "IF Alert": {
      "main": [
        [
          {
            "node": "PagerDuty + Slack"
          },
          {
            "node": "Email CTO + CISO"
          }
        ],
        []
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Setup: Replace endpoint URLs with your actual health-check routes. Add PagerDuty HTTP Request node after Slack for CRITICAL endpoints (fhir_api, phi_encryption_api).

Workflow 4: HIPAA Breach Detection & Notification Pipeline

When a breach event fires — whether from a SIEM alert, a vendor notification, or an internal discovery — the 60-day clock under 45 CFR §164.412 starts at discovery, not at confirmation. Most breach response programs lose days before the clock is formally tracked.

This pipeline starts the clock at intake, classifies the breach type, determines whether media notice is required (>500 affected individuals per §164.406), logs to Postgres, and notifies the privacy team, CCO, legal, and CEO in parallel.

{
  "name": "HIPAA Breach Detection & Notification Pipeline",
  "nodes": [
    {
      "id": "1",
      "name": "Breach Event Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "hipaa-breach-event",
        "httpMethod": "POST"
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Classify & Set Clock",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const event = $json;\nconst now = new Date();\n\nconst BREACH_TYPES = {\n  'UNAUTHORIZED_ACCESS': { severity: 'CRITICAL', ocr_required: true, media_threshold: 500 },\n  'HACKING_CYBERATTACK': { severity: 'CRITICAL', ocr_required: true, media_threshold: 500 },\n  'THEFT_LOSS': { severity: 'HIGH', ocr_required: true, media_threshold: 500 },\n  'IMPROPER_DISPOSAL': { severity: 'HIGH', ocr_required: true, media_threshold: 500 },\n  'INSIDER_THREAT': { severity: 'CRITICAL', ocr_required: true, media_threshold: 500 },\n  'VENDOR_BA_BREACH': { severity: 'HIGH', ocr_required: true, media_threshold: 500 }\n};\n\nconst meta = BREACH_TYPES[event.breach_type] || { severity: 'HIGH', ocr_required: true, media_threshold: 500 };\n\n// 45 CFR \u00a7164.412 \u2014 60 calendar days from discovery\nconst discovery_date = new Date(event.discovery_date || now);\nconst ocr_deadline = new Date(discovery_date);\nocr_deadline.setDate(ocr_deadline.getDate() + 60);\n\n// Days remaining\nconst days_remaining = Math.ceil((ocr_deadline - now) / (1000 * 60 * 60 * 24));\n\nconst affected_count = parseInt(event.affected_individuals) || 0;\nconst media_notice_required = affected_count >= meta.media_threshold;\n\nreturn [{ json: {\n  ...event,\n  breach_id: `BREACH-${Date.now()}`,\n  severity: meta.severity,\n  ocr_deadline: ocr_deadline.toISOString().split('T')[0],\n  days_remaining,\n  media_notice_required,\n  classified_at: now.toISOString(),\n  law: '45 CFR \u00a7164.412 \u2014 60-day OCR notification deadline'\n}}];"
      },
      "position": [
        450,
        300
      ]
    },
    {
      "id": "3",
      "name": "Postgres Log",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "insert",
        "table": "hipaa_breach_log",
        "columns": "breach_id,breach_type,severity,affected_individuals,discovery_date,ocr_deadline,days_remaining,media_notice_required,account_id,classified_at",
        "values": "={{ $json.breach_id }},{{ $json.breach_type }},{{ $json.severity }},{{ $json.affected_individuals }},{{ $json.discovery_date }},{{ $json.ocr_deadline }},{{ $json.days_remaining }},{{ $json.media_notice_required }},{{ $json.account_id }},{{ $json.classified_at }}"
      },
      "position": [
        650,
        300
      ]
    },
    {
      "id": "4",
      "name": "Slack #hipaa-privacy",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#hipaa-privacy-team",
        "text": "\ud83d\udea8 *HIPAA BREACH EVENT* | {{ $json.breach_type }}\n*Breach ID:* {{ $json.breach_id }}\n*Severity:* {{ $json.severity }}\n*Affected Individuals:* {{ $json.affected_individuals }}\n*Discovery Date:* {{ $json.discovery_date }}\n*OCR Deadline (60 days):* {{ $json.ocr_deadline }} ({{ $json.days_remaining }} days remaining)\n*Media Notice Required:* {{ $json.media_notice_required }}\n*Law:* {{ $json.law }}\nActivate breach response protocol immediately."
      },
      "position": [
        850,
        200
      ]
    },
    {
      "id": "5",
      "name": "Email CEO + CPO + Legal",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "privacy@yourcompany.com",
        "bcc": "ceo@yourcompany.com,cpo@yourcompany.com,legal@yourcompany.com",
        "subject": "HIPAA BREACH \u2014 {{ $json.breach_type }} | OCR Deadline {{ $json.ocr_deadline }}",
        "message": "HIPAA Breach Event Detected\n\nBreach ID: {{ $json.breach_id }}\nBreach Type: {{ $json.breach_type }}\nSeverity: {{ $json.severity }}\nAffected Individuals: {{ $json.affected_individuals }}\nDiscovery Date: {{ $json.discovery_date }}\nOCR Notification Deadline (45 CFR \u00a7164.412): {{ $json.ocr_deadline }} \u2014 {{ $json.days_remaining }} days remaining\nMedia Notice Required (>500 affected): {{ $json.media_notice_required }}\n\nRequired actions:\n1. Activate breach response team\n2. Complete breach risk assessment (45 CFR \u00a7164.402 \u2014 4-factor test)\n3. Notify affected individuals within 60 days (\u00a7164.404)\n4. Notify OCR within 60 days (\u00a7164.412)\n5. If media_notice_required=true: notify prominent media outlets in affected state (\u00a7164.406)\n\nBreach ID {{ $json.breach_id }} has been logged to the HIPAA breach register."
      },
      "position": [
        850,
        400
      ]
    },
    {
      "id": "6",
      "name": "Respond 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "parameters": {
        "responseCode": 200,
        "responseBody": "={{ JSON.stringify({ breach_id: $json.breach_id, ocr_deadline: $json.ocr_deadline, days_remaining: $json.days_remaining, status: 'BREACH_LOGGED' }) }}"
      },
      "position": [
        1050,
        300
      ]
    }
  ],
  "connections": {
    "Breach Event Webhook": {
      "main": [
        [
          {
            "node": "Classify & Set Clock"
          }
        ]
      ]
    },
    "Classify & Set Clock": {
      "main": [
        [
          {
            "node": "Postgres Log"
          }
        ]
      ]
    },
    "Postgres Log": {
      "main": [
        [
          {
            "node": "Slack #hipaa-privacy"
          },
          {
            "node": "Email CEO + CPO + Legal"
          }
        ]
      ]
    },
    "Slack #hipaa-privacy": {
      "main": [
        [
          {
            "node": "Respond 200"
          }
        ]
      ]
    },
    "Email CEO + CPO + Legal": {
      "main": [
        [
          {
            "node": "Respond 200"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Breach types covered:

  • UNAUTHORIZED_ACCESS — CRITICAL, 60-day OCR clock
  • HACKING_CYBERATTACK — CRITICAL, 60-day OCR + potential FBI notification
  • THEFT_LOSS — HIGH, 60-day OCR + media if >500
  • IMPROPER_DISPOSAL — HIGH, 60-day OCR
  • INSIDER_THREAT — CRITICAL, 60-day OCR + HR involvement
  • VENDOR_BA_BREACH — HIGH, BA must notify covered entity (§164.410)

SQL for the breach log table:

CREATE TABLE hipaa_breach_log (
  breach_id TEXT PRIMARY KEY,
  breach_type TEXT NOT NULL,
  severity TEXT NOT NULL,
  affected_individuals INTEGER,
  discovery_date DATE NOT NULL,
  ocr_deadline DATE NOT NULL,
  days_remaining INTEGER,
  media_notice_required BOOLEAN DEFAULT false,
  account_id TEXT,
  classified_at TIMESTAMPTZ DEFAULT now(),
  status TEXT DEFAULT 'OPEN'
);
Enter fullscreen mode Exit fullscreen mode

Self-hosting note: This workflow writes to your internal Postgres — breach event data never leaves your environment. Cloud iPaaS routes breach notification metadata through a third-party data center; that routing itself requires a BAA and may create chain-of-custody issues in OCR investigation discovery.

Workflow 5: Weekly HealthTech KPI Briefing

Monday 8 AM ET, to CEO + BCC CCO and CISO. Pulls accounts by tier, MRR, churn, open HIPAA breach items, information blocking complaints, FDA SaMD issues, and TEFCA status.

{
  "name": "Weekly HealthTech KPI Briefing",
  "nodes": [
    {
      "id": "1",
      "name": "Monday 8AM ET",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 13 * * 1"
            }
          ]
        }
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Query Postgres",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  COUNT(*) AS total_accounts,\n  SUM(CASE WHEN tier='LARGE_HEALTH_SYSTEM' THEN 1 ELSE 0 END) AS large_health_system,\n  SUM(CASE WHEN tier='DIGITAL_HEALTH_SAAS' THEN 1 ELSE 0 END) AS digital_health_saas,\n  SUM(CASE WHEN tier='CLINICAL_ANALYTICS_SAAS' THEN 1 ELSE 0 END) AS clinical_analytics,\n  SUM(CASE WHEN tier='HEALTH_IT_VENDOR' THEN 1 ELSE 0 END) AS health_it_vendor,\n  SUM(mrr_usd) AS total_mrr,\n  SUM(CASE WHEN churned_at > NOW() - INTERVAL '7 days' THEN mrr_usd ELSE 0 END) AS churn_mrr_7d\nFROM accounts WHERE active = true;"
      },
      "position": [
        450,
        200
      ]
    },
    {
      "id": "3",
      "name": "Query Breach Log",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  COUNT(*) AS open_breach_items,\n  MIN(days_remaining) AS min_days_to_ocr_deadline,\n  SUM(CASE WHEN media_notice_required THEN 1 ELSE 0 END) AS media_notices_required\nFROM hipaa_breach_log WHERE ocr_deadline >= NOW()::date AND status != 'CLOSED';"
      },
      "position": [
        450,
        400
      ]
    },
    {
      "id": "4",
      "name": "Query Compliance",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  SUM(CASE WHEN deadline_type='ONC_INFORMATION_BLOCKING_COMPLAINT_10_DAY' AND urgency!='OK' THEN 1 ELSE 0 END) AS info_blocking_complaints_open,\n  SUM(CASE WHEN deadline_type='FDA_SAMD_ANNUAL_PERFORMANCE_SUMMARY' AND urgency!='OK' THEN 1 ELSE 0 END) AS samd_items_open,\n  SUM(CASE WHEN deadline_type LIKE 'HIPAA%' AND urgency!='OK' THEN 1 ELSE 0 END) AS hipaa_items_open,\n  SUM(CASE WHEN deadline_type='TEFCA_QHIN_ANNUAL_ATTESTATION' AND urgency!='OK' THEN 1 ELSE 0 END) AS tefca_items_open\nFROM compliance_deadlines WHERE status != 'RESOLVED';"
      },
      "position": [
        450,
        600
      ]
    },
    {
      "id": "5",
      "name": "Build HTML Report",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const acct = $('Query Postgres').first().json;\nconst breach = $('Query Breach Log').first().json;\nconst comp = $('Query Compliance').first().json;\n\nconst html = `\n<h2>FlowKit HealthTech Weekly KPI \u2014 ${new Date().toDateString()}</h2>\n<h3>Accounts & Revenue</h3>\n<table border='1' cellpadding='6'>\n<tr><th>Metric</th><th>Value</th></tr>\n<tr><td>Total Accounts</td><td>${acct.total_accounts}</td></tr>\n<tr><td>Large Health System</td><td>${acct.large_health_system}</td></tr>\n<tr><td>Digital Health SaaS</td><td>${acct.digital_health_saas}</td></tr>\n<tr><td>Clinical Analytics SaaS</td><td>${acct.clinical_analytics}</td></tr>\n<tr><td>Health IT Vendor</td><td>${acct.health_it_vendor}</td></tr>\n<tr><td>Total MRR</td><td>$${acct.total_mrr}</td></tr>\n<tr><td>Churn MRR (7d)</td><td>$${acct.churn_mrr_7d}</td></tr>\n</table>\n<h3>HIPAA Breach Register</h3>\n<table border='1' cellpadding='6'>\n<tr><th>Open Breach Items</th><td>${breach.open_breach_items}</td></tr>\n<tr><th>Min Days to OCR Deadline</th><td style='color:${breach.min_days_to_ocr_deadline < 14 ? 'red' : 'black'}'>${breach.min_days_to_ocr_deadline || 'N/A'}</td></tr>\n<tr><th>Media Notices Required</th><td>${breach.media_notices_required}</td></tr>\n</table>\n<h3>Compliance Snapshot</h3>\n<table border='1' cellpadding='6'>\n<tr><th>HIPAA Open Items</th><td>${comp.hipaa_items_open}</td></tr>\n<tr><th>Info Blocking Complaints Open</th><td>${comp.info_blocking_complaints_open}</td></tr>\n<tr><th>FDA SaMD Items Open</th><td>${comp.samd_items_open}</td></tr>\n<tr><th>TEFCA Items Open</th><td>${comp.tefca_items_open}</td></tr>\n</table>\n`;\nreturn [{ json: { html } }];"
      },
      "position": [
        650,
        400
      ]
    },
    {
      "id": "6",
      "name": "Email CEO + CCO + CISO",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "to": "ceo@yourcompany.com",
        "bcc": "cco@yourcompany.com,ciso@yourcompany.com",
        "subject": "HealthTech Weekly KPI \u2014 {{ $now.format('YYYY-MM-DD') }}",
        "message": "={{ $json.html }}",
        "options": {
          "emailFormat": "html"
        }
      },
      "position": [
        850,
        400
      ]
    }
  ],
  "connections": {
    "Monday 8AM ET": {
      "main": [
        [
          {
            "node": "Query Postgres"
          },
          {
            "node": "Query Breach Log"
          },
          {
            "node": "Query Compliance"
          }
        ]
      ]
    },
    "Query Postgres": {
      "main": [
        [
          {
            "node": "Build HTML Report"
          }
        ]
      ]
    },
    "Query Breach Log": {
      "main": [
        [
          {
            "node": "Build HTML Report"
          }
        ]
      ]
    },
    "Query Compliance": {
      "main": [
        [
          {
            "node": "Build HTML Report"
          }
        ]
      ]
    },
    "Build HTML Report": {
      "main": [
        [
          {
            "node": "Email CEO + CCO + CISO"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The 3 HealthTech Compliance Risks Cloud iPaaS Creates

1. HIPAA Business Associate scope creep. Cloud n8n, Zapier, and Make become business associates the moment ePHI flows through them. Most vendors offer BAAs but the audit log and access control requirements of 45 CFR §164.312 now extend to the iPaaS vendor's infrastructure — infrastructure you don't control.

2. 21st Century Cures Act §4004 information blocking via workflow error handling. If an n8n workflow that serves FHIR data throws an error and returns nothing — rather than returning an error that allows the client to retry — that silence may constitute information blocking. ONC's actor definition (45 CFR §171.102) includes Health IT developers. Your automation layer is part of your §4004 analysis.

3. FDA SaMD intended use and cloud change management. If your n8n workflow routes model output into a clinical decision path, that workflow is part of your SaMD. Cloud iPaaS updates — new n8n Cloud version, new execution engine — happen without your change control documentation. 21 CFR §820.30 requires you to document and validate design changes. Self-hosted n8n gives you version-controlled deployment with change management you can demonstrate to FDA.

Get all 5 workflows

These workflows are available as ready-to-import JSON files at stripeai.gumroad.com.

The AI Customer Support Bot workflow ($29) includes a HIPAA-aware routing layer. The Webhook to Database workflow ($12) includes the SQL schema for the breach log table above. Full bundle (all 15 workflows) at $97.


Have a HealthTech compliance question or a workflow variant to share? Drop it in the comments.

Top comments (0)