DEV Community

Alex Kane
Alex Kane

Posted on

n8n for LogisticsTech & FreightTech SaaS Vendors: 5 Automations for FMCSA, PHMSA, CBP ISF, IATA DGR, and FMC Compliance

If you run a LogisticsTech or FreightTech SaaS platform — TMS, freight brokerage software, customs tech, last-mile delivery, hazmat compliance — you're sitting at the intersection of some of the most time-sensitive compliance clocks in federal law.

PHMSA §171.16(a): 30 minutes to notify NRC after hazmat incident discovery. Not 30 days. 30 minutes.

CBP ISF 10+2: 24 hours before vessel departure. Miss it: $5,000–$10,000 per shipment, cargo holds, possible bond revocation.

IATA DGR §2.8.2: Undeclared dangerous goods — IMMEDIATE airline notification. An aircraft can't depart.

FMCSA §395.8(k): ELD 7-day rolling HOS window — continuous. A driver's log is a live federal record.

When your logistics platform routes freight data through Zapier or Make, every one of these records sits on a cloud vendor's servers. When PHMSA, CBP, DOT, or TSA issues a subpoena, they send it to the vendor — not to you. You find out after.

Here are 5 n8n workflows built specifically for LogisticsTech and FreightTech SaaS vendors.


The regulatory landscape for logistics SaaS vendors

Seven customer tiers, each with a distinct compliance profile:

  • FREIGHT_BROKER_SAAS_VENDOR
  • TMS_PLATFORM_VENDOR
  • CUSTOMS_BROKER_SAAS_VENDOR
  • LAST_MILE_DELIVERY_SAAS
  • COLD_CHAIN_LOGISTICS_SAAS
  • HAZMAT_COMPLIANCE_SAAS
  • LOGISTICSTECH_STARTUP

Seven compliance flags that determine which federal clocks apply:

  • FMCSA_ELD_COVERED_CARRIER
  • PHMSA_HAZMAT_CARRIER
  • CBP_ISF_REQUIRED
  • IATA_DGR_SUBJECT
  • FMC_NVOCC_LICENSED
  • TSA_CCSP_CERTIFIED
  • SOC2_REQUIRED

Workflow 1: Tier-Segmented Customer Onboarding

Every customer tier has a different compliance exposure. A customs broker SaaS vendor needs to know about CBP ISF 10+2 and power-of-attorney data sovereignty on Day 0. A hazmat compliance SaaS vendor needs the PHMSA 30-minute clock framed at onboarding — not after their first incident.

{
  "name": "LogisticsTech Tier-Segmented Customer Onboarding",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "logisticstech-signup",
        "responseMode": "lastNode"
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Code - Classify Tier",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst tier = data.customer_tier || 'LOGISTICSTECH_STARTUP';\nconst flags = [];\nif (['FREIGHT_BROKER_SAAS_VENDOR','TMS_PLATFORM_VENDOR'].includes(tier)) flags.push('FMCSA_ELD_COVERED_CARRIER');\nif (['HAZMAT_COMPLIANCE_SAAS','TMS_PLATFORM_VENDOR'].includes(tier)) flags.push('PHMSA_HAZMAT_CARRIER');\nif (['CUSTOMS_BROKER_SAAS_VENDOR','TMS_PLATFORM_VENDOR'].includes(tier)) flags.push('CBP_ISF_REQUIRED');\nif (['CUSTOMS_BROKER_SAAS_VENDOR','FREIGHT_BROKER_SAAS_VENDOR'].includes(tier)) flags.push('FMC_NVOCC_LICENSED');\nif (['LAST_MILE_DELIVERY_SAAS'].includes(tier)) flags.push('TSA_CCSP_CERTIFIED');\nconst msgs = {\n  'FREIGHT_BROKER_SAAS_VENDOR': 'Note: FMCSA \u00a7395.8(k) requires ELD records accessible for 6 months. Your platform routes driver HOS data \u2014 routing through cloud iPaaS creates a DOT audit target outside your custody.',\n  'TMS_PLATFORM_VENDOR': 'Note: FMCSA HOS 7-day rolling window, PHMSA \u00a7172 hazmat 30-min notification, CBP ISF 24h pre-departure \u2014 your TMS sits at the intersection of three federal clocks.',\n  'CUSTOMS_BROKER_SAAS_VENDOR': 'Note: CBP ISF 10+2 data (HTS codes, supplier names, commercial invoice values) routing through Zapier/Make = data egress outside your CBP bond boundary. Power of attorney data is privileged.',\n  'LAST_MILE_DELIVERY_SAAS': 'Note: TSA CCSP chain-of-custody records and PHMSA last-mile hazmat manifests are audit targets \u2014 cloud automation vendor as subpoena destination.',\n  'COLD_CHAIN_LOGISTICS_SAAS': 'Note: FDA FSMA \u00a7204 cold chain KDE/CTE records + PHMSA temperature-sensitive hazmat \u2014 24h traceability requirement creates continuous data flow that must stay in your custody.',\n  'HAZMAT_COMPLIANCE_SAAS': 'Note: PHMSA \u00a7172.604 immediate notification + ERG data + shipping paper generation \u2014 hazmat incident data routed through cloud iPaaS = discoverable in litigation before your legal team knows.',\n  'LOGISTICSTECH_STARTUP': 'Welcome to FlowKit. Your onboarding is set up. Reach out anytime.'\n};\nreturn [{json: {customer_id: data.customer_id, email: data.email, company: data.company, tier, flags, onboarding_note: msgs[tier] || msgs['LOGISTICSTECH_STARTUP']}}];"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Gmail - Day 0 Welcome",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "={{$json.email}}",
        "subject": "={{$json.company}} is live on FlowKit \u2014 FMCSA/PHMSA/CBP compliance automations ready",
        "message": "={{$json.onboarding_note}}\n\nYour FlowKit workflows are ready to activate."
      },
      "position": [
        680,
        300
      ]
    },
    {
      "id": "4",
      "name": "Sheets - Log Onboarding",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "append",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "Onboarding!A:G",
        "dataMode": "autoMapInputData"
      },
      "position": [
        900,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Code - Classify Tier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Classify Tier": {
      "main": [
        [
          {
            "node": "Gmail - Day 0 Welcome",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Day 0 Welcome": {
      "main": [
        [
          {
            "node": "Sheets - Log Onboarding",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 2: FMCSA/PHMSA/CBP/IATA/FMC Compliance Deadline Tracker

Twelve compliance deadlines, daily triage at 7AM, four urgency tiers (OVERDUE → IMMEDIATE → CRITICAL → URGENT). The shortest clocks:

Deadline Type Clock Regulation
PHMSA Hazmat Incident 30 minutes 49 CFR §171.16(a)
IATA DGR Undeclared IMMEDIATE IATA DGR §2.8.2
CBP ISF 10+2 24 hours before vessel CBP 19 CFR §§1-505.3
FMCSA ELD 7-Day Window Continuous rolling 49 CFR §395.8(k)
FMC NVOCC Tariff Filing 30 days prospective 46 USC §40501
DOT Drug Test Annual March 15 49 CFR §382.603
TSA CCSP Annual Audit Annual 49 CFR §1544.228
{
  "name": "LogisticsTech FMCSA/PHMSA/CBP/IATA/FMC Compliance Deadline Tracker",
  "nodes": [
    {
      "id": "1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "readRows",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "ComplianceDeadlines!A:F"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Code - Triage",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const rows = $input.all().map(i => i.json);\nconst today = new Date();\nconst deadlines = [\n  {type:'FMCSA_ELD_7DAY_LOG_RETENTION',days:7,description:'FMCSA \u00a7395.8(k) 7-day HOS rolling window \u2014 driver log records must be current',clock:'CONTINUOUS'},\n  {type:'PHMSA_HAZMAT_INCIDENT_30MIN',days:0,description:'PHMSA 49 CFR \u00a7171.16(a) \u2014 telephonic notification within 30 min of hazmat incident discovery',clock:'30_MINUTES'},\n  {type:'CBP_ISF_10PLUS2_24H',days:1,description:'CBP ISF 10+2 \u2014 Importer Security Filing due 24h before vessel departure',clock:'24_HOURS'},\n  {type:'IATA_DGR_UNDECLARED_IMMEDIATE',days:0,description:'IATA DGR \u00a72.8.2 \u2014 undeclared dangerous goods notification IMMEDIATE to airline',clock:'IMMEDIATE'},\n  {type:'FMC_NVOCC_TARIFF_FILING',days:30,description:'FMC 46 USC \u00a740501 \u2014 NVOCC tariff rates must be published 30 days before effective date',clock:'30_DAYS'},\n  {type:'TSA_CCSP_ANNUAL_AUDIT',days:365,description:'TSA CCSP \u00a71544.228 \u2014 certified cargo screening program annual audit renewal',clock:'ANNUAL'},\n  {type:'FMCSA_SAFETY_FITNESS_ANNUAL',days:365,description:'FMCSA 49 CFR \u00a7385.3 \u2014 motor carrier safety fitness determination annual review',clock:'ANNUAL'},\n  {type:'DOT_DRUG_TESTING_ANNUAL',days:365,description:'DOT 49 CFR \u00a7382.603 \u2014 FMCSA drug/alcohol testing MIS annual submission March 15',clock:'ANNUAL'},\n  {type:'PHMSA_HAZMAT_REGISTRATION_ANNUAL',days:365,description:'PHMSA 49 CFR \u00a7107.601 \u2014 hazmat shipper/carrier annual registration renewal',clock:'ANNUAL'},\n  {type:'CBP_ACE_PORTAL_BOND_ANNUAL',days:365,description:'CBP 19 CFR \u00a7113 \u2014 continuous bond annual review and sufficiency check',clock:'ANNUAL'},\n  {type:'SOC2_TYPE2_RENEWAL',days:365,description:'SOC2 Type II annual audit renewal for enterprise logistics platform customers',clock:'ANNUAL'},\n  {type:'ANNUAL_PENTEST',days:365,description:'Annual penetration test for freight data platform (customer contract requirement)',clock:'ANNUAL'}\n];\nconst alerts = rows.map(row => {\n  const due = new Date(row.due_date);\n  const diff = Math.ceil((due - today) / 86400000);\n  let urgency = diff <= 0 ? 'OVERDUE' : diff <= 1 ? 'IMMEDIATE' : diff <= 7 ? 'CRITICAL' : diff <= 14 ? 'URGENT' : diff <= 30 ? 'WARNING' : 'NOTICE';\n  return {...row, days_remaining: diff, urgency};\n}).filter(r => r.urgency !== 'NOTICE');\nreturn alerts.map(a => ({json: a}));"
      },
      "position": [
        680,
        300
      ]
    },
    {
      "id": "4",
      "name": "IF - Urgent",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.urgency}}",
              "operation": "regex",
              "value2": "OVERDUE|IMMEDIATE|CRITICAL"
            }
          ]
        }
      },
      "position": [
        900,
        300
      ]
    },
    {
      "id": "5",
      "name": "Slack - Urgent Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#compliance-ops",
        "text": "={{$json.urgency}}: {{$json.deadline_type}} due {{$json.due_date}} ({{$json.days_remaining}}d) \u2014 {{$json.description}}"
      },
      "position": [
        1120,
        200
      ]
    },
    {
      "id": "6",
      "name": "Gmail - Owner Notice",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "={{$json.owner_email}}",
        "subject": "={{$json.urgency}}: {{$json.deadline_type}} deadline action required",
        "message": "={{$json.description}}\n\nDue: {{$json.due_date}}\nDays remaining: {{$json.days_remaining}}"
      },
      "position": [
        1120,
        400
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets": {
      "main": [
        [
          {
            "node": "Code - Triage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Triage": {
      "main": [
        [
          {
            "node": "IF - Urgent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Urgent": {
      "main": [
        [
          {
            "node": "Slack - Urgent Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gmail - Owner Notice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 3: Freight Data API Health Monitor (15-Minute Polling)

PHMSA §171.16(a) requires telephonic notification within 30 minutes of hazmat incident discovery. If your hazmat API is down when the incident occurs, the clock is still running. Your platform needs to know immediately — not when the next daily health check runs.

Each endpoint is annotated with the compliance consequence of downtime:

  • ELD/HOS API down → FMCSA §395.8(k) — unlogged HOS = DOT audit exposure
  • Hazmat API down → PHMSA §171.16(a) 30-min clock; API delay = violation
  • CBP ISF API down → $5K–$10K per missed filing; cargo holds compound hourly
  • TMS Core down → FMC NVOCC tariff data unavailable = rate quote non-compliance
{
  "name": "LogisticsTech Freight Data API Health Monitor",
  "nodes": [
    {
      "id": "1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/15 * * * *"
            }
          ]
        }
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "HTTP - ELD API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-api.com/eld/health",
        "method": "GET"
      },
      "position": [
        460,
        200
      ]
    },
    {
      "id": "3",
      "name": "HTTP - Hazmat API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-api.com/hazmat/health",
        "method": "GET"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "4",
      "name": "HTTP - CBP ISF API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-api.com/cbp-isf/health",
        "method": "GET"
      },
      "position": [
        460,
        400
      ]
    },
    {
      "id": "5",
      "name": "HTTP - TMS Core API",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://your-api.com/tms/health",
        "method": "GET"
      },
      "position": [
        460,
        500
      ]
    },
    {
      "id": "6",
      "name": "Code - Evaluate",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const endpoints = [\n  {name:'eld_api', label:'ELD/HOS API', compliance:'FMCSA \u00a7395.8(k) \u2014 ELD downtime = unlogged HOS = FMCSA audit exposure'},\n  {name:'hazmat_api', label:'Hazmat Compliance API', compliance:'PHMSA \u00a7171.16(a) \u2014 30-min incident clock; API down = notification delay = \u00a7171.16 violation'},\n  {name:'cbp_isf_api', label:'CBP ISF Filing API', compliance:'CBP ISF 10+2 \u2014 24h pre-departure; API down = missed filing = $5K-$10K penalty per shipment'},\n  {name:'tms_core_api', label:'TMS Core API', compliance:'FMC NVOCC 46 USC \u00a740501 \u2014 tariff data unavailable = rate quote non-compliance'}\n];\nconst results = $input.all().map((item, i) => ({\n  endpoint: endpoints[i]?.name,\n  label: endpoints[i]?.label,\n  compliance_note: endpoints[i]?.compliance,\n  status: item.json.status || 'unknown',\n  ok: item.json.status === 'ok',\n  ts: new Date().toISOString()\n}));\nconst failed = results.filter(r => !r.ok);\nif (failed.length) return failed.map(f => ({json: {...f, alert: true}}));\nreturn [{json: {alert: false, message: 'All freight APIs healthy', ts: new Date().toISOString()}}];"
      },
      "position": [
        680,
        350
      ]
    },
    {
      "id": "7",
      "name": "IF - Alert",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$json.alert}}",
              "value2": true
            }
          ]
        }
      },
      "position": [
        900,
        350
      ]
    },
    {
      "id": "8",
      "name": "Slack - API Down",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#freight-ops-critical",
        "text": "API DOWN: {{$json.label}} \u2014 {{$json.compliance_note}}"
      },
      "position": [
        1120,
        300
      ]
    },
    {
      "id": "9",
      "name": "Sheets - SLA Log",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "append",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "APIHealth!A:F",
        "dataMode": "autoMapInputData"
      },
      "position": [
        1120,
        450
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "HTTP - ELD API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - Hazmat API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - CBP ISF API",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP - TMS Core API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - ELD API": {
      "main": [
        [
          {
            "node": "Code - Evaluate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - Hazmat API": {
      "main": [
        [
          {
            "node": "Code - Evaluate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - CBP ISF API": {
      "main": [
        [
          {
            "node": "Code - Evaluate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - TMS Core API": {
      "main": [
        [
          {
            "node": "Code - Evaluate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Evaluate": {
      "main": [
        [
          {
            "node": "IF - Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Alert": {
      "main": [
        [
          {
            "node": "Slack - API Down",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Sheets - SLA Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 4: Compliance Incident & Violation Pipeline

Eight incident types, each routed to the correct response channel with the right clock:

Incident Type Clock Regulation Action
PHMSA_HAZMAT_INCIDENT 30 minutes 49 CFR §171.16(a) NRC hotline 1-800-424-8802
IATA_DGR_UNDECLARED_GOODS IMMEDIATE IATA DGR §2.8.2 Notify airline ops control
FMCSA_ELD_VIOLATION 8 hours 49 CFR §392.2 Pull ELD records, 7-day audit
CBP_ISF_PENALTY_NOTICE 30 days CBP CF-19 petition File petition, gather ISF records
DOT_DRUG_TEST_POSITIVE 3 business days 49 CFR §382.215 Remove driver, notify DER
TSA_CCSP_SCREENING_GAP 24 hours 49 CFR §1544.228 Quarantine cargo, notify DFSD
DATA_BREACH_FREIGHT_DATA 72 hours GDPR Art.33 / CCPA Supervisory authority notification
FMC_TARIFF_VIOLATION 30 days 46 USC §40501 File corrective tariff amendment
{
  "name": "LogisticsTech Compliance Incident & Violation Pipeline",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "logistics-incident",
        "responseMode": "lastNode"
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Code - Classify Incident",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const ev = $input.first().json;\nconst types = {\n  'PHMSA_HAZMAT_INCIDENT': {\n    priority: 'P0',\n    clock: '30_MINUTES',\n    regulation: 'PHMSA 49 CFR \u00a7171.16(a)',\n    description: 'Hazmat incident requiring NRC telephonic notification within 30 minutes \u2014 do NOT wait for written report',\n    action: 'Call NRC hotline (1-800-424-8802) IMMEDIATELY. Written OP-26/PHSMT within 30 days.',\n    channel: '#hazmat-emergency'\n  },\n  'CBP_ISF_PENALTY_NOTICE': {\n    priority: 'P1',\n    clock: '30_DAYS',\n    regulation: 'CBP 19 CFR \u00a7171 / ISF 10+2 \u00a7\u00a71-505.3',\n    description: 'CBP ISF penalty notice \u2014 $5K-$10K per late/inaccurate filing. 30-day response window.',\n    action: 'File CBP CF-19 petition within 30 days. Gather ISF filing records, identify root cause.',\n    channel: '#customs-compliance'\n  },\n  'FMCSA_ELD_VIOLATION': {\n    priority: 'P1',\n    clock: '8_HOURS',\n    regulation: 'FMCSA 49 CFR \u00a7395.8(k) / \u00a7392.2',\n    description: 'FMCSA ELD HOS violation detected \u2014 8-hour out-of-service threshold for drivers.',\n    action: 'Pull ELD records immediately. 7-day log audit. Notify driver safety officer.',\n    channel: '#dot-compliance'\n  },\n  'IATA_DGR_UNDECLARED_GOODS': {\n    priority: 'P0',\n    clock: 'IMMEDIATE',\n    regulation: 'IATA DGR \u00a72.8.2 / ICAO Annex 18',\n    description: 'Undeclared or misdeclared dangerous goods on aircraft \u2014 IMMEDIATE airline notification required.',\n    action: 'Notify airline operations control IMMEDIATELY. Do not allow aircraft departure.',\n    channel: '#hazmat-emergency'\n  },\n  'FMC_TARIFF_VIOLATION': {\n    priority: 'P1',\n    clock: '30_DAYS',\n    regulation: 'FMC 46 USC \u00a740501 / 46 CFR Part 515',\n    description: 'FMC NVOCC tariff violation \u2014 rates published less than 30 days before effective date.',\n    action: 'File corrective tariff amendment with FMC. 30-day prospective notice required.',\n    channel: '#freight-compliance'\n  },\n  'DOT_DRUG_TEST_POSITIVE': {\n    priority: 'P1',\n    clock: '3_BUSINESS_DAYS',\n    regulation: 'DOT 49 CFR \u00a7382.215 / FMCSA Part 40',\n    description: 'DOT drug/alcohol positive result \u2014 immediate removal from safety-sensitive function.',\n    action: 'Remove driver from operation immediately. Notify DER. MIS record update required.',\n    channel: '#dot-compliance'\n  },\n  'DATA_BREACH_FREIGHT_DATA': {\n    priority: 'P1',\n    clock: '72_HOURS',\n    regulation: 'GDPR Art.33 / CCPA / CBP 19 CFR \u00a724.5',\n    description: 'Freight platform data breach \u2014 customer shipment data, HTS codes, supplier info exposed.',\n    action: '72h GDPR Art.33 supervisory authority notification. CBP bond notification if ISF data involved.',\n    channel: '#security-incident'\n  },\n  'TSA_CCSP_SCREENING_GAP': {\n    priority: 'P1',\n    clock: '24_HOURS',\n    regulation: 'TSA 49 CFR \u00a71544.228 / CCSP Program',\n    description: 'TSA CCSP cargo screening gap \u2014 unscreened cargo accepted under screening program.',\n    action: 'Quarantine affected cargo. Notify TSA designated federal security director within 24h.',\n    channel: '#tsa-compliance'\n  }\n};\nconst incident_type = ev.incident_type || 'DATA_BREACH_FREIGHT_DATA';\nconst info = types[incident_type] || types['DATA_BREACH_FREIGHT_DATA'];\nreturn [{json: {\n  incident_id: ev.incident_id || ('INC-' + Date.now()),\n  incident_type,\n  ...info,\n  ts: new Date().toISOString(),\n  reporter: ev.reporter_email,\n  details: ev.details\n}}];"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Switch - Channel",
      "type": "n8n-nodes-base.switch",
      "parameters": {
        "dataType": "string",
        "value1": "={{$json.incident_type}}",
        "rules": {
          "rules": [
            {
              "value2": "PHMSA_HAZMAT_INCIDENT",
              "output": 0
            },
            {
              "value2": "IATA_DGR_UNDECLARED_GOODS",
              "output": 0
            },
            {
              "value2": "FMCSA_ELD_VIOLATION",
              "output": 1
            },
            {
              "value2": "CBP_ISF_PENALTY_NOTICE",
              "output": 1
            },
            {
              "value2": "DATA_BREACH_FREIGHT_DATA",
              "output": 2
            }
          ]
        },
        "fallbackOutput": 1
      },
      "position": [
        680,
        300
      ]
    },
    {
      "id": "4",
      "name": "Slack - P0 Emergency",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "={{$json.channel}}",
        "text": "P0 FREIGHT INCIDENT: {{$json.incident_type}} | Clock: {{$json.clock}} | {{$json.action}}"
      },
      "position": [
        900,
        200
      ]
    },
    {
      "id": "5",
      "name": "Slack - P1 Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "={{$json.channel}}",
        "text": "{{$json.priority}} {{$json.incident_type}}: {{$json.description}} | Reg: {{$json.regulation}} | Action: {{$json.action}}"
      },
      "position": [
        900,
        350
      ]
    },
    {
      "id": "6",
      "name": "Gmail - Security",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "security@yourcompany.com",
        "subject": "BREACH: {{$json.incident_type}} \u2014 72h GDPR clock active",
        "message": "={{$json.description}}\n\nAction required: {{$json.action}}\nRegulation: {{$json.regulation}}"
      },
      "position": [
        900,
        480
      ]
    },
    {
      "id": "7",
      "name": "Sheets - Incident Log",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "append",
        "spreadsheetId": "YOUR_SHEET_ID",
        "range": "Incidents!A:J",
        "dataMode": "autoMapInputData"
      },
      "position": [
        1120,
        340
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Code - Classify Incident",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Classify Incident": {
      "main": [
        [
          {
            "node": "Switch - Channel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch - Channel": {
      "main": [
        [
          {
            "node": "Slack - P0 Emergency",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack - P1 Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gmail - Security",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - P0 Emergency": {
      "main": [
        [
          {
            "node": "Sheets - Incident Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - P1 Alert": {
      "main": [
        [
          {
            "node": "Sheets - Incident Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Security": {
      "main": [
        [
          {
            "node": "Sheets - Incident Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 5: Weekly LogisticsTech Compliance KPI Briefing

Monday 8AM: active customers by tier, MRR, open compliance items by type, incidents this week. CEOs and COOs see the regulatory exposure scorecard alongside revenue.

{
  "name": "LogisticsTech Weekly Compliance KPI Briefing",
  "nodes": [
    {
      "id": "1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      },
      "position": [
        240,
        300
      ]
    },
    {
      "id": "2",
      "name": "Postgres - KPIs",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  COUNT(DISTINCT customer_id) as active_customers,\n  SUM(CASE WHEN tier='FREIGHT_BROKER_SAAS_VENDOR' THEN 1 ELSE 0 END) as freight_brokers,\n  SUM(CASE WHEN tier='CUSTOMS_BROKER_SAAS_VENDOR' THEN 1 ELSE 0 END) as customs_brokers,\n  SUM(mrr_usd) as total_mrr,\n  SUM(CASE WHEN flag='FMCSA_ELD_COVERED_CARRIER' THEN 1 ELSE 0 END) as fmcsa_eld_customers,\n  SUM(CASE WHEN flag='PHMSA_HAZMAT_CARRIER' THEN 1 ELSE 0 END) as phmsa_hazmat_customers,\n  SUM(CASE WHEN flag='CBP_ISF_REQUIRED' THEN 1 ELSE 0 END) as cbp_isf_customers,\n  SUM(CASE WHEN flag='FMC_NVOCC_LICENSED' THEN 1 ELSE 0 END) as fmc_nvocc_customers\nFROM customers WHERE status='active'"
      },
      "position": [
        460,
        300
      ]
    },
    {
      "id": "3",
      "name": "Postgres - Open Items",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  SUM(CASE WHEN type='PHMSA_HAZMAT' AND status='open' THEN 1 ELSE 0 END) as phmsa_open,\n  SUM(CASE WHEN type='CBP_ISF_PENALTY' AND status='open' THEN 1 ELSE 0 END) as cbp_penalty_open,\n  SUM(CASE WHEN type='FMCSA_ELD' AND status='open' THEN 1 ELSE 0 END) as fmcsa_open,\n  SUM(CASE WHEN type='DATA_BREACH' AND status='open' THEN 1 ELSE 0 END) as breach_open,\n  SUM(CASE WHEN created_at >= NOW()-INTERVAL '7 days' THEN 1 ELSE 0 END) as incidents_this_week\nFROM compliance_incidents"
      },
      "position": [
        460,
        450
      ]
    },
    {
      "id": "4",
      "name": "Code - Build Report",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const kpi = $('Postgres - KPIs').first().json;\nconst items = $('Postgres - Open Items').first().json;\nconst html = `<h2>FlowKit LogisticsTech Weekly KPI \u2014 ${new Date().toLocaleDateString('en-US',{weekday:'long',year:'numeric',month:'long',day:'numeric'})}</h2>\n<table border=\"1\" cellpadding=\"6\" style=\"border-collapse:collapse;font-family:monospace\">\n<tr><th>Metric</th><th>Value</th></tr>\n<tr><td>Active Customers</td><td>${kpi.active_customers}</td></tr>\n<tr><td>Freight Broker SaaS</td><td>${kpi.freight_brokers}</td></tr>\n<tr><td>Customs Broker SaaS</td><td>${kpi.customs_brokers}</td></tr>\n<tr><td>Total MRR</td><td>$${Number(kpi.total_mrr).toLocaleString()}</td></tr>\n<tr><td>FMCSA ELD Customers</td><td>${kpi.fmcsa_eld_customers}</td></tr>\n<tr><td>PHMSA Hazmat Customers</td><td>${kpi.phmsa_hazmat_customers}</td></tr>\n<tr><td>CBP ISF Customers</td><td>${kpi.cbp_isf_customers}</td></tr>\n<tr><td>FMC NVOCC Licensed</td><td>${kpi.fmc_nvocc_customers}</td></tr>\n<tr><td colspan=\"2\"><b>Open Compliance Items</b></td></tr>\n<tr><td>PHMSA Hazmat Open</td><td>${items.phmsa_open}</td></tr>\n<tr><td>CBP ISF Penalty Open</td><td>${items.cbp_penalty_open}</td></tr>\n<tr><td>FMCSA ELD Open</td><td>${items.fmcsa_open}</td></tr>\n<tr><td>Data Breach Open</td><td>${items.breach_open}</td></tr>\n<tr><td>Incidents This Week</td><td>${items.incidents_this_week}</td></tr>\n</table><br><p><a href=\"https://stripeai.gumroad.com\">FlowKit n8n Automation Templates</a></p>`;\nreturn [{json: {html, subject: `FlowKit LogisticsTech Weekly KPI \u2014 MRR $${Number(kpi.total_mrr).toLocaleString()} \u2014 ${items.incidents_this_week} incidents this week`}}];"
      },
      "position": [
        680,
        380
      ]
    },
    {
      "id": "5",
      "name": "Gmail - KPI Report",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "operation": "send",
        "to": "ceo@yourcompany.com",
        "bcc": "coo@yourcompany.com",
        "subject": "={{$json.subject}}",
        "message": "={{$json.html}}",
        "options": {
          "bodyContentType": "html"
        }
      },
      "position": [
        900,
        380
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Postgres - KPIs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Postgres - Open Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres - KPIs": {
      "main": [
        [
          {
            "node": "Code - Build Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres - Open Items": {
      "main": [
        [
          {
            "node": "Code - Build Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Build Report": {
      "main": [
        [
          {
            "node": "Gmail - KPI Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Why logistics and freight SaaS vendors self-host n8n

Data Type Cloud iPaaS Risk Self-Hosted n8n Fix
FMCSA ELD/HOS records §395.8(k) — DOT subpoena goes to Zapier, not you Records stay inside your custody boundary
PHMSA hazmat shipping papers Discoverable in litigation before your legal team knows Incident data never leaves your infrastructure
CBP ISF 10+2 data HTS codes, supplier names, invoice values on vendor servers Power-of-attorney data stays inside your bond boundary
IATA DGR records Undeclared DG documentation as third-party evidence Chain-of-custody intact in your environment
FMC NVOCC tariff data Confidential commercial rates on public cloud Tariff data never transits cloud vendor
TSA CCSP screening records Chain-of-custody gaps = certification risk Screening documentation inside your certified boundary

When CBP issues an ISF penalty, they look at the electronic record trail. When PHMSA investigates a hazmat incident, they pull the notification log. When DOT audits ELD compliance, they subpoena records. All three can reach your cloud automation vendor directly.

Self-hosted n8n means one less party with access to freight data that regulators can reach without telling you first.


vs. Zapier / Make

Feature Zapier/Make Self-hosted n8n
FMCSA ELD data custody Cloud vendor servers Your servers
PHMSA hazmat records Routed through cloud Never leaves your stack
CBP ISF data SaaS vendor storage Inside your CBP bond boundary
IATA DGR chain-of-custody Third-party gap Intact in your environment
Incident notification latency API rate limits Sub-second internal
Cost at scale $299–$599/mo ~$20/mo self-hosted

Get the complete FlowKit logistics template pack

All 5 workflows above — plus 10 more n8n automation templates for SaaS operations — are available at stripeai.gumroad.com.

Each template includes:

  • Import-ready n8n JSON (drag and drop into your n8n instance)
  • Tier and flag segmentation pre-built
  • Compliance deadline tables with regulation citations
  • Incident pipeline with correct escalation routing

Individual templates from $12. Bundle of all 15: $97.


FlowKit is a collection of ready-to-deploy n8n automation templates. Not legal advice. Verify regulatory requirements with qualified counsel.

Top comments (0)