If you sell software to general contractors, construction project management firms, BIM platforms, job site safety compliance companies, LEED documentation providers, or construction fintech vendors, you operate in a multi-agency regulatory environment with the fastest worker-safety reporting clock in the tech sector: 8 hours.
That is the OSHA 29 CFR §1904.39(a)(1) fatality reporting window. It is not a business-hours clock. It does not pause for system maintenance windows, cloud provider incidents, or multi-tenant queue backlogs. When a worker dies on a project your software touches, your customer's OSHA notification pipeline must fire within 8 hours of employer awareness — and every data hop through a third-party cloud iPaaS is a latency variable in that pipeline.
Here are 5 n8n workflows every ConstructionTech SaaS vendor needs — with full workflow JSON — and the OSHA §1926 data sovereignty argument that makes self-hosted n8n a procurement requirement for enterprise construction platforms, not just a technical preference.
The regulatory stack every ConstructionTech SaaS vendor must navigate
| Agency / Law | Scope | Fastest clock |
|---|---|---|
| OSHA 29 CFR §1904.39 | Fatality and serious injury reporting | 8 hours (fatality) |
| OSHA 29 CFR §1904.39 | Hospitalization / amputation / eye loss | 24 hours |
| Davis-Bacon Act 40 USC §3142 | Federal project certified payroll | Weekly (WH-347) |
| EPA RCRA 40 CFR §264.56 | Hazardous waste release notification | Immediate (NRC call) |
| EPA CWA NPDES §122.26 | Construction stormwater permit compliance | Annual inspection |
| USGBC LEED v4/v4.1 | LEED credit documentation submission | Project milestone |
| Miller Act 40 USC §3133 | Federal payment bond claim | 90 days from last work |
| State mechanic lien law | Lien perfection window | 60–120 days (state-specific) |
The 8-hour OSHA fatality clock is the fastest hard compliance deadline in this series outside of financial sanctions. It begins at the moment any employer representative or agent knows about a work-related fatality — not when HR is notified, not when an attorney is engaged.
The OSHA §1926 data sovereignty argument
When OSHA investigates a construction fatality or serious injury, the agency issues a records request for:
- Pre-task planning records (safe work method statements, JHA/JSA)
- Toolbox talk attendance logs
- Competent person designation records (§1926.20(a))
- Subcontractor safety qualification records
- Prior safety inspection reports for the work area
- Equipment maintenance and inspection logs
In parallel, plaintiff's counsel issues a litigation hold over every system containing any of these record categories.
If your ConstructionTech SaaS routes these records through a cloud iPaaS, that iPaaS becomes a third-party subpoena target with its own data retention schedule, backup policies, and disclosure obligations — outside your customer's attorney-client privilege and litigation hold control. The general contractor now has a discovery dependency on a vendor they cannot control.
Self-hosted n8n, deployed inside the GC's own infrastructure perimeter, keeps the entire safety record automation chain within the system the GC controls, holds, and produces in discovery.
7 customer tiers, 7 compliance flags
| Tier | Description |
|---|---|
| ENTERPRISE_CONSTRUCTION_ERP | Procore-tier platforms: full project lifecycle + safety + financial |
| MIDMARKET_PROJECT_MGMT_SAAS | Buildertrend/CoConstruct-tier: scheduling, change orders, client portal |
| SUBCONTRACTOR_MGMT_SAAS | Specialty contractor platforms: bid management, prequalification, EMR tracking |
| BIM_SAAS_VENDOR | BIM 360/Revit Cloud-tier: model coordination, clash detection, RFI management |
| SAFETY_COMPLIANCE_SAAS | Job site safety: incident reporting, OSHA 300 log, near-miss tracking |
| LEED_CERTIFICATION_SAAS | LEED point tracking, credit documentation, commissioning records |
| CONSTRUCTION_FINTECH | AIA payment applications, lien management, retainage automation |
| Flag | Regulation |
|---|---|
| OSHA_29_CFR_1926_SUBJECT | Construction safety standards (all construction employers) |
| DAVIS_BACON_ACT_SUBJECT | Federal/federally-assisted projects (40 USC §3142) |
| EPA_RCRA_WASTE_GENERATOR | C&D hazardous waste generator (40 CFR Part 262) |
| AIA_CONTRACT_ADMINISTRATOR | AIA Document A201 indemnification chain processor |
| LEED_PROJECT_REGISTERED | USGBC LEED certification documentation |
| DOT_MUTCD_SUBJECT | Traffic control for road/highway construction (MUTCD 2009/2023) |
| MILLER_ACT_SUBJECT | Federal construction project payment bond (40 USC §3133) |
Workflow 1: Construction SaaS Customer Onboarding Drip
Webhook trigger → tier classifier → 7-tier conditional Day 0/3/7 email sequence. Each tier receives its specific compliance context:
- SAFETY_COMPLIANCE_SAAS receives the OSHA 8-hour fatality clock brief and the latency risk argument for cloud iPaaS in Day 0
- ENTERPRISE_CONSTRUCTION_ERP receives the OSHA eDiscovery exposure and Davis-Bacon subprocessor argument
- CONSTRUCTION_FINTECH receives the AIA Document A201 §3.18 indemnification chain brief
{
"name": "Construction SaaS Customer Onboarding Drip",
"nodes": [
{
"id": "1",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
],
"parameters": {
"httpMethod": "POST",
"path": "construction-onboarding",
"responseMode": "onReceived"
}
},
{
"id": "2",
"name": "Set Tier & Flags",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
],
"parameters": {
"jsCode": "const d=items[0].json;const tierMap={ENTERPRISE_CONSTRUCTION_ERP:{day0:'Your OSHA 29 CFR \u00a71926 construction safety compliance guide, Davis-Bacon Act certified payroll checklist, and EPA RCRA construction waste generator quick-reference are attached. As an enterprise construction ERP processing injury records, subcontractor PII, and safety inspection logs, your data governance posture determines your eDiscovery exposure when OSHA investigations or construction litigation begins. Cloud iPaaS routing subcontractor safety data creates a third-party data chain outside your privilege and litigation hold control.',osha_flag:true,davis_bacon_flag:true},MIDMARKET_PROJECT_MGMT_SAAS:{day0:'Your OSHA injury reporting timeline (8h fatality/24h hospitalization) and Davis-Bacon certified payroll compliance guide are enclosed. Midmarket construction PMs running federal or federally-assisted projects must ensure certified payroll data never passes through an unauthorized cloud subprocessor \u2014 DOL Wage and Hour Division has broad subpoena authority.',osha_flag:true,davis_bacon_flag:true},SUBCONTRACTOR_MGMT_SAAS:{day0:'Your OSHA subcontractor prequalification compliance guide and Miller Act 40 USC \u00a73133 payment bond claim timeline are attached. Subcontractor qualification records containing OSHA 300 log data and EMR (Experience Modification Rate) ratings are litigation-sensitive \u2014 cloud iPaaS processing EMR data creates exposure outside your privilege boundary.',osha_flag:true,davis_bacon_flag:False},BIM_SAAS_VENDOR:{day0:'Your OSHA 29 CFR \u00a71926 construction phase coordination guide and LEED documentation data integrity checklist are enclosed. BIM platforms processing project safety coordination records and RFI logs may be subject to construction litigation discovery \u2014 data hosted in third-party cloud iPaaS extends your subpoena exposure to include that vendor.',osha_flag:True,davis_bacon_flag:False},SAFETY_COMPLIANCE_SAAS:{day0:'CRITICAL: Your OSHA 29 CFR \u00a71904.39 injury/illness reporting timeline is enclosed. You have 8 hours to notify OSHA of a work-related fatality. 24 hours for inpatient hospitalization, amputation, or eye loss. Cloud iPaaS latency and queue delays during a major site incident could push your notification past the statutory window \u2014 a self-hosted n8n pipeline eliminates the third-party latency variable entirely.',osha_flag:True,davis_bacon_flag:False},LEED_CERTIFICATION_SAAS:{day0:'Your USGBC LEED documentation data integrity guide and LEED credit submission timeline are attached. LEED certification depends on auditable documentation chains \u2014 construction material specifications, energy modeling inputs, commissioning records. Cloud iPaaS co-processing LEED documentation with project PII creates an uncontrolled evidence chain that USGBC reviewers and project owners have flagged in disputes.',osha_flag:False,davis_bacon_flag:False},CONSTRUCTION_FINTECH:{day0:'Your AIA Document A201 \u00a73.18 indemnification chain guide and Miller Act 40 USC \u00a73133 payment bond claim checklist are enclosed. Construction payment automation that routes lien waivers and certified payroll through cloud iPaaS creates an uncontrolled data chain in the AIA indemnification structure \u2014 subcontractor injury data + payment dispute records = third-party litigation exposure.',osha_flag:False,davis_bacon_flag:True}};const t=tierMap[d.tier]||tierMap.MIDMARKET_PROJECT_MGMT_SAAS;return [{json:{...d,tierNote:t.day0,osha_flag:t.osha_flag,davis_bacon_flag:t.davis_bacon_flag,enrolledAt:new Date().toISOString()}}];"
}
},
{
"id": "3",
"name": "Gmail Day 0 Welcome",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
650,
300
],
"parameters": {
"operation": "send",
"toList": "={{$json.email}}",
"subject": "Welcome to FlowKit \u2014 your ConstructionTech compliance automation is live",
"message": "=Hi {{$json.name}},\n\nYour FlowKit account is active. {{$json.tierNote}}\n\nCRITICAL OSHA CLOCK: 29 CFR \u00a71904.39(a)(1) \u2014 8 hours to notify OSHA of any work-related fatality. This is not a business-hours clock. A cloud iPaaS pipeline with multi-tenant queue delays is a compliance risk during a mass-casualty site event. Self-hosted n8n inside your own infrastructure eliminates the third-party latency variable.\n\nStore: https://stripeai.gumroad.com\n\nBest,\nAlex Kane / FlowKit"
}
},
{
"id": "4",
"name": "Log to Sheets",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
850,
300
],
"parameters": {
"operation": "append",
"documentId": "YOUR_SHEET_ID",
"sheetName": "construction_onboarding",
"columns": {
"mappingMode": "defineBelow",
"value": {
"email": "={{$json.email}}",
"name": "={{$json.name}}",
"tier": "={{$json.tier}}",
"enrolled": "={{$json.enrolledAt}}",
"osha_flag": "={{$json.osha_flag}}",
"davis_bacon_flag": "={{$json.davis_bacon_flag}}",
"day3_sent": "False",
"day7_sent": "False"
}
}
}
},
{
"id": "5",
"name": "Wait 3 Days",
"type": "n8n-nodes-base.wait",
"typeVersion": 1,
"position": [
1050,
300
],
"parameters": {
"amount": 3,
"unit": "days"
}
},
{
"id": "6",
"name": "Gmail Day 3",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
1250,
300
],
"parameters": {
"operation": "send",
"toList": "={{$json.email}}",
"subject": "Day 3 \u2014 have you reviewed your OSHA 8-hour fatality reporting pipeline?",
"message": "=Hi {{$json.name}},\n\nChecking in: have you mapped the data path for your OSHA \u00a71904.39 8-hour fatality notification?\n\nKey action: identify which system owns the first-alert trigger for a site fatality, and confirm there is no third-party queue between that trigger and your OSHA Area Office notification. This is the first question in an OSHA post-incident inspection.\n\nReply with any questions.\n\nAlex / FlowKit"
}
},
{
"id": "7",
"name": "Wait 4 Days",
"type": "n8n-nodes-base.wait",
"typeVersion": 1,
"position": [
1450,
300
],
"parameters": {
"amount": 4,
"unit": "days"
}
},
{
"id": "8",
"name": "Gmail Day 7 Features",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
1650,
300
],
"parameters": {
"operation": "send",
"toList": "={{$json.email}}",
"subject": "5 FlowKit automations your construction compliance team needs this week",
"message": "=Hi {{$json.name}},\n\nHere are the 5 workflows to deploy this week:\n\n1. OSHA/Davis-Bacon/EPA/LEED/DOT Compliance Deadline Tracker\n2. Construction Regulatory API Health Monitor\n3. OSHA/RCRA/Davis-Bacon/LEED Incident Pipeline\n4. Construction SaaS Customer Onboarding Drip (this workflow)\n5. Weekly ConstructionTech KPI Dashboard\n\nFull JSON: https://stripeai.gumroad.com\n\nAlex / FlowKit"
}
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Set Tier & Flags",
"type": "main",
"index": 0
}
]
]
},
"Set Tier & Flags": {
"main": [
[
{
"node": "Gmail Day 0 Welcome",
"type": "main",
"index": 0
}
]
]
},
"Gmail Day 0 Welcome": {
"main": [
[
{
"node": "Log to Sheets",
"type": "main",
"index": 0
}
]
]
},
"Log to Sheets": {
"main": [
[
{
"node": "Wait 3 Days",
"type": "main",
"index": 0
}
]
]
},
"Wait 3 Days": {
"main": [
[
{
"node": "Gmail Day 3",
"type": "main",
"index": 0
}
]
]
},
"Gmail Day 3": {
"main": [
[
{
"node": "Wait 4 Days",
"type": "main",
"index": 0
}
]
]
},
"Wait 4 Days": {
"main": [
[
{
"node": "Gmail Day 7 Features",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 2: ConstructionTech Compliance Deadline Tracker
Daily 7AM cron → Google Sheets deadline read → urgency classifier → Slack/Gmail alerts. 12 deadline types:
- OSHA_300_LOG_ANNUAL_POSTING — Form 300A posting Feb 1–Apr 30 (§1904.32)
- OSHA_INJURY_ILLNESS_ELECTRONIC_SUBMIT — electronic OSHA 300A by March 2 for 250+ employee sites
- DAVIS_BACON_CERTIFIED_PAYROLL_WEEKLY — DOL WH-347 weekly for all federal projects
- EPA_RCRA_BIENNIAL_REPORT — August 1, even years (§262.41)
- EPA_STORMWATER_NPDES_ANNUAL — annual BMP inspection (40 CFR §122.26)
- LEED_DOCUMENTATION_SUBMISSION — USGBC credit submission at certification stage
- AIA_G702_MONTHLY_PAY_APP — monthly AIA G702/G703 pay application
- CONSTRUCTION_LIEN_PERFECTION — state mechanic lien window (60–120 days from last work)
- MILLER_ACT_PAYMENT_BOND_CLAIM — 90 days from last work on federal projects (40 USC §3133)
- DOT_MUTCD_TRAFFIC_CONTROL_PERMIT — local TCP approval before lane closure
- SUBCONTRACTOR_PREQUALIFICATION_RENEWAL — annual subcontractor qualification update
- SOC2_TYPE2_RENEWAL — annual SOC 2 audit cycle
{
"name": "ConstructionTech Compliance Deadline Tracker",
"nodes": [
{
"id": "1",
"name": "Daily 7AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
250,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 7 * * *"
}
]
}
}
},
{
"id": "2",
"name": "Read Deadlines Sheet",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
450,
300
],
"parameters": {
"operation": "read",
"documentId": "YOUR_SHEET_ID",
"sheetName": "construction_compliance_deadlines"
}
},
{
"id": "3",
"name": "Classify Urgency",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
650,
300
],
"parameters": {
"jsCode": "const today=new Date();return items.map(i=>{const d=i.json;const due=new Date(d.due_date);const days=Math.round((due-today)/(1000*60*60*24));let urgency='UPCOMING';if(days<0)urgency='OVERDUE';else if(days<=3)urgency='CRITICAL';else if(days<=7)urgency='URGENT';else if(days<=30)urgency='WARNING';else if(days<=60)urgency='NOTICE';const deadlineMap={OSHA_300_LOG_ANNUAL_POSTING:'OSHA 29 CFR \u00a71904.32 \u2014 Form 300A annual summary must be posted in workplace Feb 1 through Apr 30. Failure = willful violation up to $156,259.',OSHA_INJURY_ILLNESS_ELECTRONIC_SUBMIT:'OSHA 29 CFR \u00a71904.41 \u2014 establishments with 250+ employees must submit OSHA 300A data electronically by March 2. OSHA cross-checks against reported incidents.',DAVIS_BACON_CERTIFIED_PAYROLL_WEEKLY:'Davis-Bacon Act 40 USC \u00a73142 \u2014 weekly Certified Payroll (WH-347) required for all federally-assisted construction projects. Failure = debarment from federal contracts + back-pay restitution.',EPA_RCRA_BIENNIAL_REPORT:'EPA RCRA 40 CFR \u00a7262.41 \u2014 large quantity generators must submit biennial hazardous waste report by August 1 of even-numbered years. Non-compliance = $37,500/day civil penalty.',EPA_STORMWATER_NPDES_ANNUAL:'EPA CWA NPDES Construction Stormwater 40 CFR \u00a7122.26 \u2014 annual site inspection and BMP assessment. Non-compliance = discharge permit violation + $25,000/day.',LEED_DOCUMENTATION_SUBMISSION:'USGBC LEED v4/v4.1 \u2014 credit documentation submission at LEED certification review stage. Late or incomplete submission = credit denied, certification delayed or downgraded.',AIA_G702_MONTHLY_PAY_APP:'AIA Document G702/G703 \u2014 monthly contractor application for payment. Missed pay app cycle = 30-60 day cash flow gap on large projects. Lien rights may lapse if work not billed timely.',CONSTRUCTION_LIEN_PERFECTION:'State mechanic lien law \u2014 varies by state (60-120 days from last work/materials). Missed lien window = unsecured creditor status in owner insolvency. No exceptions after deadline.',MILLER_ACT_PAYMENT_BOND_CLAIM:'Miller Act 40 USC \u00a73133 \u2014 subcontractors on federal projects must file payment bond claim within 90 days after last work/materials. Miss = no claim against bond.',DOT_MUTCD_TRAFFIC_CONTROL_PERMIT:'MUTCD 2009/2023 \u2014 local traffic control plan (TCP) approval required before lane closure. Unpermitted lane closure = DOT stop-work + potential OSHA \u00a71926.200 citation.',SUBCONTRACTOR_PREQUALIFICATION_RENEWAL:'AIA Document A201 \u00a75.2 \u2014 owner/GC annual subcontractor prequalification renewal. Expired prequalification = sub cannot be used on bonded projects.',SOC2_TYPE2_RENEWAL:'AICPA SOC 2 Type II \u2014 annual audit cycle. Lapsed SOC 2 = enterprise construction ERP buyer sales blocker.'};return {json:{...d,daysUntil:days,urgency,deadlineNote:deadlineMap[d.deadline_type]||d.deadline_type}};}).filter(i=>i.json.urgency!=='UPCOMING'||i.json.daysUntil<=60);"
}
},
{
"id": "4",
"name": "Switch Urgency",
"type": "n8n-nodes-base.switch",
"typeVersion": 1,
"position": [
850,
300
],
"parameters": {
"dataType": "string",
"value1": "={{$json.urgency}}",
"rules": {
"rules": [
{
"value2": "OVERDUE",
"output": 0
},
{
"value2": "CRITICAL",
"output": 0
},
{
"value2": "URGENT",
"output": 1
},
{
"value2": "WARNING",
"output": 2
},
{
"value2": "NOTICE",
"output": 3
}
]
}
}
},
{
"id": "5",
"name": "Slack CRITICAL",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
1050,
200
],
"parameters": {
"channel": "#regulatory-compliance",
"text": "=:rotating_light: CONSTRUCTION COMPLIANCE {{$json.urgency}}: *{{$json.deadline_type}}* for {{$json.customer_name}} \u2014 due {{$json.due_date}} ({{$json.daysUntil}}d). {{$json.deadlineNote}}"
}
},
{
"id": "6",
"name": "Gmail CRITICAL",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
1050,
320
],
"parameters": {
"operation": "send",
"toList": "={{$json.owner_email}}",
"subject": "=CONSTRUCTION {{$json.urgency}}: {{$json.deadline_type}} due {{$json.due_date}}",
"message": "={{$json.urgency}} \u2014 {{$json.daysUntil}} days remaining.\n\nDeadline: {{$json.deadline_type}}\nRegulation: {{$json.deadlineNote}}\nCustomer: {{$json.customer_name}}\nDue: {{$json.due_date}}\n\nAction required immediately."
}
},
{
"id": "7",
"name": "Slack WARNING",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
1050,
440
],
"parameters": {
"channel": "#construction-ops",
"text": "=:warning: CONSTRUCTION {{$json.urgency}}: {{$json.deadline_type}} for {{$json.customer_name}} in {{$json.daysUntil}} days ({{$json.due_date}}). {{$json.deadlineNote}}"
}
},
{
"id": "8",
"name": "Slack NOTICE",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
1050,
560
],
"parameters": {
"channel": "#construction-ops",
"text": "=:calendar: CONSTRUCTION NOTICE: {{$json.deadline_type}} for {{$json.customer_name}} in {{$json.daysUntil}} days."
}
}
],
"connections": {
"Daily 7AM": {
"main": [
[
{
"node": "Read Deadlines Sheet",
"type": "main",
"index": 0
}
]
]
},
"Read Deadlines Sheet": {
"main": [
[
{
"node": "Classify Urgency",
"type": "main",
"index": 0
}
]
]
},
"Classify Urgency": {
"main": [
[
{
"node": "Switch Urgency",
"type": "main",
"index": 0
}
]
]
},
"Switch Urgency": {
"main": [
[
{
"node": "Slack CRITICAL",
"type": "main",
"index": 0
},
{
"node": "Gmail CRITICAL",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack WARNING",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack NOTICE",
"type": "main",
"index": 0
}
],
[]
]
}
}
}
Workflow 3: Construction Regulatory API Health Monitor
Every 15 minutes → load 5 endpoints → split → HTTP health check → dedup via $getWorkflowStaticData → alert on first failure only. Monitored endpoints:
- osha_data_api — OSHA data portal (injury/illness cross-check)
- dol_wage_hour_api — DOL WHD (Davis-Bacon wage determination lookup)
- epa_rcra_info_api — EPA RCRAInfo e-Manifest API
- usgbc_leed_api — USGBC LEED project portal
- construction_project_db — internal construction data API
API health monitoring is critical for OSHA-covered construction platforms because the 8-hour fatality clock does not pause for system outages. If your OSHA notification pipeline depends on an API call to a system that is down, you need to know within 15 minutes.
{
"name": "Construction Regulatory API Health Monitor",
"nodes": [
{
"id": "1",
"name": "Every 15 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
250,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "*/15 * * * *"
}
]
}
}
},
{
"id": "2",
"name": "Load Endpoints",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
],
"parameters": {
"jsCode": "return [{json:{api_name:'osha_data_api',health_url:'https://api.bls.gov/publicAPI/v2/timeseries/data/',compliance_note:'OSHA injury/illness data API. Downtime = OSHA 300 log cross-check unavailable. 29 CFR \u00a71904.39 \u2014 8h fatality clock cannot be validated against OSHA systems.'}},{json:{api_name:'dol_wage_hour_api',health_url:'https://www.dol.gov/agencies/whd',compliance_note:'DOL Wage and Hour Division \u2014 Davis-Bacon certified payroll verification. Downtime = WH-347 prevailing wage rate lookup unavailable. Davis-Bacon 40 USC \u00a73142.'}},{json:{api_name:'epa_rcra_info_api',health_url:'https://rcrainfo.epa.gov/rcrainfoprod/rest/api/v1/emanifest/lookup/manifesttracking',compliance_note:'EPA RCRAInfo e-Manifest API. Downtime = hazardous waste manifest tracking unavailable. RCRA 40 CFR \u00a7262 \u2014 LQG manifest required for each HW shipment.'}},{json:{api_name:'usgbc_leed_api',health_url:'https://www.usgbc.org/projects',compliance_note:'USGBC LEED project portal. Downtime = LEED credit submission unavailable. Project certification timeline at risk if documentation submission window missed.'}},{json:{api_name:'construction_project_db',health_url:'https://api.yourcompany.com/projects/health',compliance_note:'Internal construction project data API. Downtime = subcontractor safety records, certified payroll, and lien management data unavailable. OSHA \u00a71904 records inaccessible.'}}];"
}
},
{
"id": "3",
"name": "Split Endpoints",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
650,
300
],
"parameters": {
"batchSize": 1
}
},
{
"id": "4",
"name": "HTTP Health Check",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
850,
300
],
"parameters": {
"method": "GET",
"url": "={{$json.health_url}}",
"timeout": 8000,
"continueOnFail": true
}
},
{
"id": "5",
"name": "Classify Status",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1050,
300
],
"parameters": {
"jsCode": "const e=items[0].json;const statusCode=e.$response?.statusCode||0;const latency=parseInt(e.$response?.headers?.['x-response-time']||'0');let status='OK';let detail='';if(statusCode===0||statusCode>=500){status='DOWN';detail='No response or server error';}else if(statusCode>=400){status='DEGRADED';detail='HTTP '+statusCode;}else if(latency>5000){status='DEGRADED';detail='High latency: '+latency+'ms';}const lastState=$getWorkflowStaticData('global');const key='state_'+e.api_name;const alreadyAlerting=lastState[key]==='alerting';if(status!=='OK'){if(!alreadyAlerting){lastState[key]='alerting';return [{json:{...e,apiStatus:status,statusCode,detail,shouldAlert:true}}];}return [{json:{...e,apiStatus:status,shouldAlert:false}}];}lastState[key]='ok';return [{json:{...e,apiStatus:'OK',shouldAlert:false}}];"
}
},
{
"id": "6",
"name": "Alert If Down",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1250,
300
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": false
},
"conditions": [
{
"leftValue": "={{$json.shouldAlert}}",
"operator": {
"type": "boolean",
"operation": "true"
}
}
]
}
}
},
{
"id": "7",
"name": "Slack Alert",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
1450,
250
],
"parameters": {
"channel": "#platform-ops",
"text": "=:red_circle: CONSTRUCTION API {{$json.apiStatus}}: *{{$json.api_name}}* \u2014 {{$json.compliance_note}} Detail: {{$json.detail}}. OSHA 8-hour clock cannot be paused for system downtime."
}
},
{
"id": "8",
"name": "Log Incident",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
1450,
380
],
"parameters": {
"operation": "append",
"documentId": "YOUR_SHEET_ID",
"sheetName": "construction_api_incidents",
"columns": {
"mappingMode": "defineBelow",
"value": {
"ts": "={{new Date().toISOString()}}",
"api": "={{$json.api_name}}",
"status": "={{$json.apiStatus}}",
"detail": "={{$json.detail}}",
"compliance": "={{$json.compliance_note}}"
}
}
}
}
],
"connections": {
"Every 15 Minutes": {
"main": [
[
{
"node": "Load Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Load Endpoints": {
"main": [
[
{
"node": "Split Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Split Endpoints": {
"main": [
[
{
"node": "HTTP Health Check",
"type": "main",
"index": 0
}
]
]
},
"HTTP Health Check": {
"main": [
[
{
"node": "Classify Status",
"type": "main",
"index": 0
}
]
]
},
"Classify Status": {
"main": [
[
{
"node": "Alert If Down",
"type": "main",
"index": 0
}
]
]
},
"Alert If Down": {
"main": [
[
{
"node": "Slack Alert",
"type": "main",
"index": 0
},
{
"node": "Log Incident",
"type": "main",
"index": 0
}
],
[]
]
}
}
}
Workflow 4: ConstructionTech Safety & Compliance Incident Pipeline
Webhook → incident classifier → simultaneous Slack alert + Gmail to safety/legal + Google Sheets log. 8 incident types:
| Incident | SLA | Regulation |
|---|---|---|
| OSHA_CONSTRUCTION_FATALITY | 8 hours | 29 CFR §1904.39(a)(1) |
| OSHA_HOSPITALIZATION_AMPUTATION_EYE | 24 hours | 29 CFR §1904.39(a)(2) |
| OSHA_SERIOUS_CITATION_ISSUED | 15 working days to contest | OSHA Act §17(a) |
| DAVIS_BACON_INVESTIGATION_NOTICE | Respond within 5 working days | 29 CFR §5.6 |
| EPA_RCRA_HAZARDOUS_WASTE_RELEASE | IMMEDIATE NRC call | 40 CFR §264.56 + CERCLA §103(a) |
| CONSTRUCTION_LIEN_FILED_AGAINST_PROJECT | State lien response window | State mechanic lien law |
| LEED_CREDIT_REJECTION | 25 days to appeal | USGBC LEED Appeal Guidance |
| MILLER_ACT_PAYMENT_BOND_CLAIM | Surety notice immediately, 45 days to respond | 40 USC §3133 |
The EPA_RCRA_HAZARDOUS_WASTE_RELEASE clock (immediate NRC call) is the second-fastest clock in this stack after the OSHA fatality 8-hour window. C&D demolition projects generating asbestos, lead paint dust, or other RCRA-listed hazardous waste face immediate notification obligations if a release reaches a reportable quantity.
{
"name": "ConstructionTech Safety & Compliance Incident Pipeline",
"nodes": [
{
"id": "1",
"name": "Incident Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
],
"parameters": {
"httpMethod": "POST",
"path": "construction-incident",
"responseMode": "onReceived"
}
},
{
"id": "2",
"name": "Classify Incident",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
],
"parameters": {
"jsCode": "const d=items[0].json;const incidentMap={OSHA_CONSTRUCTION_FATALITY:{sla:'8 hours from employer awareness \u2014 29 CFR \u00a71904.39(a)(1). Report to OSHA Area Office by phone or online at 1-800-321-OSHA. Clock starts when employer or any agent knows. IMMEDIATE PRIORITY.',slack:'#regulatory-compliance',regulation:'OSHA 29 CFR \u00a71904.39(a)(1) \u2014 work-related fatality. Civil penalty up to $156,259 for failure to report. Criminal referral possible.',action:'Call OSHA 1-800-321-OSHA immediately. Preserve site \u2014 do not disturb fatality scene except to prevent further injury. Preserve all pre-task planning records, toolbox talk logs, competent person designations, and safety inspection records from that shift. Engage construction attorney for litigation hold.'},OSHA_HOSPITALIZATION_AMPUTATION_EYE:{sla:'24 hours from employer awareness \u2014 29 CFR \u00a71904.39(a)(2). Inpatient hospitalization, amputation, or loss of an eye. Call 1-800-321-OSHA.',slack:'#regulatory-compliance',regulation:'OSHA 29 CFR \u00a71904.39(a)(2) \u2014 24-hour reporting for in-patient hospitalization, amputation, or eye loss. Penalty up to $156,259.',action:'Report to OSHA within 24 hours. Do not disturb incident site. Preserve PPE, tool/equipment condition, witness statements. Issue litigation hold. Notify GCs insurance carrier and surety.'},OSHA_SERIOUS_CITATION_ISSUED:{sla:'15 working days to contest \u2014 OSHA \u00a71903.17. Informal conference with Area Director typically within first 15 days. Notice of Contest must be filed with Area Director.',slack:'#regulatory-compliance',regulation:'OSHA Occupational Safety and Health Act \u00a717(a) \u2014 serious violation up to $15,625 per violation. Willful: $156,259. Contested citations can be reduced at informal conference.',action:'Review citation carefully \u2014 is the alleged hazard OSHA standard-specific or general duty clause \u00a75(a)(1)? Prepare evidence of abatement or affirmative defense. Engage OSHA counsel. File Notice of Contest if contesting penalty.'},DAVIS_BACON_INVESTIGATION_NOTICE:{sla:'Respond within 5 working days to DOL WHD investigation notice \u2014 DOL Regulations 29 CFR \u00a75.6. Failure to produce payroll records = debarment recommendation.',slack:'#regulatory-ops',regulation:'Davis-Bacon Act 40 USC \u00a73142 / DBA Regulations 29 CFR Part 5 \u2014 federal prevailing wage. Debarment from federal contracts for 3 years on first violation.',action:'Pull all WH-347 certified payrolls for the affected project and period. Cross-check actual wages paid against applicable wage determination (SAM.gov). Identify any underpayment by craft classification. Cooperate with WHD \u2014 voluntary restitution is the strongest mitigating factor.'},EPA_RCRA_HAZARDOUS_WASTE_RELEASE:{sla:'IMMEDIATE \u2014 if release equals or exceeds reportable quantity (RQ), call National Response Center 1-800-424-8802. CERCLA \u00a7103(a) + RCRA \u00a7264.56(d). Within 15 days: written follow-up to EPA regional administrator.',slack:'#regulatory-compliance',regulation:'EPA RCRA 40 CFR \u00a7264.56 / CERCLA 42 USC \u00a79603 \u2014 RQ release of RCRA listed hazardous waste. Civil: $37,500/day. Criminal: up to 5 years.',action:'Call NRC immediately if release >= RQ. Do not move waste without EPA notification unless necessary to prevent further release. Manifest all waste movement. Submit written release report within 15 days. Preserve all RCRA waste management records \u2014 EPA has 5-year audit lookback.'},CONSTRUCTION_LIEN_FILED_AGAINST_PROJECT:{sla:'Owner must respond within state lien response window (varies 20-60 days) \u2014 failure to release or bond over lien = property title clouded at closing.',slack:'#legal-ops',regulation:'State mechanic lien law (varies by state) \u2014 lien encumbers property title. Owner or GC must release, bond over, or dispute lien before project closes or refinances.',action:'Identify lien claimant and claimed amount. Confirm whether predicate notice (prelim notice, notice to owner) was timely filed per state law. Verify if claimed work was actually performed and unpaid. Consult construction lien counsel. Bond over lien with payment bond to release title while dispute proceeds.'},LEED_CREDIT_REJECTION:{sla:'25 calendar days to appeal USGBC credit review denial \u2014 LEED v4 Rating System Appeal Guidance. No extension available.',slack:'#leed-compliance',regulation:'USGBC LEED v4/v4.1 \u2014 credit documentation review. Rejected credit = project downgraded to lower certification tier (Certified/Silver/Gold/Platinum).',action:'Review rejection reason carefully. Gather additional documentation for appeal: calculations, product specs, commissioning reports, material invoices. Appeal via USGBC LEED Online within 25 days. Consider whether alternative compliance path (ACP) applies.'},MILLER_ACT_PAYMENT_BOND_CLAIM:{sla:'Surety must be notified immediately \u2014 Miller Act 40 USC \u00a73133(b)(2). Claimant has 90 days after last work/materials to file. Bond principal (GC) must respond within 45 days.',slack:'#legal-ops',regulation:'Miller Act 40 USC \u00a73133 \u2014 federal construction project payment bond. Failure to respond = surety litigation. Bond amount typically equals full contract price.',action:'Notify surety in writing immediately. Pull contract, subcontract, and payment records for the claimant. Verify last date of work/materials to confirm 90-day window validity. Gather proof of payment or disputed invoices. Engage construction attorney for Miller Act response strategy.'}}; const cfg=incidentMap[d.incident_type]||{sla:'Review required',slack:'#compliance-ops',regulation:'Unknown',action:'Escalate to VP Safety and Legal'};return [{json:{...d,sla:cfg.sla,slackChannel:cfg.slack,regulation:cfg.regulation,action:cfg.action,ts:new Date().toISOString()}}];"
}
},
{
"id": "3",
"name": "Slack Alert",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
650,
200
],
"parameters": {
"channel": "={{$json.slackChannel}}",
"text": "=:rotating_light: CONSTRUCTION COMPLIANCE INCIDENT: *{{$json.incident_type}}*\nSLA: {{$json.sla}}\nRegulation: {{$json.regulation}}\nAction: {{$json.action}}\nCustomer: {{$json.customer_id}} | Project: {{$json.project_id}}\nDetected: {{$json.ts}}"
}
},
{
"id": "4",
"name": "Gmail Safety & Legal",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
650,
340
],
"parameters": {
"operation": "send",
"toList": "coo@yourcompany.com,safety@yourcompany.com",
"subject": "=CONSTRUCTION INCIDENT: {{$json.incident_type}} \u2014 {{$json.sla}}",
"message": "=Incident: {{$json.incident_type}}\nSLA clock: {{$json.sla}}\nRegulation: {{$json.regulation}}\nRequired action: {{$json.action}}\n\nCustomer: {{$json.customer_id}}\nProject: {{$json.project_id}}\nDetected: {{$json.ts}}\n\nThis notification is auto-generated by FlowKit. Engage qualified construction counsel for all OSHA, Davis-Bacon, and Miller Act matters."
}
},
{
"id": "5",
"name": "Log Incident",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
650,
480
],
"parameters": {
"operation": "append",
"documentId": "YOUR_SHEET_ID",
"sheetName": "construction_incident_log",
"columns": {
"mappingMode": "defineBelow",
"value": {
"ts": "={{$json.ts}}",
"incident_type": "={{$json.incident_type}}",
"customer_id": "={{$json.customer_id}}",
"project_id": "={{$json.project_id}}",
"sla": "={{$json.sla}}",
"regulation": "={{$json.regulation}}",
"action_taken": "pending",
"regulatory_notified": "True"
}
}
}
}
],
"connections": {
"Incident Webhook": {
"main": [
[
{
"node": "Classify Incident",
"type": "main",
"index": 0
}
]
]
},
"Classify Incident": {
"main": [
[
{
"node": "Slack Alert",
"type": "main",
"index": 0
},
{
"node": "Gmail Safety & Legal",
"type": "main",
"index": 0
},
{
"node": "Log Incident",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 5: Weekly ConstructionTech SaaS KPI Dashboard
Monday 8AM cron → PostgreSQL query → KPI build with WoW delta via $getWorkflowStaticData → Gmail to CEO + BCC VP Safety + COO → Slack summary. Tracked metrics:
- Active customers (WoW delta)
- MRR (WoW delta)
- Enterprise Construction ERP MRR
- OSHA-covered customers
- Davis-Bacon covered customers
- Active projects
- OSHA incidents (7d)
- Open Davis-Bacon disputes
- Lien filings (7d)
- OSHA incident status flag (ALERT if open incidents)
{
"name": "Weekly ConstructionTech SaaS KPI Dashboard",
"nodes": [
{
"id": "1",
"name": "Monday 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
250,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
}
},
{
"id": "2",
"name": "Query KPIs",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
450,
300
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(DISTINCT customer_id) AS active_customers, SUM(mrr_usd) AS mrr_usd, SUM(CASE WHEN tier='ENTERPRISE_CONSTRUCTION_ERP' THEN mrr_usd ELSE 0 END) AS enterprise_mrr, COUNT(DISTINCT CASE WHEN osha_covered=true THEN customer_id END) AS osha_customers, COUNT(DISTINCT CASE WHEN davis_bacon_covered=true THEN customer_id END) AS davis_bacon_customers, SUM(active_projects) AS active_projects, SUM(osha_incidents_7d) AS osha_incidents, SUM(davis_bacon_disputes_open) AS davis_bacon_disputes, SUM(lien_filings_7d) AS lien_filings FROM construction_metrics WHERE period_end >= NOW() - INTERVAL '7 days'"
}
},
{
"id": "3",
"name": "Build KPI Report",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
650,
300
],
"parameters": {
"jsCode": "const d=items[0].json;const prev=$getWorkflowStaticData('global');const mrrWoW=prev.mrr?(((d.mrr_usd-prev.mrr)/prev.mrr)*100).toFixed(1)+'%':'N/A';const custWoW=prev.customers?(((d.active_customers-prev.customers)/prev.customers)*100).toFixed(1)+'%':'N/A';const oshaAlert=d.osha_incidents>0?'ALERT: '+d.osha_incidents+' OSHA incidents pending (8h fatality clock)':'OK';const html='<h2>ConstructionTech SaaS Weekly KPIs</h2><table border=\"1\" cellpadding=\"6\"><tr><th>Metric</th><th>Value</th><th>WoW</th></tr><tr><td>Active Customers</td><td>'+d.active_customers+'</td><td>'+custWoW+'</td></tr><tr><td>MRR</td><td>$'+Number(d.mrr_usd).toLocaleString()+'</td><td>'+mrrWoW+'</td></tr><tr><td>Enterprise Construction ERP MRR</td><td>$'+Number(d.enterprise_mrr).toLocaleString()+'</td><td>-</td></tr><tr><td>OSHA-Covered Customers</td><td>'+d.osha_customers+'</td><td>-</td></tr><tr><td>Davis-Bacon Customers</td><td>'+d.davis_bacon_customers+'</td><td>-</td></tr><tr><td>Active Projects</td><td>'+Number(d.active_projects).toLocaleString()+'</td><td>-</td></tr><tr><td>OSHA Incidents 7d</td><td>'+d.osha_incidents+'</td><td>-</td></tr><tr><td>Davis-Bacon Disputes Open</td><td>'+d.davis_bacon_disputes+'</td><td>-</td></tr><tr><td>Lien Filings 7d</td><td>'+Number(d.lien_filings).toLocaleString()+'</td><td>-</td></tr></table><p>OSHA Status: '+oshaAlert+'</p>';$getWorkflowStaticData('global').mrr=d.mrr_usd;$getWorkflowStaticData('global').customers=d.active_customers;return [{json:{...d,html,mrrWoW,custWoW,oshaAlert}}];"
}
},
{
"id": "4",
"name": "Gmail CEO + BCC VP Safety",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
850,
300
],
"parameters": {
"operation": "send",
"toList": "ceo@yourcompany.com",
"bccList": "vp-safety@yourcompany.com,coo@yourcompany.com",
"subject": "=ConstructionTech Weekly KPIs \u2014 MRR {{$json.mrrWoW}} WoW | Projects: {{$json.active_projects}} | OSHA: {{$json.osha_incidents}}",
"message": "={{$json.html}}"
}
},
{
"id": "5",
"name": "Slack Summary",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
850,
420
],
"parameters": {
"channel": "#executive-summary",
"text": "=:construction: ConstructionTech Weekly: {{$json.active_customers}} customers | MRR ${{$json.mrr_usd?.toLocaleString()}} ({{$json.mrrWoW}} WoW) | Projects: {{$json.active_projects}} | OSHA customers: {{$json.osha_customers}} | OSHA incidents: {{$json.osha_incidents}} | Davis-Bacon disputes: {{$json.davis_bacon_disputes}} | Lien filings: {{$json.lien_filings}}"
}
}
],
"connections": {
"Monday 8AM": {
"main": [
[
{
"node": "Query KPIs",
"type": "main",
"index": 0
}
]
]
},
"Query KPIs": {
"main": [
[
{
"node": "Build KPI Report",
"type": "main",
"index": 0
}
]
]
},
"Build KPI Report": {
"main": [
[
{
"node": "Gmail CEO + BCC VP Safety",
"type": "main",
"index": 0
},
{
"node": "Slack Summary",
"type": "main",
"index": 0
}
]
]
}
}
}
Why cloud iPaaS is a structural liability for construction safety platforms
| Requirement | Cloud iPaaS | Self-hosted n8n |
|---|---|---|
| OSHA §1904.39 8h clock | Third-party queue latency during site incident | Pipeline runs inside your infrastructure, no third-party hop |
| OSHA investigation discovery | iPaaS becomes third-party subpoena target for safety records | Safety records stay within GC's privilege boundary |
| Davis-Bacon certified payroll | Cloud iPaaS = unauthorized DOL subprocessor | Payroll data stays within project management system perimeter |
| AIA A201 §3.18 indemnification | Subcontractor PII in cloud = extends indemnification chain | Indemnification chain stays within contractual boundary |
| EPA RCRA e-Manifest | Third-party manifest tracking dependency | Direct RCRA integration, no cloud intermediary |
The OSHA investigation discovery argument is the most actionable procurement argument for enterprise construction ERP platforms. When GCs process subcontractor injury records, safety inspection logs, and pre-task planning documents through cloud iPaaS, they extend their discovery production obligations to include a vendor they do not control and cannot instruct to hold. Self-hosted n8n eliminates this dependency by keeping the entire safety automation chain inside the GC's own system.
Get all 5 workflows + 10 more ConstructionTech automations in the FlowKit n8n Template Bundle ($97 for 15 templates, including the full ConstructionTech pack).
This article is for informational purposes only and does not constitute legal advice. OSHA, EPA, DOL, USGBC, and state lien law requirements vary by project, jurisdiction, and employer classification. Consult qualified construction counsel for specific compliance obligations.
Top comments (0)