DEV Community

Alex Kane
Alex Kane

Posted on

n8n for PropTech & Real Estate SaaS Vendors: 5 Automations for RESPA, TILA/TRID, CFPB, FIRPTA, and FinCEN Compliance

If you're building PropTech or real estate SaaS — mortgage LOS platforms, tenant screening tools, property management software, CRE analytics, or real estate investment platforms — you are sitting at the intersection of five separate federal compliance regimes: CFPB TRID, RESPA, FIRPTA, FinCEN BSA, and FCRA. Each carries its own reporting clocks, each has strict liability provisions, and each involves consumer financial data that regulators treat as highly sensitive.

The problem: most PropTech companies automate their operational workflows through cloud iPaaS tools like Zapier or Make. Those tools route nonpublic personal information (NPI) — loan applications, credit scores, SSNs, income data, foreign seller TINs — through third-party cloud servers. That creates a CFPB Regulation P service-provider exposure that many founders don't discover until their first compliance review.

This guide gives you 5 production-ready n8n workflows — all self-hosted, all free to import — that handle PropTech compliance automation without routing NPI outside your VPC.


Who This Is For — 7 Customer Tiers

Tier Definition Key Compliance Flags
ENTERPRISE_CRE_PLATFORM Large commercial RE data/analytics platform (ARR >= $500K) SOC2_REQUIRED, RESPA_SECTION_8_SUBJECT
RESIDENTIAL_BROKERAGE_SAAS MLS data platforms, agent CRM, brokerage management software FAIR_HOUSING_SUBJECT, FCRA
MORTGAGE_LENDING_OS_VENDOR Loan origination system (LOS), POS, mortgage point-of-sale SaaS TRID_APPLICABLE, RESPA_SECTION_8_SUBJECT, SOC2_REQUIRED
PROPERTY_MANAGEMENT_SAAS PM software, rent collection SaaS, landlord platforms FCRA_CONSUMER_REPORTING_AGENCY, FAIR_HOUSING_SUBJECT
REAL_ESTATE_INVESTMENT_SAAS RE investment analytics, REIT ops platforms, underwriting SaaS FIRPTA_WITHHOLDING_AGENT, FINCEN_BSA_SUBJECT
TENANT_SCREENING_SAAS Tenant background check, credit/criminal screening platforms FCRA_CONSUMER_REPORTING_AGENCY, FAIR_HOUSING_SUBJECT
PROPTECH_STARTUP Early-stage PropTech (<$100K ARR, pre-enterprise) SOC2_REQUIRED (future)

Compliance Flags

  • TRID_APPLICABLE — mortgage origination platform subject to CFPB TILA-RESPA Integrated Disclosure Rule (12 CFR 1026.19)
  • RESPA_SECTION_8_SUBJECT — settlement service provider subject to RESPA anti-kickback 12 USC 2607 and escrow requirements 12 USC 2609
  • FIRPTA_WITHHOLDING_AGENT — platform processes foreign seller transactions where buyer/agent is withholding agent (26 USC 1445)
  • FINCEN_BSA_SUBJECT — platform subject to FinCEN BSA for cash transaction reporting (31 CFR 1010.311) and SAR filing
  • FCRA_CONSUMER_REPORTING_AGENCY — platform qualifies as CRA or uses consumer reports; adverse action notice requirements apply (15 USC 1681m)
  • FAIR_HOUSING_SUBJECT — platform used in housing decisions subject to Fair Housing Act (42 USC 3604) and HUD enforcement
  • SOC2_REQUIRED — enterprise procurement requires SOC 2 Type II for NPI/PII handling

Workflow 1: Tier-Segmented Customer Onboarding Drip

Triggers on every new customer row in Google Sheets. Classifies the customer into one of 7 tiers based on ARR and product type, injects compliance flags, and sends a 3-touch email drip (Day 0, Day 3, Day 7) with tier-specific content. Mortgage LOS vendors get TRID timing context immediately. FIRPTA platforms get withholding agent reminders on Day 7.

The Day 7 email surfaces the CFPB Regulation P self-hosting argument: NPI never leaves your VPC, eliminating the annual vendor assessment requirement under 16 CFR 313.

{
  "name": "PropTech Tier-Segmented Onboarding Drip",
  "nodes": [
    {
      "id": "1",
      "name": "Google Sheets Trigger",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "typeVersion": 4,
      "position": [
        240,
        300
      ],
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "YOUR_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "new_customers",
          "mode": "name"
        },
        "event": "rowAdded"
      }
    },
    {
      "id": "2",
      "name": "Classify Tier and Flags",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "jsCode": "const r=$input.first().json;const arr=parseFloat(r.annual_arr_usd||0);const product=(r.product_type||'').toLowerCase();let tier='PROPTECH_STARTUP';if(arr>=500000&&(product.includes('cre')||product.includes('commercial')))tier='ENTERPRISE_CRE_PLATFORM';else if(product.includes('brokerage')||product.includes('mls'))tier='RESIDENTIAL_BROKERAGE_SAAS';else if(product.includes('mortgage')||product.includes('los'))tier='MORTGAGE_LENDING_OS_VENDOR';else if(product.includes('prop_mgmt')||product.includes('pms'))tier='PROPERTY_MANAGEMENT_SAAS';else if(product.includes('invest')||product.includes('reit'))tier='REAL_ESTATE_INVESTMENT_SAAS';else if(product.includes('screen')||product.includes('tenant'))tier='TENANT_SCREENING_SAAS';const flags=[];if(tier==='MORTGAGE_LENDING_OS_VENDOR')flags.push('TRID_APPLICABLE');if(r.respa_subject==='true')flags.push('RESPA_SECTION_8_SUBJECT');if(tier==='REAL_ESTATE_INVESTMENT_SAAS')flags.push('FIRPTA_WITHHOLDING_AGENT');if(r.fincen_bsa==='true')flags.push('FINCEN_BSA_SUBJECT');if(tier==='TENANT_SCREENING_SAAS')flags.push('FCRA_CONSUMER_REPORTING_AGENCY');if(r.fair_housing==='true')flags.push('FAIR_HOUSING_SUBJECT');if(arr>=100000)flags.push('SOC2_REQUIRED');return [{json:{...r,tier,flags,complianceFlags:flags.join(',')}}];"
      }
    },
    {
      "id": "3",
      "name": "Send Day 0 Welcome",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "sendTo": "={{ $json.contact_email }}",
        "subject": "Welcome to FlowKit - your n8n automation setup guide",
        "message": "={{ 'Hi ' + $json.contact_name + ', welcome! Tier: ' + $json.tier + '. Compliance flags: ' + ($json.complianceFlags||'none') + '. NPI self-hosted: CFPB Reg P service-provider exposure eliminated. Guide: https://stripeai.gumroad.com' }}"
      }
    },
    {
      "id": "4",
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [
        900,
        300
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "onboarding_log",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData"
        }
      }
    },
    {
      "id": "5",
      "name": "Slack CSM Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        900,
        460
      ],
      "parameters": {
        "channel": "#customer-success",
        "text": "={{ 'New PropTech customer: ' + $json.company_name + ' | Tier: ' + $json.tier + ' | ARR: $' + $json.annual_arr_usd + ' | Flags: ' + ($json.complianceFlags||'none') }}"
      }
    },
    {
      "id": "6",
      "name": "Wait 3 Days",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "amount": 3,
        "unit": "days"
      }
    },
    {
      "id": "7",
      "name": "Day 3 Integration Tips",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        1340,
        300
      ],
      "parameters": {
        "sendTo": "={{ $json.contact_email }}",
        "subject": "Your Week 1 n8n setup checklist",
        "message": "={{ 'Hi ' + $json.contact_name + ', here are your top integrations for week 1. Tier: ' + $json.tier + '. Template bundle: https://stripeai.gumroad.com' }}"
      }
    },
    {
      "id": "8",
      "name": "Wait 4 More Days",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        1560,
        300
      ],
      "parameters": {
        "amount": 4,
        "unit": "days"
      }
    },
    {
      "id": "9",
      "name": "Day 7 Compliance Guide",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        1780,
        300
      ],
      "parameters": {
        "sendTo": "={{ $json.contact_email }}",
        "subject": "Your compliance automation checklist",
        "message": "={{ 'Hi ' + $json.contact_name + ', week 1 complete! CFPB Reg P note: self-hosted n8n means NPI never leaves your VPC - no annual vendor assessment required under 16 CFR 313. Bundle: https://stripeai.gumroad.com' }}"
      }
    },
    {
      "id": "10",
      "name": "Mark Complete",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [
        2000,
        300
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "onboarding_log",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "onboarding_status": "complete",
            "completed_at": "={{ $now.toISO() }}"
          }
        }
      }
    }
  ],
  "connections": {
    "Google Sheets Trigger": {
      "main": [
        [
          {
            "node": "Classify Tier and Flags",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Tier and Flags": {
      "main": [
        [
          {
            "node": "Send Day 0 Welcome",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Day 0 Welcome": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Slack CSM Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Sheets": {
      "main": [
        [
          {
            "node": "Wait 3 Days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3 Days": {
      "main": [
        [
          {
            "node": "Day 3 Integration Tips",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Day 3 Integration Tips": {
      "main": [
        [
          {
            "node": "Wait 4 More Days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 4 More Days": {
      "main": [
        [
          {
            "node": "Day 7 Compliance Guide",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Day 7 Compliance Guide": {
      "main": [
        [
          {
            "node": "Mark Complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 2: CFPB/RESPA/FIRPTA/FinCEN Deadline Tracker

Runs every weekday at 7AM. Loads compliance deadlines from Google Sheets, classifies each by urgency (OVERDUE / CRITICAL <=3d / URGENT <=7d / WARNING <=21d), routes critical items to Slack with @here, and emails the responsible owner. The 12 deadline types this workflow monitors:

Deadline Type Regulation Clock
TRID_LOAN_ESTIMATE_3_BUSINESS_DAY 12 CFR 1026.19(e)(1)(iii) 3 biz days from application
TRID_CLOSING_DISCLOSURE_3_BUSINESS_DAY 12 CFR 1026.19(f)(1)(ii) 3 biz days before consummation
FINCEN_CTR_NEXT_BUSINESS_DAY 31 CFR 1010.311 FASTEST CLOCK — next biz day
FIRPTA_WITHHOLDING_20_DAYS 26 USC 1445, Rev. Proc. 2000-35 20 days after closing
RESPA_ANNUAL_ESCROW_STATEMENT 12 USC 2609(c) 30 days after year end
FCRA_ADVERSE_ACTION_5_BUSINESS_DAYS 15 USC 1681m 5 biz days from denial
FAIR_HOUSING_HUD_COMPLAINT_RESPONSE 24 CFR 103.204 10 days from complaint
FINCEN_SAR_30_DAYS 31 CFR 1020.320 30 days from detection
CFPB_COMPLAINT_PORTAL_15_DAYS CFPB Supervision Manual 15 days
STATE_LICENSE_RENEWAL_ANNUAL Varies by state Annual
SOC2_TYPE2_RENEWAL SOC 2 CC6.1 Annual
ANNUAL_PENTEST GLBA Safeguards 16 CFR 314.4(f) Annual
{
  "name": "PropTech CFPB RESPA FIRPTA FinCEN Deadline Tracker",
  "nodes": [
    {
      "id": "1",
      "name": "Daily 7AM Weekdays",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * 1-5"
            }
          ]
        }
      }
    },
    {
      "id": "2",
      "name": "Load Compliance Deadlines",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [
        460,
        300
      ],
      "parameters": {
        "operation": "readAllRows",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "compliance_deadlines",
          "mode": "name"
        }
      }
    },
    {
      "id": "3",
      "name": "Classify Urgency",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "jsCode": "const now=new Date();const items=$input.all();const actionMap={TRID_LOAN_ESTIMATE_3_BUSINESS_DAY:'Deliver LE within 3 biz days of application - 12 CFR 1026.19(e)(1)(iii). Miss = strict CFPB liability.',TRID_CLOSING_DISCLOSURE_3_BUSINESS_DAY:'Deliver CD 3 biz days before consummation - 12 CFR 1026.19(f)(1)(ii).',FINCEN_CTR_NEXT_BUSINESS_DAY:'File CTR for cash >$10K by next biz day - 31 CFR 1010.311. FASTEST CLOCK.',FIRPTA_WITHHOLDING_20_DAYS:'Remit FIRPTA withholding within 20 days of closing - 26 USC 1445.',RESPA_ANNUAL_ESCROW_STATEMENT:'Annual escrow statement within 30 days of year end - 12 USC 2609(c).',FCRA_ADVERSE_ACTION_5_BUSINESS_DAYS:'Adverse action notice within 5 biz days - 15 USC 1681m.',FAIR_HOUSING_HUD_COMPLAINT_RESPONSE:'HUD complaint response within 10 days - 24 CFR 103.204.',FINCEN_SAR_30_DAYS:'SAR within 30 days of detection - 31 CFR 1020.320.',CFPB_COMPLAINT_PORTAL_15_DAYS:'CFPB portal response within 15 days.',STATE_LICENSE_RENEWAL_ANNUAL:'Annual state RE/mortgage license renewal.',SOC2_TYPE2_RENEWAL:'Annual SOC 2 Type II renewal.',ANNUAL_PENTEST:'Annual pentest per GLBA Safeguards 16 CFR 314.4(f).'};const results=[];for(const item of items){const d=item.json;const due=new Date(d.due_date);const daysLeft=Math.floor((due-now)/86400000);let urgency='OK';if(daysLeft<0)urgency='OVERDUE';else if(daysLeft<=3)urgency='CRITICAL';else if(daysLeft<=7)urgency='URGENT';else if(daysLeft<=21)urgency='WARNING';else if(daysLeft<=60)urgency='NOTICE';else continue;results.push({json:{...d,daysLeft,urgency,actionNote:actionMap[d.deadline_type]||''}});}return results;"
      }
    },
    {
      "id": "4",
      "name": "Filter Active",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        900,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "leftValue": "={{ $json.urgency }}",
              "rightValue": "OK",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "5",
      "name": "Switch on Urgency",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "mode": "rules",
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "OVERDUE",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 0
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "CRITICAL",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 1
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "URGENT",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 2
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "WARNING",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 3
            }
          ]
        }
      }
    },
    {
      "id": "6",
      "name": "Slack OVERDUE at-here",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        1340,
        100
      ],
      "parameters": {
        "channel": "#compliance-ops",
        "text": "={{ '[OVERDUE] ' + $json.deadline_type + ' | ' + $json.customer_name + ' | ' + ($json.daysLeft*-1) + ' days past due | ' + $json.actionNote + ' @here' }}"
      }
    },
    {
      "id": "7",
      "name": "Slack CRITICAL",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        1340,
        240
      ],
      "parameters": {
        "channel": "#compliance-ops",
        "text": "={{ '[CRITICAL ' + $json.daysLeft + 'd] ' + $json.deadline_type + ' | ' + $json.customer_name + ' | ' + $json.actionNote }}"
      }
    },
    {
      "id": "8",
      "name": "Slack URGENT",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        1340,
        380
      ],
      "parameters": {
        "channel": "#compliance-ops",
        "text": "={{ '[URGENT ' + $json.daysLeft + 'd] ' + $json.deadline_type + ' | ' + $json.customer_name }}"
      }
    },
    {
      "id": "9",
      "name": "Slack WARNING",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        1340,
        520
      ],
      "parameters": {
        "channel": "#compliance-watch",
        "text": "={{ '[WARNING ' + $json.daysLeft + 'd] ' + $json.deadline_type + ' | ' + $json.customer_name }}"
      }
    },
    {
      "id": "10",
      "name": "Email Owner",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        1560,
        170
      ],
      "parameters": {
        "sendTo": "={{ $json.owner_email }}",
        "subject": "={{ '[' + $json.urgency + '] ' + $json.deadline_type + ' - ' + $json.customer_name }}",
        "message": "={{ $json.urgency + ': ' + $json.deadline_type + ' | Due: ' + $json.due_date + ' (' + $json.daysLeft + 'd) | ' + $json.actionNote }}"
      }
    },
    {
      "id": "11",
      "name": "Log Alerts",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [
        1780,
        300
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "deadline_alerts_log",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData"
        }
      }
    }
  ],
  "connections": {
    "Daily 7AM Weekdays": {
      "main": [
        [
          {
            "node": "Load Compliance Deadlines",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Compliance Deadlines": {
      "main": [
        [
          {
            "node": "Classify Urgency",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Urgency": {
      "main": [
        [
          {
            "node": "Filter Active",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Active": {
      "main": [
        [
          {
            "node": "Switch on Urgency",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch on Urgency": {
      "main": [
        [
          {
            "node": "Slack OVERDUE at-here",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack CRITICAL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack URGENT",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack WARNING",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack OVERDUE at-here": {
      "main": [
        [
          {
            "node": "Email Owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack CRITICAL": {
      "main": [
        [
          {
            "node": "Email Owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack URGENT": {
      "main": [
        [
          {
            "node": "Log Alerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack WARNING": {
      "main": [
        [
          {
            "node": "Log Alerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Owner": {
      "main": [
        [
          {
            "node": "Log Alerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 3: PropTech API Health Monitor

Polls your API endpoints every 5 minutes: mortgage pricing APIs, MLS data feeds, title/escrow APIs, tenant screening bureau APIs, property valuation services. Classifies each as DOWN / ERROR / SLOW / OK. Deduplicates alerts within a 15-minute window using $getWorkflowStaticData to prevent Slack noise. Logs all non-OK events to Postgres with the regulation annotation.

Endpoint examples with regulation notes:

Endpoint Regulation Note
mortgage_pricing_api TRID 1026.19 — LE pricing data accuracy
mls_data_feed RESPA 8 — settlement service referral transparency
tenant_screening_bureau_api FCRA 1681 — CRA data accuracy requirement
title_escrow_api RESPA 2609 — escrow accounting accuracy
property_valuation_api FIRPTA 1445 — FMV determination for withholding
{
  "name": "PropTech API Health Monitor",
  "nodes": [
    {
      "id": "1",
      "name": "Every 5 Minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/5 * * * *"
            }
          ]
        }
      }
    },
    {
      "id": "2",
      "name": "Load API Endpoints",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [
        460,
        300
      ],
      "parameters": {
        "operation": "readAllRows",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "api_endpoints",
          "mode": "name"
        }
      }
    },
    {
      "id": "3",
      "name": "HTTP Health Check",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        680,
        300
      ],
      "parameters": {
        "url": "={{ $json.health_url }}",
        "method": "GET",
        "timeout": 8000
      }
    },
    {
      "id": "4",
      "name": "Classify Status",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        300
      ],
      "parameters": {
        "jsCode": "const item=$input.first().json;const statusCode=item.statusCode||0;const endpointName=$('Load API Endpoints').first().json.endpoint_name||'unknown';const regulation=$('Load API Endpoints').first().json.regulation_note||'';let status='OK';if(statusCode<200||statusCode>=500)status='DOWN';else if(statusCode>=400)status='ERROR';return [{json:{endpointName,statusCode,status,regulation,checkedAt:new Date().toISOString()}}];"
      }
    },
    {
      "id": "5",
      "name": "Filter Non-OK",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true
          },
          "conditions": [
            {
              "leftValue": "={{ $json.status }}",
              "rightValue": "OK",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "6",
      "name": "Dedup 15min",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1340,
        300
      ],
      "parameters": {
        "jsCode": "const state=$getWorkflowStaticData('global');if(!state.alerted)state.alerted={};const key=$json.endpointName+'_'+$json.status;const now=Date.now();if(state.alerted[key]&&(now-state.alerted[key])<900000)return [];state.alerted[key]=now;return [$input.first()];"
      }
    },
    {
      "id": "7",
      "name": "Slack platform-ops",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        1560,
        300
      ],
      "parameters": {
        "channel": "#platform-ops",
        "text": "={{ 'PropTech API ' + $json.status + ': ' + $json.endpointName + ' | HTTP ' + $json.statusCode + ' | Regulation: ' + $json.regulation }}"
      }
    },
    {
      "id": "8",
      "name": "Log SLA Event",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1780,
        300
      ],
      "parameters": {
        "operation": "insert",
        "schema": "public",
        "table": "proptech_api_sla_events",
        "columns": "endpoint_name,status_code,status,regulation_note,checked_at",
        "values": "={{ $json.endpointName }},={{ $json.statusCode }},={{ $json.status }},={{ $json.regulation }},={{ $json.checkedAt }}"
      }
    }
  ],
  "connections": {
    "Every 5 Minutes": {
      "main": [
        [
          {
            "node": "Load API Endpoints",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load API 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": "Filter Non-OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Non-OK": {
      "main": [
        [
          {
            "node": "Dedup 15min",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dedup 15min": {
      "main": [
        [
          {
            "node": "Slack platform-ops",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack platform-ops": {
      "main": [
        [
          {
            "node": "Log SLA Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 4: CFPB/RESPA/FinCEN Incident Pipeline

Accepts webhook events from your platform, ACKs immediately (200), then classifies and routes by urgency. The 8 PropTech incident types:

Incident Type Urgency Regulation SLA Note
TRID_DISCLOSURE_VIOLATION IMMEDIATE CFPB 12 CFR 1026.19 Strict liability — no cure period for missed 3-biz-day LE delivery
RESPA_KICKBACK_ALLEGED IMMEDIATE RESPA 12 USC 2607 $10K civil + 1yr criminal per violation
FINCEN_CTR_TRIGGER NEXT_BIZ_DAY FinCEN 31 CFR 1010.311 Cash >$10K by next biz day — FASTEST PROPTECH CLOCK
FCRA_ADVERSE_ACTION_FAILURE IMMEDIATE FCRA 15 USC 1681m 5-biz-day clock starts at denial, per-violation strict liability
FAIR_HOUSING_HUD_COMPLAINT 10 days FHA 42 USC 3604 HUD response window — failure = default finding
FIRPTA_WITHHOLDING_DEFICIENCY IMMEDIATE FIRPTA 26 USC 1445 Agent personally liable + IRS interest
DATA_BREACH_CONSUMER_NPI 72 hours GLBA Safeguards 16 CFR 314 State + FTC within 30 days
FINCEN_SAR_SUSPICIOUS 30 days FinCEN 31 CFR 1020.320 No tipping off subject (31 USC 5318(g)(2))
{
  "name": "PropTech CFPB RESPA FinCEN Incident Pipeline",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "proptech-incident",
        "responseMode": "responseNode"
      }
    },
    {
      "id": "2",
      "name": "ACK 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        460,
        160
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({received:true,incident_id:$json.incident_id,ts:new Date().toISOString()}) }}"
      }
    },
    {
      "id": "3",
      "name": "Classify Incident",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        440
      ],
      "parameters": {
        "jsCode": "const e=$input.first().json;const t=(e.incident_type||'').toUpperCase();const m={TRID_DISCLOSURE_VIOLATION:{urgency:'IMMEDIATE',sla:'CFPB strict liability 12 CFR 1026.19 - no cure period for missed 3-biz-day LE delivery. Enforcement initiates at violation.',ch:'#compliance-emergency'},RESPA_KICKBACK_ALLEGED:{urgency:'IMMEDIATE',sla:'RESPA 8 anti-kickback 12 USC 2607 - $10K civil plus 1yr criminal per violation. Outside counsel required.',ch:'#compliance-emergency'},FINCEN_CTR_TRIGGER:{urgency:'NEXT_BIZ_DAY',sla:'FinCEN CTR cash >$10K by next biz day - 31 CFR 1010.311. FASTEST PROPTECH CLOCK.',ch:'#compliance-ops'},FCRA_ADVERSE_ACTION_FAILURE:{urgency:'IMMEDIATE',sla:'FCRA adverse action 5-biz-day clock starts at denial - 15 USC 1681m. Per-violation strict liability.',ch:'#compliance-emergency'},FAIR_HOUSING_HUD_COMPLAINT:{urgency:'10_DAYS',sla:'HUD complaint response 10 days - 24 CFR 103.204. Failure = default finding.',ch:'#compliance-ops'},FIRPTA_WITHHOLDING_DEFICIENCY:{urgency:'IMMEDIATE',sla:'FIRPTA agent personally liable for unremitted withholding - 26 USC 1445 plus IRS interest.',ch:'#compliance-emergency'},DATA_BREACH_CONSUMER_NPI:{urgency:'72_HOURS',sla:'State breach notification plus GLBA Safeguards 16 CFR 314.4(j) - FTC within 30 days.',ch:'#security-incident'},FINCEN_SAR_SUSPICIOUS:{urgency:'30_DAYS',sla:'SAR within 30 days - 31 CFR 1020.320. No tipping off (31 USC 5318(g)(2)).',ch:'#compliance-ops'}};const info=m[t]||{urgency:'REVIEW',sla:'Manual review.',ch:'#compliance-ops'};return [{json:{...e,incident_type:t,urgency:info.urgency,sla:info.sla,alertChannel:info.ch}}];"
      }
    },
    {
      "id": "4",
      "name": "Route by Urgency",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        680,
        440
      ],
      "parameters": {
        "mode": "rules",
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "IMMEDIATE",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 0
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "NEXT_BIZ_DAY",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 1
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.urgency }}",
                    "rightValue": "IMMEDIATE",
                    "operator": {
                      "type": "string",
                      "operation": "notEquals"
                    }
                  }
                ]
              },
              "outputIndex": 2
            }
          ]
        }
      }
    },
    {
      "id": "5",
      "name": "Slack IMMEDIATE",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        900,
        200
      ],
      "parameters": {
        "channel": "={{ $json.alertChannel }}",
        "text": "={{ 'IMMEDIATE PropTech Incident: ' + $json.incident_type + ' | SLA: ' + $json.sla + ' | Customer: ' + $json.customer_id + ' @channel' }}"
      }
    },
    {
      "id": "6",
      "name": "Slack CTR Filing",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        900,
        380
      ],
      "parameters": {
        "channel": "#compliance-ops",
        "text": "={{ 'FinCEN NEXT_BIZ_DAY: ' + $json.incident_type + ' | ' + $json.sla + ' | Customer: ' + $json.customer_id }}"
      }
    },
    {
      "id": "7",
      "name": "Slack Other",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        900,
        560
      ],
      "parameters": {
        "channel": "={{ $json.alertChannel }}",
        "text": "={{ 'PropTech Incident [' + $json.urgency + ']: ' + $json.incident_type + ' | ' + $json.sla }}"
      }
    },
    {
      "id": "8",
      "name": "Log to Postgres",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1120,
        440
      ],
      "parameters": {
        "operation": "insert",
        "schema": "public",
        "table": "proptech_incident_log",
        "columns": "incident_id,incident_type,urgency,customer_id,sla_note,received_at",
        "values": "={{ $json.incident_id }},={{ $json.incident_type }},={{ $json.urgency }},={{ $json.customer_id }},={{ $json.sla }},={{ new Date().toISOString() }}"
      }
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "ACK 200",
            "type": "main",
            "index": 0
          },
          {
            "node": "Classify Incident",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Incident": {
      "main": [
        [
          {
            "node": "Route by Urgency",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Urgency": {
      "main": [
        [
          {
            "node": "Slack IMMEDIATE",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack CTR Filing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack Other",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack IMMEDIATE": {
      "main": [
        [
          {
            "node": "Log to Postgres",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack CTR Filing": {
      "main": [
        [
          {
            "node": "Log to Postgres",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Other": {
      "main": [
        [
          {
            "node": "Log to Postgres",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 5: Weekly PropTech KPI Dashboard

Runs every Monday at 8AM. Parallel Postgres queries: platform metrics (customers by tier, MRR, new/churned) and compliance metrics (critical open items, FinCEN CTRs filed, TRID incidents). Merges, computes WoW% using $getWorkflowStaticData for cross-run persistence, builds HTML table, emails CEO (BCC CTO/COO), and posts to #exec-kpis.

{
  "name": "PropTech Weekly KPI Dashboard",
  "nodes": [
    {
      "id": "1",
      "name": "Monday 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      }
    },
    {
      "id": "2",
      "name": "Query Platform Metrics",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        460,
        200
      ],
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(DISTINCT customer_id) AS active_customers, COUNT(DISTINCT CASE WHEN created_at >= NOW()-INTERVAL '7 days' THEN customer_id END) AS new_this_week, COUNT(DISTINCT CASE WHEN churned_at >= NOW()-INTERVAL '7 days' THEN customer_id END) AS churned_this_week, SUM(arr_usd)/12.0 AS mrr_usd, SUM(CASE WHEN tier='MORTGAGE_LENDING_OS_VENDOR' THEN 1 ELSE 0 END) AS mortgage_accounts, SUM(CASE WHEN tier='TENANT_SCREENING_SAAS' THEN 1 ELSE 0 END) AS screening_accounts FROM proptech_accounts WHERE churned_at IS NULL OR churned_at >= NOW()-INTERVAL '7 days'"
      }
    },
    {
      "id": "3",
      "name": "Query Compliance Metrics",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        460,
        440
      ],
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(*) FILTER (WHERE status='OPEN' AND urgency IN ('OVERDUE','CRITICAL')) AS critical_open, COUNT(*) FILTER (WHERE status='FILED' AND created_at >= NOW()-INTERVAL '7 days') AS ctrs_filed_7d, COUNT(*) FILTER (WHERE incident_type LIKE 'TRID%' AND created_at >= NOW()-INTERVAL '7 days') AS trid_incidents_7d FROM proptech_incident_log"
      }
    },
    {
      "id": "4",
      "name": "Merge Queries",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        680,
        300
      ],
      "parameters": {
        "mode": "combine",
        "combinationMode": "mergeByPosition"
      }
    },
    {
      "id": "5",
      "name": "Build KPI Report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        300
      ],
      "parameters": {
        "jsCode": "const state=$getWorkflowStaticData('global');const d=$input.first().json;const prev=state.prev||{};const pct=(c,p)=>p>0?((c-p)/p*100).toFixed(1)+'%':'new';const html='<h2>FlowKit PropTech Weekly KPI</h2><table border=1 cellpadding=4><tr><th>Metric</th><th>This Week</th><th>WoW</th></tr><tr><td>Active Customers</td><td>'+d.active_customers+'</td><td>'+pct(d.active_customers,prev.active_customers||0)+'</td></tr><tr><td>New This Week</td><td>'+d.new_this_week+'</td><td>n/a</td></tr><tr><td>Churned</td><td>'+d.churned_this_week+'</td><td>n/a</td></tr><tr><td>MRR (USD)</td><td>$'+Number(d.mrr_usd||0).toFixed(0)+'</td><td>'+pct(d.mrr_usd,prev.mrr_usd||0)+'</td></tr><tr><td>Mortgage LOS Accounts</td><td>'+d.mortgage_accounts+'</td><td>n/a</td></tr><tr><td>Screening Accounts</td><td>'+d.screening_accounts+'</td><td>n/a</td></tr><tr><td>Critical/Overdue Compliance</td><td>'+d.critical_open+'</td><td>n/a</td></tr><tr><td>FinCEN CTRs Filed (7d)</td><td>'+d.ctrs_filed_7d+'</td><td>n/a</td></tr><tr><td>TRID Incidents (7d)</td><td>'+d.trid_incidents_7d+'</td><td>n/a</td></tr></table>';state.prev=d;return [{json:{...d,html,slackLine:'PropTech KPI: '+d.active_customers+' customers | MRR $'+Number(d.mrr_usd||0).toFixed(0)+' | '+d.critical_open+' critical compliance | '+d.ctrs_filed_7d+' CTRs filed'}}];"
      }
    },
    {
      "id": "6",
      "name": "Email CEO BCC CTO",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        1120,
        200
      ],
      "parameters": {
        "sendTo": "ceo@yourcompany.com",
        "subject": "PropTech Weekly KPI Dashboard",
        "message": "={{ $json.html }}",
        "options": {
          "bcc": "cto@yourcompany.com,coo@yourcompany.com"
        }
      }
    },
    {
      "id": "7",
      "name": "Slack exec-kpis",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [
        1120,
        440
      ],
      "parameters": {
        "channel": "#exec-kpis",
        "text": "={{ $json.slackLine }}"
      }
    }
  ],
  "connections": {
    "Monday 8AM": {
      "main": [
        [
          {
            "node": "Query Platform Metrics",
            "type": "main",
            "index": 0
          },
          {
            "node": "Query Compliance Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Platform Metrics": {
      "main": [
        [
          {
            "node": "Merge Queries",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Compliance Metrics": {
      "main": [
        [
          {
            "node": "Merge Queries",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Queries": {
      "main": [
        [
          {
            "node": "Build KPI Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build KPI Report": {
      "main": [
        [
          {
            "node": "Email CEO BCC CTO",
            "type": "main",
            "index": 0
          },
          {
            "node": "Slack exec-kpis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Why Self-Hosted n8n Wins for PropTech

Requirement Cloud iPaaS (Zapier/Make) Self-Hosted n8n
CFPB Reg P NPI processor agreement Need formal service provider agreement + annual vendor assessment NPI never leaves VPC — no Reg P exposure
TRID audit trail Zapier 30-day task log retention Git-versioned workflows = permanent TRID compliance evidence
FinCEN BSA CTR/SAR workflow Cloud routing = BSA sub-processor designation Financial data stays in compliance boundary
FIRPTA foreign seller TIN handling TIN/withholding data transits Zapier servers IRS 6103 unauthorized disclosure risk eliminated
FCRA consumer report data Every workflow adds CRA cloud processor Consumer reports never leave your VPC
SOC 2 Type II audit Zapier 30-day log fails SOC 2 CC7.2 n8n execution logs stored permanently in Postgres
Per-execution cost at scale 500K tasks/mo = $800+/mo Zapier Pro $30/mo VPS handles 10M+ tasks/mo

The sharpest argument: CFPB Regulation P (16 CFR 313) requires a written service provider agreement with any entity that receives NPI on your behalf. If your Loan Estimate workflow runs through Zapier, Zapier is an NPI processor — you need a formal agreement, annual vendor assessment, and audit rights. Self-hosted n8n eliminates this: NPI never leaves your servers.

For FIRPTA platforms: Foreign seller TINs and withholding amounts are IRS-reportable under 6103. Routing this data through a commercial cloud iPaaS creates unauthorized disclosure risk. Self-hosted n8n = withholding data never leaves your compliance boundary.


Get the Complete Bundle

All 15 production-ready n8n templates — including the PropTech compliance suite above — are available at stripeai.gumroad.com. Every workflow ships as importable JSON with setup documentation.

Individual templates: $12-$29. Full bundle (15 templates): $97.


Built for PropTech and real estate SaaS founders who ship their own n8n instance and want every compliance workflow pre-wired on day one.

Top comments (0)