DEV Community

Alex Kane
Alex Kane

Posted on

n8n for BioTech/CRO SaaS Vendors: 5 Automations for FDA 21 CFR Part 11, GCP, and CDISC Compliance (Free Workflow JSON)

If your SaaS product touches clinical trial data, electronic records, or adverse event reporting, you already know the compliance stakes. A 483 observation from an FDA inspector or a missed 15-day ICH E2B pharmacovigilance clock is not a recoverable situation — not for your customers, and not for your business.

This article covers 5 production-ready n8n workflows built specifically for BioTech and CRO SaaS vendors. These are the companies building CTMS platforms, eTMF systems, LIMS, pharmacovigilance SaaS, CDISC submission tools, and electronic data capture (EDC) software. If you sell into pharma, biotech, or contract research, these workflows are for you.

All JSON is import-ready. No API calls, no paid add-ons — just n8n.


The Regulatory Context

FDA 21 CFR Part 11 governs electronic records and electronic signatures. If your platform stores trial data, generates audit trails, or enables electronic sign-off, Part 11 applies. The most-cited 483 observations: §11.10(e) audit trail immutability, §11.10(i) periodic validation review, and §11.30 hybrid control procedures.

ICH E6(R2) GCP is the international standard for clinical trial conduct. Sponsors using your SaaS are bound by §5.18 audit requirements — and by §5.5.3, the sponsor is obligated to oversee vendor systems that handle source data.

ICH E2B R3 governs pharmacovigilance Individual Case Safety Reports (ICSRs). Serious unexpected adverse drug reactions must reach FDA and EMA within 15 calendar days — no exceptions. A workflow automation managing this pipeline cannot afford undocumented downtime.

CDISC (Clinical Data Interchange Standards Consortium) defines SDTM and ADaM dataset formats required by FDA for NDA/BLA submissions. Errors in your export pipeline delay drug approvals.

EU CTR Regulation 536/2014 aligns EU clinical trial oversight with a single EMA portal. Article 17 requires SUSAR (Suspected Unexpected Serious Adverse Reactions) submission within 15 days.


Workflow 1: BioTech/Pharma Customer Onboarding Drip

Customer tiers: LARGE_PHARMA / MIDSIZE_PHARMA / BIOTECH_STARTUP / CRO_SPONSOR / ACADEMIC_RESEARCH_ORG / VIRTUAL_PHARMA / CDMO

Compliance flags: CFR_PART11_APPLICABLE / GCP_ICH_E6_REQUIRED / GMP_21_CFR_21x / CDISC_SUBMISSION / PHARMACOVIGILANCE_ICSR / EU_CTR_REQUIRED / ISO_13485_MDR_APPLICABLE

Day 0 email sends tier-appropriate validation checklists. Part 11 customers get §11.10(e) audit trail setup guide immediately. GCP sponsors get ICH E6(R2) §5.5.3 vendor oversight documentation. Day 3 delivers integration tips specific to each compliance flag. Day 7 unlocks advanced features: adverse event pipeline, CDISC submission validator, compliance deadline calendar.

{
  "name": "BioTech/Pharma Customer Onboarding Drip",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "biotech-onboarding",
        "httpMethod": "POST"
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Set Customer Context",
      "type": "n8n-nodes-base.set",
      "parameters": {
        "values": {
          "string": [
            {
              "name": "companyId",
              "value": "={{ $json.company_id }}"
            },
            {
              "name": "tier",
              "value": "={{ $json.tier }}"
            },
            {
              "name": "cfr_part11",
              "value": "={{ $json.cfr_part11_applicable }}"
            },
            {
              "name": "gcp_required",
              "value": "={{ $json.gcp_ich_e6_required }}"
            },
            {
              "name": "cdisc_submission",
              "value": "={{ $json.cdisc_submission }}"
            },
            {
              "name": "pharmacovigilance",
              "value": "={{ $json.pharmacovigilance_icsr }}"
            },
            {
              "name": "eu_ctr",
              "value": "={{ $json.eu_ctr_required }}"
            },
            {
              "name": "iso_13485",
              "value": "={{ $json.iso_13485_mdr_applicable }}"
            }
          ]
        }
      },
      "position": [
        450,
        300
      ]
    },
    {
      "id": "3",
      "name": "Day 0 Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "={{ $json.email }}",
        "subject": "Your 21 CFR Part 11 compliance checklist is ready",
        "message": "Welcome. Your validated system checklist and audit trail configuration guide are attached. Tier: {{ $json.tier }}. If 21 CFR Part 11 applicable: audit trail must be computer-generated, time-stamped, and operator-tagged (\u00a711.10(e)). If GCP ICH E6 required: source data verification protocol in your CSR binder. If CDISC submission: SDTM v1.8/ADaM v1.1 mapping worksheet enclosed."
      },
      "position": [
        650,
        200
      ]
    },
    {
      "id": "4",
      "name": "Wait 3 Days",
      "type": "n8n-nodes-base.wait",
      "parameters": {
        "unit": "days",
        "amount": 3
      },
      "position": [
        650,
        300
      ]
    },
    {
      "id": "5",
      "name": "Day 3 Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "={{ $json.email }}",
        "subject": "Validation protocol tips for your 21 CFR Part 11 system",
        "message": "Day 3 integration guide. 21 CFR Part 11 audit trail: configure immutable logging endpoint now \u2014 FDA inspectors check \u00a711.10(e) chain of custody first. GCP ICH E6(R2): set up sponsor-CRO oversight webhook per \u00a75.5.3 today. CDISC: SDTM dataset validation against FDA conformance rules now available in your dashboard. Pharmacovigilance: enable 15-day ICSR clock trigger."
      },
      "position": [
        850,
        300
      ]
    },
    {
      "id": "6",
      "name": "Wait 4 Days",
      "type": "n8n-nodes-base.wait",
      "parameters": {
        "unit": "days",
        "amount": 4
      },
      "position": [
        850,
        400
      ]
    },
    {
      "id": "7",
      "name": "Day 7 Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "={{ $json.email }}",
        "subject": "Power features: adverse event automation & CDISC submission pipelines",
        "message": "Day 7: advanced features. Adverse event pipeline: 15-day ICH E2B R3 ICSR clock, EMA CTR Art.17 EU SUSAR 15-day track, serious vs non-serious routing. Compliance deadline tracker: 12 deadline types covering FDA Part 11 annual validation review, GCP sponsor audits, IND annual report, PSUR pharmacovigilance, ISO 13485 surveillance. Schedule your validated system walkthrough with our compliance team."
      },
      "position": [
        1050,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Set Customer Context"
          }
        ]
      ]
    },
    "Set Customer Context": {
      "main": [
        [
          {
            "node": "Day 0 Email"
          },
          {
            "node": "Wait 3 Days"
          }
        ]
      ]
    },
    "Wait 3 Days": {
      "main": [
        [
          {
            "node": "Day 3 Email"
          }
        ]
      ]
    },
    "Day 3 Email": {
      "main": [
        [
          {
            "node": "Wait 4 Days"
          }
        ]
      ]
    },
    "Wait 4 Days": {
      "main": [
        [
          {
            "node": "Day 7 Email"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 2: Validated System Health Monitor (21 CFR Part 11)

Polls 5 critical endpoints every 5 minutes:

Endpoint Regulatory Risk
audit_trail_api 21 CFR §11.10(e) — immutable audit trail. Downtime = potential data integrity deviation
esign_service 21 CFR §11.30 — hybrid controls must be in force at all times
gcp_source_data_api ICH E6(R2) §4.9.0 — source data integrity. Inspector checks this first
cdisc_odm_export_api FDA CDISC Technical Conformance Guide — NDA/BLA submission pipeline
pharmacovigilance_api ICH E2B R3 — 15-day ICSR clock. API downtime while an ICSR is pending = reporting risk

Uses $getWorkflowStaticData for state transitions — alerts only on DOWN events (not every poll). CISO and QA Lead notified on any transition.

{
  "name": "Validated System Health Monitor (21 CFR Part 11)",
  "nodes": [
    {
      "id": "1",
      "name": "Every 5 Minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 5
            }
          ]
        }
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Check Audit Trail API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/audit-trail/health",
        "method": "GET",
        "timeout": 10000
      },
      "position": [
        450,
        200
      ]
    },
    {
      "id": "3",
      "name": "Check eSign Service",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/esign/health",
        "method": "GET",
        "timeout": 10000
      },
      "position": [
        450,
        300
      ]
    },
    {
      "id": "4",
      "name": "Check GCP Source Data",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/source-data/health",
        "method": "GET",
        "timeout": 10000
      },
      "position": [
        450,
        400
      ]
    },
    {
      "id": "5",
      "name": "Check CDISC Export",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/cdisc-odm/health",
        "method": "GET",
        "timeout": 10000
      },
      "position": [
        450,
        500
      ]
    },
    {
      "id": "6",
      "name": "Check PV API (15-day clock)",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-platform.com/api/pharmacovigilance/health",
        "method": "GET",
        "timeout": 10000
      },
      "position": [
        450,
        600
      ]
    },
    {
      "id": "7",
      "name": "Evaluate Status",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst now = Date.now();\nconst results = [];\nconst checks = [\n  { name: 'audit_trail_api', label: '21 CFR Part 11 Audit Trail', regulation: '21 CFR \u00a711.10(e) \u2014 immutable audit trail REQUIRED', node: $('Check Audit Trail API').first() },\n  { name: 'esign_service', label: 'Electronic Signature Service', regulation: '21 CFR \u00a711.30 \u2014 hybrid controls must be in force', node: $('Check eSign Service').first() },\n  { name: 'gcp_source_data', label: 'GCP Source Data API', regulation: 'ICH E6(R2) \u00a74.9.0 \u2014 source data integrity', node: $('Check GCP Source Data').first() },\n  { name: 'cdisc_odm_export', label: 'CDISC ODM Export', regulation: 'FDA CDISC Technical Conformance Guide \u2014 submission pipeline', node: $('Check CDISC Export').first() },\n  { name: 'pharmacovigilance_api', label: 'Pharmacovigilance API (15-day clock)', regulation: 'ICH E2B R3 \u2014 15-day ICSR clock. DOWNTIME = FDA reporting risk', node: $('Check PV API (15-day clock)').first() },\n];\nfor (const check of checks) {\n  let status = 'UP';\n  try { const r = check.node.json; if (!r || r.status === 'error' || r.status === 'down') status = 'DOWN'; } catch(e) { status = 'DOWN'; }\n  const prevStatus = staticData[check.name] || 'UP';\n  const justWentDown = (prevStatus === 'UP' && status === 'DOWN');\n  staticData[check.name] = status;\n  if (justWentDown) results.push({ name: check.name, label: check.label, regulation: check.regulation, status: 'DOWN', justWentDown: true });\n}\nreturn results.map(r => ({ json: r }));"
      },
      "position": [
        700,
        400
      ]
    },
    {
      "id": "8",
      "name": "If Down",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.justWentDown }}",
              "value2": true
            }
          ]
        }
      },
      "position": [
        900,
        400
      ]
    },
    {
      "id": "9",
      "name": "Alert CISO + QA Lead",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "ciso@your-company.com",
        "ccEmail": "qa-lead@your-company.com",
        "subject": "CRITICAL: {{ $json.label }} DOWN \u2014 {{ $json.regulation }}",
        "message": "VALIDATED SYSTEM ALERT\nEndpoint: {{ $json.label }}\nStatus: DOWN\nRegulatory risk: {{ $json.regulation }}\nTime: {{ $now.toISO() }}\n\nImmediate action required. 21 CFR Part 11 system downtime may constitute a data integrity event. Log this incident in your deviation management system. If pharmacovigilance API: check all pending ICSRs for 15-day clock breach."
      },
      "position": [
        1100,
        350
      ]
    }
  ],
  "connections": {
    "Every 5 Minutes": {
      "main": [
        [
          {
            "node": "Check Audit Trail API"
          },
          {
            "node": "Check eSign Service"
          },
          {
            "node": "Check GCP Source Data"
          },
          {
            "node": "Check CDISC Export"
          },
          {
            "node": "Check PV API (15-day clock)"
          }
        ]
      ]
    },
    "Check Audit Trail API": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check eSign Service": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check GCP Source Data": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check CDISC Export": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Check PV API (15-day clock)": {
      "main": [
        [
          {
            "node": "Evaluate Status"
          }
        ]
      ]
    },
    "Evaluate Status": {
      "main": [
        [
          {
            "node": "If Down"
          }
        ]
      ]
    },
    "If Down": {
      "main": [
        [
          {
            "node": "Alert CISO + QA Lead"
          }
        ],
        []
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 3: FDA/GCP Compliance Deadline Tracker

Runs weekdays at 8 AM. Covers 12 deadline types:

Deadline Type Reference
FDA_PART11_VALIDATION_ANNUAL 21 CFR §11.10(i) — periodic validation review
GCP_SPONSOR_AUDIT_ANNUAL ICH E6(R2) §5.18 — quality assurance audits
GCP_CRO_AUDIT_ANNUAL ICH E6(R2) §5.18.3 — CRO qualification
IND_ANNUAL_REPORT_DUE 21 CFR §312.33 — IND progress report, 12-month rolling
PHARMACOVIGILANCE_PSUR_ANNUAL ICH E2C(R2) — Periodic Safety Update Report
EU_SUSAR_EXPEDITED_REVIEW EU CTR Art.17 / Reg 536/2014
ISO_13485_SURVEILLANCE_ANNUAL ISO 13485:2016 §8.5.1 — notified body surveillance
SOC2_TYPE2_RENEWAL SOC 2 CC9.2 — subprocessor evidence package
GMP_ANNUAL_PRODUCT_REVIEW 21 CFR §211.180(e) — annual product review
CDISC_VERSION_UPGRADE FDA Technical Conformance Guide version mandate
EU_GMP_ANNEX_11_REVALIDATION EU GMP Annex 11 clause 12 — periodic revalidation
ANNUAL_PENTEST SOC 2 CC7.1 / ISO 27001 A.12.6

Alert levels: OVERDUE / CRITICAL (≤14 days) / URGENT (≤30 days) / WARNING (≤60 days) / NOTICE (≤90 days). Uses alert_sent_date dedup — one alert per deadline per day.

{
  "name": "FDA/GCP Compliance Deadline Tracker",
  "nodes": [
    {
      "id": "1",
      "name": "Weekdays 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1-5"
            }
          ]
        }
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Get Compliance Deadlines",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT id, deadline_type, deadline_date, alert_sent_date, owner_email FROM compliance_deadlines WHERE deadline_type IN ('FDA_PART11_VALIDATION_ANNUAL','GCP_SPONSOR_AUDIT_ANNUAL','GCP_CRO_AUDIT_ANNUAL','IND_ANNUAL_REPORT_DUE','PHARMACOVIGILANCE_PSUR_ANNUAL','EU_SUSAR_EXPEDITED_REVIEW','ISO_13485_SURVEILLANCE_ANNUAL','SOC2_TYPE2_RENEWAL','GMP_ANNUAL_PRODUCT_REVIEW','CDISC_VERSION_UPGRADE','EU_GMP_ANNEX_11_REVALIDATION','ANNUAL_PENTEST') AND deadline_date >= CURRENT_DATE AND deadline_date <= CURRENT_DATE + INTERVAL '90 days'"
      },
      "position": [
        450,
        300
      ]
    },
    {
      "id": "3",
      "name": "Calculate Urgency",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const items = $input.all();\nconst out = [];\nfor (const item of items) {\n  const d = item.json;\n  const days = Math.ceil((new Date(d.deadline_date) - new Date()) / 86400000);\n  const lastSent = d.alert_sent_date ? new Date(d.alert_sent_date) : null;\n  const sentToday = lastSent && lastSent.toDateString() === new Date().toDateString();\n  if (sentToday) continue;\n  let level = '';\n  if (days < 0) level = 'OVERDUE';\n  else if (days <= 14) level = 'CRITICAL';\n  else if (days <= 30) level = 'URGENT';\n  else if (days <= 60) level = 'WARNING';\n  else level = 'NOTICE';\n  out.push({ json: { ...d, days_remaining: days, urgency: level } });\n}\nreturn out;"
      },
      "position": [
        700,
        300
      ]
    },
    {
      "id": "4",
      "name": "Send Alert",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "={{ $json.owner_email }}",
        "subject": "[{{ $json.urgency }}] {{ $json.deadline_type }} \u2014 {{ $json.days_remaining }} days",
        "message": "Compliance deadline approaching:\nType: {{ $json.deadline_type }}\nDeadline: {{ $json.deadline_date }}\nDays remaining: {{ $json.days_remaining }}\nUrgency: {{ $json.urgency }}\n\nFDA/GCP reference:\n- FDA_PART11_VALIDATION_ANNUAL: 21 CFR \u00a711.10(i) periodic validation review required\n- GCP_SPONSOR_AUDIT_ANNUAL: ICH E6(R2) \u00a75.18 sponsor quality assurance audit\n- IND_ANNUAL_REPORT_DUE: 21 CFR \u00a7312.33 IND annual progress report (12-month rolling)\n- PHARMACOVIGILANCE_PSUR_ANNUAL: ICH E2C(R2) Periodic Safety Update Report\n- EU_GMP_ANNEX_11_REVALIDATION: EU GMP Annex 11 clause 12 \u2014 periodic revalidation\n- ISO_13485_SURVEILLANCE_ANNUAL: ISO 13485:2016 \u00a78.5.1 surveillance audit by notified body"
      },
      "position": [
        950,
        300
      ]
    },
    {
      "id": "5",
      "name": "Update alert_sent_date",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE compliance_deadlines SET alert_sent_date = CURRENT_DATE WHERE id = {{ $json.id }}"
      },
      "position": [
        1150,
        300
      ]
    }
  ],
  "connections": {
    "Weekdays 8AM": {
      "main": [
        [
          {
            "node": "Get Compliance Deadlines"
          }
        ]
      ]
    },
    "Get Compliance Deadlines": {
      "main": [
        [
          {
            "node": "Calculate Urgency"
          }
        ]
      ]
    },
    "Calculate Urgency": {
      "main": [
        [
          {
            "node": "Send Alert"
          }
        ]
      ]
    },
    "Send Alert": {
      "main": [
        [
          {
            "node": "Update alert_sent_date"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 4: Adverse Event & Pharmacovigilance Incident Pipeline

Webhook ingests 8 incident types with regulatory clocks:

Incident Type Clock Regulation
SERIOUS_ADVERSE_EVENT_15DAY 360h ICH E2B R3 — ICSR to FDA MedWatch 3500A + EMA EudraVigilance
UNEXPECTED_AE_EXPEDITED 360h ICH E2B R3 — unexpected serious ADR expedited report
GCP_PROTOCOL_DEVIATION_MAJOR 48h ICH E6(R2) §4.5 — sponsor notification + IRB/EC
AUDIT_TRAIL_INTEGRITY_FAILURE 24h 21 CFR §11.10(e) — deviation record in QMS required
ELECTRONIC_SIGNATURE_FAILURE 2h 21 CFR §11.30 — halt affected processes immediately
CDISC_SUBMISSION_ERROR 24h FDA CDISC TCG — NDA/BLA filing timeline risk
EU_SUSAR_15DAY 360h EU CTR Art.17, Reg 536/2014 — EMA EU Portal
SECURITY_BREACH_PHI_21CFR11 72h 21 CFR Part 11 + HIPAA 45 CFR §164.400

Logs to Postgres with incident_id, response_deadline_hours, regulation. Returns structured ACK with deadline so the calling system can track the clock.

{
  "name": "Adverse Event & Pharmacovigilance Incident Pipeline",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "pv-incident",
        "httpMethod": "POST"
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Route by Incident Type",
      "type": "n8n-nodes-base.switch",
      "parameters": {
        "dataType": "string",
        "value1": "={{ $json.incident_type }}",
        "rules": {
          "rules": [
            {
              "value2": "SERIOUS_ADVERSE_EVENT_15DAY",
              "output": 0
            },
            {
              "value2": "UNEXPECTED_AE_EXPEDITED",
              "output": 1
            },
            {
              "value2": "GCP_PROTOCOL_DEVIATION_MAJOR",
              "output": 2
            },
            {
              "value2": "AUDIT_TRAIL_INTEGRITY_FAILURE",
              "output": 3
            },
            {
              "value2": "ELECTRONIC_SIGNATURE_FAILURE",
              "output": 4
            },
            {
              "value2": "CDISC_SUBMISSION_ERROR",
              "output": 5
            },
            {
              "value2": "EU_SUSAR_15DAY",
              "output": 6
            },
            {
              "value2": "SECURITY_BREACH_PHI_21CFR11",
              "output": 7
            }
          ]
        }
      },
      "position": [
        500,
        300
      ]
    },
    {
      "id": "3",
      "name": "Log to Postgres",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO pv_incidents (incident_type, severity, received_at, response_deadline_hours, regulation, raw_payload) VALUES ('{{ $json.incident_type }}', '{{ $json.severity }}', NOW(), CASE '{{ $json.incident_type }}' WHEN 'SERIOUS_ADVERSE_EVENT_15DAY' THEN 360 WHEN 'UNEXPECTED_AE_EXPEDITED' THEN 360 WHEN 'GCP_PROTOCOL_DEVIATION_MAJOR' THEN 48 WHEN 'AUDIT_TRAIL_INTEGRITY_FAILURE' THEN 24 WHEN 'ELECTRONIC_SIGNATURE_FAILURE' THEN 2 WHEN 'CDISC_SUBMISSION_ERROR' THEN 24 WHEN 'EU_SUSAR_15DAY' THEN 360 WHEN 'SECURITY_BREACH_PHI_21CFR11' THEN 72 END, CASE '{{ $json.incident_type }}' WHEN 'SERIOUS_ADVERSE_EVENT_15DAY' THEN 'ICH E2B R3 \u2014 15-day ICSR to FDA/EMA' WHEN 'ELECTRONIC_SIGNATURE_FAILURE' THEN '21 CFR \u00a711.30 \u2014 hybrid controls halt' WHEN 'AUDIT_TRAIL_INTEGRITY_FAILURE' THEN '21 CFR \u00a711.10(e) \u2014 deviation required' WHEN 'EU_SUSAR_15DAY' THEN 'EU CTR Art.17 \u2014 15-day SUSAR to EMA' WHEN 'SECURITY_BREACH_PHI_21CFR11' THEN '21 CFR Part 11 + HIPAA 45 CFR \u00a7164.400' ELSE 'ICH/FDA regulatory clock' END, '{{ $json | toJSON }}'::jsonb) RETURNING id, response_deadline_hours"
      },
      "position": [
        700,
        300
      ]
    },
    {
      "id": "4",
      "name": "Alert Regulatory Affairs",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "regulatory@your-company.com",
        "ccEmail": "cso@your-company.com",
        "subject": "PV INCIDENT {{ $json.incident_type }} \u2014 {{ $json.response_deadline_hours }}h regulatory clock",
        "message": "Pharmacovigilance/regulatory incident received:\nType: {{ $json.incident_type }}\nSeverity: {{ $json.severity }}\nIncident ID: {{ $json.id }}\nRegulation: {{ $json.regulation }}\nResponse deadline: {{ $json.response_deadline_hours }} hours from receipt\nTime received: {{ $now.toISO() }}\n\nSERIOUS_ADVERSE_EVENT_15DAY: 15 calendar days to submit ICSR to FDA via MedWatch 3500A + EMA EudraVigilance\nELECTRONIC_SIGNATURE_FAILURE: halt affected 21 CFR Part 11 processes immediately per \u00a711.30\nAUDIT_TRAIL_INTEGRITY_FAILURE: open deviation record in QMS per 21 CFR \u00a711.10(e)\nEU_SUSAR_15DAY: submit to EMA CTR via the EU Portal within 15 calendar days (Art.17 Reg 536/2014)\nSECURITY_BREACH_PHI_21CFR11: HIPAA breach assessment + 21 CFR Part 11 data integrity impact analysis required"
      },
      "position": [
        950,
        300
      ]
    },
    {
      "id": "5",
      "name": "ACK 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "parameters": {
        "respondWith": "json",
        "responseBody": "={ \"status\": \"received\", \"incident_id\": \"{{ $json.id }}\", \"regulation\": \"{{ $json.regulation }}\", \"response_deadline_hours\": {{ $json.response_deadline_hours }}, \"received_at\": \"{{ $now.toISO() }}\" }"
      },
      "position": [
        1100,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Route by Incident Type"
          }
        ]
      ]
    },
    "Route by Incident Type": {
      "main": [
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ],
        [
          {
            "node": "Log to Postgres"
          }
        ]
      ]
    },
    "Log to Postgres": {
      "main": [
        [
          {
            "node": "Alert Regulatory Affairs"
          },
          {
            "node": "ACK 200"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 5: Weekly BioTech/Pharma KPI Dashboard

Fires Monday 8 AM. Queries platform metrics (customer count by tier, MRR, MRR WoW) and compliance events (ICSRs this week, 21 CFR Part 11 violations, IND overdue, GCP deviations open). Email subject flags [ICSR THIS WEEK — 15-DAY CLOCK ACTIVE] / [21 CFR PART 11 VIOLATION] / [IND ANNUAL REPORT OVERDUE] / [GCP DEVIATION OPEN]. CEO + CSO recipients, Quality team BCC.

{
  "name": "Weekly BioTech/Pharma KPI Dashboard",
  "nodes": [
    {
      "id": "1",
      "name": "Monday 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      },
      "position": [
        250,
        300
      ]
    },
    {
      "id": "2",
      "name": "Query Platform Metrics",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(*) AS total_customers, COUNT(CASE WHEN tier = 'LARGE_PHARMA' THEN 1 END) AS large_pharma, COUNT(CASE WHEN tier = 'CRO_SPONSOR' THEN 1 END) AS cro_count, SUM(mrr_usd) AS total_mrr, SUM(mrr_usd) - LAG(SUM(mrr_usd), 1) OVER (ORDER BY DATE_TRUNC('week', created_at)) AS mrr_wow FROM customers WHERE active = true"
      },
      "position": [
        450,
        200
      ]
    },
    {
      "id": "3",
      "name": "Query Compliance Events",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(CASE WHEN incident_type LIKE '%ADVERSE_EVENT%' AND received_at >= NOW() - INTERVAL '7 days' THEN 1 END) AS icsr_this_week, COUNT(CASE WHEN incident_type = 'AUDIT_TRAIL_INTEGRITY_FAILURE' AND received_at >= NOW() - INTERVAL '7 days' THEN 1 END) AS part11_violations, COUNT(CASE WHEN deadline_type = 'IND_ANNUAL_REPORT_DUE' AND deadline_date < CURRENT_DATE THEN 1 END) AS ind_overdue, COUNT(CASE WHEN incident_type LIKE '%GCP%' AND resolved_at IS NULL THEN 1 END) AS gcp_open FROM pv_incidents, compliance_deadlines"
      },
      "position": [
        450,
        400
      ]
    },
    {
      "id": "4",
      "name": "Build KPI Email",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const platform = $('Query Platform Metrics').first().json;\nconst compliance = $('Query Compliance Events').first().json;\nconst flags = [];\nif (compliance.icsr_this_week > 0) flags.push(`[${compliance.icsr_this_week} ICSR THIS WEEK \u2014 15-DAY CLOCK ACTIVE]`);\nif (compliance.part11_violations > 0) flags.push(`[${compliance.part11_violations} 21 CFR PART 11 VIOLATION]`);\nif (compliance.ind_overdue > 0) flags.push(`[IND ANNUAL REPORT OVERDUE]`);\nif (compliance.gcp_open > 0) flags.push(`[${compliance.gcp_open} GCP DEVIATION OPEN]`);\nconst subject = flags.length > 0 ? `[ACTION] BioTech/Pharma KPI: ${flags.join(' ')}` : 'Weekly BioTech/Pharma KPI Dashboard';\nconst body = `Weekly BioTech/Pharma Platform KPI\\n\\nPlatform:\\n- Total customers: ${platform.total_customers}\\n- Large Pharma: ${platform.large_pharma} | CROs: ${platform.cro_count}\\n- MRR: $${platform.total_mrr}\\n- MRR WoW: $${platform.mrr_wow > 0 ? '+' : ''}${platform.mrr_wow}\\n\\nCompliance Events (7 days):\\n- ICSRs (15-day clock): ${compliance.icsr_this_week}\\n- 21 CFR Part 11 violations: ${compliance.part11_violations}\\n- IND annual reports overdue: ${compliance.ind_overdue}\\n- GCP deviations open: ${compliance.gcp_open}\\n\\nICH E2B R3: 15 calendar days to submit ICSR to FDA/EMA. 21 CFR \u00a711.10(e): audit trail integrity failure = required deviation in QMS.`;\nreturn [{ json: { subject, body } }];"
      },
      "position": [
        700,
        300
      ]
    },
    {
      "id": "5",
      "name": "Send to CEO + CSO",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "toEmail": "ceo@your-company.com",
        "ccEmail": "cso@your-company.com",
        "bccEmail": "quality@your-company.com",
        "subject": "={{ $json.subject }}",
        "message": "={{ $json.body }}"
      },
      "position": [
        950,
        300
      ]
    }
  ],
  "connections": {
    "Monday 8AM": {
      "main": [
        [
          {
            "node": "Query Platform Metrics"
          },
          {
            "node": "Query Compliance Events"
          }
        ]
      ]
    },
    "Query Platform Metrics": {
      "main": [
        [
          {
            "node": "Build KPI Email"
          }
        ]
      ]
    },
    "Query Compliance Events": {
      "main": [
        [
          {
            "node": "Build KPI Email"
          }
        ]
      ]
    },
    "Build KPI Email": {
      "main": [
        [
          {
            "node": "Send to CEO + CSO"
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Why BioTech/Pharma SaaS Vendors Choose Self-Hosted n8n

Risk Self-Hosted n8n Cloud iPaaS (Zapier/Make)
21 CFR §11.10(e) audit trail Immutable log stays in your validated infrastructure Cloud vendor's infrastructure becomes part of your regulated system — must be qualified
ICH E6(R2) §5.5.3 vendor oversight You are the vendor; n8n is internal tooling Cloud iPaaS = regulated vendor requiring full qualification, SOC 2, and sponsor audit access
CDISC submission chain of custody Git-versioned workflows = validated transport audit trail Third-party execution logs outside your validation boundary
EU GMP Annex 11 validation Full validation package available (IQ/OQ/PQ on your stack) Shared cloud infrastructure = incomplete validation package for Annex 11 clause 4
15-day ICSR clock Downtime is your SLA to manage Cloud vendor SLA does not distinguish pharmacovigilance urgency

5 Questions Pharma Procurement Teams Will Ask You

1. Can you produce the 21 CFR Part 11 audit trail for your workflow automations?
Yes — n8n's execution log is stored in your Postgres instance, within your validated infrastructure boundary. Every workflow run is timestamped, operator-tagged, and query-able by FDA inspectors without involving a third-party vendor.

2. How do you ensure the 15-day ICH E2B R3 clock is never missed?
The pharmacovigilance incident pipeline timestamps ICSR receipt on webhook arrival and calculates the 360-hour (15-day) deadline immediately. Both the FDA MedWatch and EMA EudraVigilance submission paths are triggered from the same clock.

3. Is your CDISC export pipeline in scope for our IND/NDA validation package?
The CDISC ODM export workflow runs on your validated n8n instance. You own the execution environment, so you can include n8n in your validation boundary without requiring a separate vendor qualification for a cloud iPaaS.

4. How does your system handle EU GMP Annex 11 periodic revalidation?
The compliance deadline tracker includes EU_GMP_ANNEX_11_REVALIDATION as a tracked deadline type. n8n's workflow version history (git-backed) provides the change control audit trail Annex 11 clause 10 requires.

5. What happens to our pharmacovigilance data if your platform has downtime?
The 5-minute health monitor detects pharmacovigilance API downtime and alerts your CISO and Regulatory Affairs lead immediately. The Postgres incident log captures the outage timestamp so you can demonstrate to FDA that any pending ICSRs were not delayed by your platform.


Get the Full FlowKit Template Pack

These 5 workflows are part of the FlowKit n8n automation template library — 15 production-ready templates covering compliance, operations, and revenue workflows.

Download all 15 templates → stripeai.gumroad.com

Individual templates: $12–$29. Full bundle: $97.


Tagged: n8n, biotech, automation, security. Built for pharma/biotech/CRO SaaS vendors navigating 21 CFR Part 11, ICH E6 GCP, ICH E2B pharmacovigilance, and CDISC submission compliance.

Top comments (0)