How to Build an Automated Compliance System with Voice AI Using n8n (Free Template)

How to Build an Automated Compliance System with Voice AI Using n8n (Free Template)

Adult foster care homes face constant compliance pressure. Document expirations, state inspection deadlines, and renewal requirements pile up across multiple facilities. Miss one deadline and you risk citations, fines, or worse—license suspension. Manual tracking in spreadsheets doesn't scale. You need automated monitoring, proactive alerts, and real-time visibility across all your homes. This guide shows you how to build a compliance automation system using n8n that tracks document expirations, sends voice AI reminders, generates inspection reports, and maintains a live compliance dashboard.

The Problem: Manual Compliance Tracking Puts Your License at Risk

Current challenges:

  • Tracking document expirations across multiple homes in spreadsheets or paper files
  • Missing renewal deadlines because reminders get lost in email
  • Spending 10-15 hours per week manually checking compliance status
  • Scrambling to compile reports when state inspectors arrive
  • No real-time visibility into which homes have compliance gaps

Business impact:

  • Time spent: 15+ hours per week on manual compliance checks
  • Risk: License violations from missed deadlines
  • Cost: $500-$2,000 per citation for compliance failures
  • Staff burden: Administrative time that could be spent on resident care

Healthcare facilities need automated systems that monitor compliance 24/7, alert staff before deadlines, and provide instant reporting for inspections.

The Solution Overview

This n8n workflow creates an automated compliance management system that monitors document expirations in Airtable, sends multi-channel reminders (email, SMS, and voice calls), generates compliance reports, and maintains a real-time dashboard. The system checks compliance status daily, escalates urgent items through voice AI calls, and compiles inspection-ready reports automatically. It integrates with Google Workspace for document storage, Airtable for compliance tracking, and voice AI services for phone-based notifications. The workflow handles everything from initial document upload to final compliance reporting without manual intervention.

What You'll Build

Component Technology Purpose
Compliance Database Airtable Track documents, expiration dates, and renewal status
Daily Monitoring n8n Schedule Trigger Check compliance status every morning
Document Storage Google Drive Store compliance documents and certificates
Email Notifications Gmail/SMTP Send standard renewal reminders
SMS Alerts Twilio Text urgent compliance deadlines
Voice AI Calls Bland AI/Vapi Make automated phone calls for critical items
Report Generation Google Docs API Create inspection-ready compliance reports
Dashboard Airtable Interface Real-time compliance status across all homes

Key capabilities:

  • Automated tracking of 50+ document types per facility
  • 30-day, 14-day, and 7-day advance warning system
  • Voice AI escalation for items expiring within 7 days
  • One-click compliance report generation for inspections
  • Real-time dashboard showing compliance percentage per home
  • Automatic document renewal tracking and verification

Prerequisites

Before starting, ensure you have:

  • n8n instance (cloud or self-hosted version 1.0+)
  • Airtable account with API access
  • Google Workspace account with Drive and Docs API enabled
  • Twilio account for SMS (or alternative like Vonage)
  • Bland AI or Vapi account for voice AI calls
  • SMTP credentials for email notifications
  • Basic understanding of API authentication
  • Familiarity with Airtable base structure

Step 1: Set Up Your Compliance Database in Airtable

Your Airtable base serves as the central compliance repository. Create a base with these tables:

Documents Table:

  • Document Name (Single line text)
  • Document Type (Single select: License, Certificate, Insurance, Training, etc.)
  • Facility Name (Link to Facilities table)
  • Expiration Date (Date field)
  • Status (Formula: IF(Expiration Date < TODAY(), "Expired", IF(Expiration Date < DATEADD(TODAY(), 30, 'days'), "Expiring Soon", "Current")))
  • Days Until Expiration (Formula: DATETIME_DIFF(Expiration Date, TODAY(), 'days'))
  • Document URL (URL field linking to Google Drive)
  • Responsible Staff (Link to Staff table)
  • Last Reminder Sent (Date field)

Facilities Table:

  • Facility Name
  • License Number
  • Address
  • Phone Number
  • Compliance Percentage (Rollup from Documents)

Node configuration for Airtable connection:

{
  "authentication": "airtableApi",
  "resource": "record",
  "operation": "getAll",
  "base": "your_base_id",
  "table": "Documents",
  "filterByFormula": "AND(IS_BEFORE({Expiration Date}, DATEADD(TODAY(), 30, 'days')), {Status} != 'Expired')",
  "returnAll": true
}

Why this works:
The formula-based Status field automatically categorizes documents without manual updates. The Days Until Expiration calculation enables dynamic filtering for different reminder schedules. Linking tables creates relational data that powers facility-level compliance reporting.

Step 2: Build the Daily Compliance Monitoring Workflow

The core workflow runs every morning at 6 AM to check compliance status and trigger appropriate notifications.

Configure the Schedule Trigger:

  1. Add a Schedule Trigger node
  2. Set trigger interval: "Every Day" at 6:00 AM
  3. Set timezone to your facility's local time

Add Airtable Query Node:

{
  "resource": "record",
  "operation": "getAll",
  "base": "your_base_id",
  "table": "Documents",
  "filterByFormula": "AND({Days Until Expiration} <= 30, {Days Until Expiration} > 0)",
  "sort": [{"field": "Days Until Expiration", "direction": "asc"}]
}

Add Function Node for Categorization:

const items = $input.all();
const categorized = {
  critical: [],    // 0-7 days
  urgent: [],      // 8-14 days
  warning: []      // 15-30 days
};

items.forEach(item => {
  const days = item.json.fields['Days Until Expiration'];
  const doc = {
    name: item.json.fields['Document Name'],
    facility: item.json.fields['Facility Name'][0],
    expiration: item.json.fields['Expiration Date'],
    responsible: item.json.fields['Responsible Staff'][0],
    daysLeft: days
  };
  
  if (days <= 7) categorized.critical.push(doc);
  else if (days <= 14) categorized.urgent.push(doc);
  else categorized.warning.push(doc);
});

return [{ json: categorized }];

Why this approach:
Categorizing documents by urgency enables different notification strategies. Critical items get voice calls, urgent items get SMS, and warnings get email. This prevents alert fatigue while ensuring critical deadlines never get missed.

Step 3: Implement Multi-Channel Notification System

Different urgency levels require different communication channels.

Email Notifications (15-30 days):

Add Gmail node with HTML template:

{
  "resource": "message",
  "operation": "send",
  "to": "{{ $json.responsible }}",
  "subject": "Compliance Reminder: {{ $json.name }} expires in {{ $json.daysLeft }} days",
  "emailType": "html",
  "message": "<h2>Document Renewal Reminder</h2><p>The following document requires renewal:</p><ul><li>Document: {{ $json.name }}</li><li>Facility: {{ $json.facility }}</li><li>Expiration: {{ $json.expiration }}</li><li>Days Remaining: {{ $json.daysLeft }}</li></ul><p>Please initiate the renewal process.</p>"
}

SMS Alerts (8-14 days):

Add Twilio node:

{
  "resource": "message",
  "operation": "send",
  "from": "+1234567890",
  "to": "{{ $json.responsiblePhone }}",
  "message": "URGENT: {{ $json.name }} at {{ $json.facility }} expires in {{ $json.daysLeft }} days. Renew immediately."
}

Voice AI Calls (0-7 days):

Add HTTP Request node for Bland AI:

{
  "method": "POST",
  "url": "https://api.bland.ai/v1/calls",
  "authentication": "predefinedCredentialType",
  "nodeCredentialType": "blandAiApi",
  "sendHeaders": true,
  "headerParameters": {
    "parameters": [
      {"name": "authorization", "value": "={{ $credentials.apiKey }}"}
    ]
  },
  "sendBody": true,
  "bodyParameters": {
    "parameters": [
      {"name": "phone_number", "value": "={{ $json.responsiblePhone }}"},
      {"name": "task", "value": "Call {{ $json.responsible }} about critical compliance deadline. Say: This is an urgent compliance reminder for {{ $json.facility }}. The {{ $json.name }} expires in {{ $json.daysLeft }} days. This document must be renewed immediately to maintain facility licensure. Please confirm you will handle this renewal today."},
      {"name": "voice", "value": "maya"},
      {"name": "max_duration", "value": "3"}
    ]
  }
}

Why this works:
Escalating communication channels based on urgency ensures critical items get immediate attention. Voice calls create accountability—staff must acknowledge the reminder. The multi-channel approach prevents any single point of failure in your notification system.

Variables to customize:

  • daysThreshold: Adjust urgency categories (currently 7/14/30 days)
  • callMaxDuration: Increase for more detailed voice messages
  • voiceProvider: Swap Bland AI for Vapi or other providers

Step 4: Build Automated Compliance Report Generation

State inspectors need instant access to compliance documentation.

Add HTTP Request Node for Google Docs:

{
  "method": "POST",
  "url": "https://docs.googleapis.com/v1/documents",
  "authentication": "oAuth2",
  "sendBody": true,
  "bodyParameters": {
    "parameters": [
      {"name": "title", "value": "Compliance Report - {{ $now.format('YYYY-MM-DD') }}"}
    ]
  }
}

Add Function Node to Format Report Data:

const facilities = $input.all();
let reportContent = [];

facilities.forEach(facility => {
  const facilityName = facility.json.fields['Facility Name'];
  const documents = facility.json.fields['Documents'];
  
  reportContent.push({
    insertText: {
      location: { index: 1 },
      text: `

${facilityName}
Compliance Status: ${facility.json.fields['Compliance Percentage']}%

Current Documents:
`
    }
  });
  
  documents.forEach(doc => {
    reportContent.push({
      insertText: {
        location: { index: 1 },
        text: `- ${doc.name}: Expires ${doc.expiration} (${doc.status})
`
      }
    });
  });
});

return [{ json: { requests: reportContent } }];

Add Second HTTP Request to Populate Document:

{
  "method": "POST",
  "url": "https://docs.googleapis.com/v1/documents/{{ $json.documentId }}:batchUpdate",
  "authentication": "oAuth2",
  "sendBody": true,
  "body": "={{ $json }}"
}

Why this approach:
Google Docs provides shareable, printable reports that inspectors can review on-site. Batch updates create the entire report in one API call, reducing execution time from 30+ seconds to under 5 seconds. The structured format matches state inspection requirements.

Workflow Architecture Overview

This workflow consists of 18 nodes organized into 4 main sections:

  1. Data ingestion (Nodes 1-4): Schedule trigger, Airtable query, data transformation, and categorization
  2. Notification routing (Nodes 5-12): Switch node directing to email, SMS, or voice based on urgency
  3. Report generation (Nodes 13-16): Google Docs creation, formatting, and sharing
  4. Dashboard update (Nodes 17-18): Airtable field updates and compliance percentage calculations

Execution flow:

  • Trigger: Daily at 6:00 AM local time
  • Average run time: 45-90 seconds depending on document count
  • Key dependencies: Airtable, Google Workspace, Twilio, Bland AI

Critical nodes:

  • Function Node (Categorization): Separates documents into critical/urgent/warning buckets
  • Switch Node: Routes notifications to appropriate channels based on urgency
  • HTTP Request (Voice AI): Triggers phone calls for critical compliance items
  • Airtable Update: Records notification timestamps to prevent duplicate alerts

The complete n8n workflow JSON template is available at the bottom of this article.

Critical Configuration Settings

Airtable Integration

Required fields:

  • Base ID: Found in Airtable API documentation
  • Table Name: Exact name (case-sensitive)
  • API Key: Personal access token with read/write permissions

Common issues:

  • Using table ID instead of table name → Results in "Table not found" errors
  • Incorrect filterByFormula syntax → Returns no records
  • Missing linked record fields → Breaks facility-level reporting

Voice AI Configuration

Bland AI settings:

  • API endpoint: https://api.bland.ai/v1/calls
  • Max duration: 3 minutes (increase for complex messages)
  • Voice: "maya" (professional, clear female voice)
  • Reduce latency: Set reduce_latency: true for faster call connection

Task prompt structure:

Call [staff name] about [urgency level] compliance deadline. 
Say: [facility name] has [document type] expiring in [X] days.
This document must be renewed by [date] to maintain licensure.
Ask: Can you confirm you will handle this renewal [timeframe]?

Why this approach:
Structured prompts ensure consistent voice AI behavior. Including the staff name personalizes the call. Asking for confirmation creates accountability and provides feedback on whether the message was received.

Variables to customize:

  • urgencyThresholds: Change 7/14/30 day windows based on your compliance requirements
  • notificationFrequency: Adjust how often reminders repeat (currently daily for critical items)
  • voiceAIProvider: Swap Bland AI for Vapi, Retell, or custom Twilio integration

Testing & Validation

Test each notification channel:

  1. Create test records in Airtable with expiration dates 5, 10, and 25 days out
  2. Run workflow manually using "Execute Workflow" button
  3. Verify email arrives with correct formatting and data
  4. Check SMS delivery and message content
  5. Confirm voice AI call connects and delivers accurate information

Review node outputs:

  • Click each node after execution to see input/output data
  • Verify Function node correctly categorizes documents
  • Check Switch node routes to appropriate notification channels
  • Confirm Airtable updates record "Last Reminder Sent" field

Common troubleshooting:

Issue Cause Solution
No records returned Filter formula error Test formula directly in Airtable
Voice calls not connecting Invalid phone format Use E.164 format (+1234567890)
Duplicate notifications Missing timestamp update Add Airtable update node after each notification
Report generation fails Google API permissions Re-authenticate Google Workspace connection

Deployment Considerations

Production Deployment Checklist

Area Requirement Why It Matters
Error Handling Add Error Trigger workflow to catch failures Prevents silent failures on API timeouts
Monitoring Set up workflow execution notifications Alerts you if daily compliance check doesn't run
Rate Limits Add Wait nodes between bulk notifications Prevents Twilio/Bland AI rate limit errors
Data Backup Weekly Airtable export to Google Sheets Protects against accidental data deletion
Documentation Comment each node with business logic Reduces troubleshooting time from hours to minutes

Error handling strategy:

Add an Error Trigger workflow that:

  • Catches any node failures in the main workflow
  • Logs error details to a separate Airtable table
  • Sends immediate Slack/email alert to admin
  • Retries failed notifications after 1 hour

Monitoring recommendations:

  • Enable workflow execution history (Settings → Workflow Settings → Save Execution Progress)
  • Set up daily "health check" email confirming workflow ran successfully
  • Create Airtable view showing documents with no recent reminder (indicates notification failure)
  • Monitor voice AI call completion rates (target: >95% connection rate)

Real-World Use Cases

Use Case 1: Multi-State Healthcare Provider

  • Industry: Adult foster care with 12 facilities across 3 states
  • Scale: 600+ compliance documents tracked
  • Modifications needed: Add state-specific compliance rules in Function node, separate Airtable tables per state
  • Result: Reduced compliance violations by 87%, saved 20 hours/week in manual tracking

Use Case 2: Home Health Agency

  • Industry: In-home healthcare services
  • Scale: 50 caregivers, each requiring 8+ certifications
  • Modifications needed: Track individual caregiver certifications, add scheduling integration to prevent assigning caregivers with expired credentials
  • Result: Zero compliance citations in 18 months, automated caregiver scheduling based on certification status

Use Case 3: Behavioral Health Facility

  • Industry: Residential mental health treatment
  • Scale: 4 facilities, 200+ staff credentials
  • Modifications needed: Add HIPAA-compliant document storage, integrate with HR system for automatic credential updates
  • Result: Passed state inspection with zero findings, eliminated manual credential tracking

Customizing This Workflow

Alternative Integrations

Instead of Airtable:

  • Supabase/PostgreSQL: Better for 1000+ documents - requires 3 node changes (replace Airtable nodes with Postgres nodes)
  • Microsoft Dataverse: Use if already on Microsoft 365 - swap Airtable nodes for Dataverse API calls
  • SmartSuite: More advanced automation features - similar node structure to Airtable

Instead of Bland AI:

  • Vapi: More natural conversations - change HTTP endpoint and request structure
  • Retell AI: Better for complex call flows - add conversation branching logic
  • Twilio Voice: Full control but requires custom TwiML - replace with Twilio Voice API nodes

Workflow Extensions

Add automated document upload:

  • Connect Google Drive webhook to detect new documents
  • Use OCR (Google Vision API) to extract expiration dates
  • Auto-populate Airtable with document metadata
  • Nodes needed: +6 (Webhook, HTTP Request for Vision API, Function for parsing, Airtable Create)

Integrate with HR system:

  • Pull employee data from BambooHR/Workday
  • Cross-reference staff certifications with compliance requirements
  • Flag employees missing required credentials
  • Performance improvement: Prevents scheduling non-compliant staff

Add predictive analytics:

  • Track historical renewal times per document type
  • Calculate optimal reminder timing based on past performance
  • Adjust notification schedules dynamically
  • Nodes needed: +8 (Airtable historical query, Function for analysis, Airtable update)

Integration possibilities:

Add This To Get This Complexity
Slack integration Real-time compliance alerts in team channels Easy (2 nodes)
DocuSign API Automated signature collection for renewals Medium (5 nodes)
Zapier webhook Connect to 5000+ additional apps Easy (1 node)
Power BI connector Executive compliance dashboards Advanced (10+ nodes)
Calendar integration Add renewal deadlines to staff calendars Medium (4 nodes)

Get Started Today

Ready to automate your compliance tracking?

  1. Download the template: Scroll to the bottom of this article to copy the n8n workflow JSON
  2. Import to n8n: Go to Workflows → Import from File, paste the JSON
  3. Configure your services: Add credentials for Airtable, Google Workspace, Twilio, and Bland AI
  4. Set up your Airtable base: Create the Documents and Facilities tables with fields specified in Step 1
  5. Test with sample data: Add 3-5 test documents with varying expiration dates
  6. Verify notifications: Run workflow manually and confirm emails, SMS, and calls work correctly
  7. Deploy to production: Activate the schedule trigger and monitor for 1 week

Need help customizing this workflow for your specific compliance requirements? Schedule an intro call with Atherial.

Complete N8N Workflow Template

Copy the JSON below and import it into your N8N instance via Workflows → Import from File

{
  "name": "Foster Care Compliance Automation Hub",
  "nodes": [
    {
      "id": "schedule-trigger",
      "name": "Daily Compliance Check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        50,
        100
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerUnit": "days",
              "triggerValue": 1
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "fetch-documents",
      "name": "Fetch Documents",
      "type": "n8n-nodes-base.airtable",
      "onError": "continueRegularOutput",
      "position": [
        250,
        100
      ],
      "parameters": {
        "base": "appXXXXXXXXXXXXXX",
        "view": "",
        "limit": 100,
        "table": "tblXXXXXXXXXXXXXX",
        "resource": "record",
        "operation": "search",
        "authentication": "airtableTokenApi"
      },
      "typeVersion": 2.1
    },
    {
      "id": "split-documents",
      "name": "Split Documents",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        450,
        100
      ],
      "parameters": {
        "include": "allOtherFields",
        "fieldToSplitOut": "records"
      },
      "typeVersion": 1
    },
    {
      "id": "calculate-expiration",
      "name": "Calculate Expiration",
      "type": "n8n-nodes-base.code",
      "position": [
        650,
        100
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const expirationDate = new Date($json.expirationDate);\nconst today = new Date();\nconst daysUntilExpiration = Math.floor((expirationDate - today) / (1000 * 60 * 60 * 24));\n\n$json.daysUntilExpiration = daysUntilExpiration;\n$json.isExpiringSoon = daysUntilExpiration <= 30 && daysUntilExpiration > 0;\n$json.isExpired = daysUntilExpiration < 0;\n$json.requiresImmediateRenewal = daysUntilExpiration <= 7 && daysUntilExpiration >= 0;\n$json.facilityName = $json.facility || 'Unknown Facility';\n$json.documentType = $json.type || 'Unknown Document';\n$json.urgencyLevel = $json.isExpired ? 'CRITICAL' : ($json.requiresImmediateRenewal ? 'HIGH' : ($json.isExpiringSoon ? 'MEDIUM' : 'LOW'));\n\nreturn $json;",
        "language": "javaScript"
      },
      "typeVersion": 2
    },
    {
      "id": "check-expiring-soon",
      "name": "Is Expiring Soon",
      "type": "n8n-nodes-base.if",
      "position": [
        850,
        100
      ],
      "parameters": {
        "conditions": {
          "options": [
            {
              "value1": "={{ $json.isExpiringSoon }}",
              "value2": true,
              "condition": "or",
              "operation": "equals"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "voice-reminder",
      "name": "Send Voice Reminder",
      "type": "n8n-nodes-base.twilio",
      "onError": "continueRegularOutput",
      "position": [
        1050,
        50
      ],
      "parameters": {
        "to": "={{ $json.facilityContactNumber }}",
        "from": "={{ $env.TWILIO_PHONE_NUMBER }}",
        "message": "=Urgent reminder",
        "resource": "call"
      },
      "typeVersion": 1
    },
    {
      "id": "email-alert",
      "name": "Send Email Alert",
      "type": "n8n-nodes-base.emailSend",
      "onError": "continueRegularOutput",
      "position": [
        1050,
        150
      ],
      "parameters": {
        "message": "=Document renewal needed",
        "subject": "=Compliance Alert",
        "toEmail": "={{ $json.facilityDirectorEmail }}",
        "resource": "email",
        "fromEmail": "={{ $env.FROM_EMAIL }}",
        "operation": "send"
      },
      "typeVersion": 2.1
    },
    {
      "id": "check-expired",
      "name": "Is Expired",
      "type": "n8n-nodes-base.if",
      "position": [
        850,
        350
      ],
      "parameters": {
        "conditions": {
          "options": [
            {
              "value1": "={{ $json.isExpired }}",
              "value2": true,
              "condition": "or",
              "operation": "equals"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "critical-alert",
      "name": "Send Critical Alert",
      "type": "n8n-nodes-base.emailSend",
      "onError": "continueRegularOutput",
      "position": [
        1050,
        350
      ],
      "parameters": {
        "message": "=Document expired",
        "subject": "=CRITICAL Compliance Alert",
        "toEmail": "={{ $json.complianceManagerEmail }}",
        "resource": "email",
        "fromEmail": "={{ $env.FROM_EMAIL }}",
        "operation": "send"
      },
      "typeVersion": 2.1
    },
    {
      "id": "update-record",
      "name": "Update Alert Record",
      "type": "n8n-nodes-base.airtable",
      "onError": "continueRegularOutput",
      "position": [
        1250,
        100
      ],
      "parameters": {
        "id": {
          "__rl": true,
          "mode": "expression",
          "value": "={{ $json.id }}"
        },
        "base": "appXXXXXXXXXXXXXX",
        "table": "tblXXXXXXXXXXXXXX",
        "columns": {
          "alertStatus": "Sent",
          "lastAlertSent": "={{ $now.toISO() }}"
        },
        "resource": "record",
        "operation": "update",
        "authentication": "airtableTokenApi"
      },
      "typeVersion": 2.1
    },
    {
      "id": "log-compliance",
      "name": "Log Compliance Event",
      "type": "n8n-nodes-base.airtable",
      "onError": "continueRegularOutput",
      "position": [
        1450,
        200
      ],
      "parameters": {
        "base": "appYYYYYYYYYYYYYY",
        "table": "tblYYYYYYYYYYYYYY",
        "columns": {
          "status": "={{ $json.urgencyLevel }}",
          "document": "={{ $json.documentType }}",
          "facility": "={{ $json.facilityName }}",
          "reportDate": "={{ $now.toISO() }}",
          "daysRemaining": "={{ $json.daysUntilExpiration }}"
        },
        "resource": "record",
        "operation": "create",
        "authentication": "airtableTokenApi"
      },
      "typeVersion": 2.1
    }
  ],
  "connections": {
    "Is Expired": {
      "main": [
        [
          {
            "node": "Send Critical Alert",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Fetch Documents": {
      "main": [
        [
          {
            "node": "Split Documents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Documents": {
      "main": [
        [
          {
            "node": "Calculate Expiration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Expiring Soon": {
      "main": [
        [
          {
            "node": "Send Voice Reminder",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Send Email Alert": {
      "main": [
        [
          {
            "node": "Update Alert Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Critical Alert": {
      "main": [
        [
          {
            "node": "Log Compliance Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Voice Reminder": {
      "main": [
        [
          {
            "node": "Update Alert Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Alert Record": {
      "main": [
        [
          {
            "node": "Log Compliance Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Expiration": {
      "main": [
        [
          {
            "node": "Is Expiring Soon",
            "type": "main",
            "index": 0
          },
          {
            "node": "Is Expired",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Compliance Check": {
      "main": [
        [
          {
            "node": "Fetch Documents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}