If you're building WealthTech or investment management SaaS, your customers' trade records, client recommendations, and portfolio data carry serious regulatory weight.
SEC Rule 17a-4, Reg BI, FINRA Rule 4370, and Form ADV requirements aren't just compliance checkboxes — they're examination gates.
When the SEC requests records, they expect production from your systems — not a subpoena detour through your cloud automation vendor.
This guide covers 5 import-ready n8n workflows for WealthTech SaaS vendors, with full JSON.
Each maps to a real compliance obligation your customers are already managing.
Why WealthTech SaaS Vendors Are Moving Automation Off Cloud iPaaS
The core issue is SEC Rule 17a-4(f) — WORM electronic record storage.
Rule 17a-4(f) requires that electronically stored records be non-rewriteable, non-erasable, and immediately accessible.
Cloud iPaaS (Zapier, Make) processes and logs workflow data on their infrastructure.
When your automation routes trade records through cloud iPaaS:
- iPaaS execution logs contain trade record data
- That data is stored outside your WORM-compliant systems
- SEC examination request = record production gap
- Examination finding = potential enforcement action
The second issue is Reg BI — Best Interest obligation.
Reg BI §240.15l-1 requires broker-dealers to act in the customer's best interest at the time of a recommendation.
Automated recommendation pipelines routing client data through cloud iPaaS = third-party data handler outside your supervision boundary.
The supervision obligation doesn't stop at your network perimeter.
This is an architecture decision, not a security incident.
Self-hosted n8n eliminates both exposures by keeping automation inside your infrastructure boundary.
SEC Rule 17a-4 WORM analysis — the 5 tiers most at risk:
| Tier | Primary Regulation | Fastest Clock | Record Exposure |
|---|---|---|---|
| Enterprise Wealth Mgmt | SEC 17a-4 + Reg BI | IMMEDIATE SEC exam | Trade + recommendation records |
| Broker-Dealer SaaS | SEC 17a-3/17a-4 WORM | IMMEDIATE SEC exam | Order and trade records |
| RIA SaaS Vendor | Advisers Act §204 + Reg BI | IMMEDIATE SEC exam | Client recommendation data |
| Robo-Advisor Platform | Reg BI §240.15l-1 | IMMEDIATE SEC exam | Algorithm input/output records |
| Crypto Trading SaaS | CFTC Dodd-Frank §731 | Same-day CFTC reporting | Swap confirmation data |
The 7 Customer Tiers
{
"customer_tiers": [
{
"tier": "ENTERPRISE_WEALTH_MGMT_PLATFORM",
"compliance_flags": [
"SEC_17A4_WORM_SUBJECT",
"RIA_REGISTERED_ADVISER",
"FINRA_MEMBER_FIRM",
"REG_BI_SUBJECT",
"SOC2_REQUIRED"
],
"fastest_clock": "SEC_EXAMINATION_REQUEST IMMEDIATE"
},
{
"tier": "RIA_SAAS_VENDOR",
"compliance_flags": [
"RIA_REGISTERED_ADVISER",
"REG_BI_SUBJECT"
],
"fastest_clock": "SEC_EXAMINATION_REQUEST IMMEDIATE"
},
{
"tier": "BROKER_DEALER_SAAS",
"compliance_flags": [
"SEC_17A4_WORM_SUBJECT",
"FINRA_MEMBER_FIRM",
"REG_BI_SUBJECT"
],
"fastest_clock": "SEC_EXAMINATION_REQUEST IMMEDIATE"
},
{
"tier": "CRYPTO_TRADING_SAAS",
"compliance_flags": [
"CFTC_SWAP_DEALER"
],
"fastest_clock": "CFTC_SWAP_DATA_REPORTING same-day"
},
{
"tier": "ROBO_ADVISOR_PLATFORM",
"compliance_flags": [
"RIA_REGISTERED_ADVISER",
"REG_BI_SUBJECT"
],
"fastest_clock": "SEC_EXAMINATION_REQUEST IMMEDIATE \u2014 algorithm audit trail"
},
{
"tier": "ALTERNATIVE_INVESTMENT_SAAS",
"compliance_flags": [
"RIA_REGISTERED_ADVISER",
"SEC_FORM_PF_FILER"
],
"fastest_clock": "SEC_EXAMINATION_REQUEST IMMEDIATE"
},
{
"tier": "WEALTHTECH_STARTUP",
"compliance_flags": [
"RIA_REGISTERED_ADVISER"
],
"fastest_clock": "SEC_EXAMINATION_REQUEST IMMEDIATE"
}
]
}
Workflow 1 — Tier-Segmented Customer Onboarding Drip
Classifies new trials by tier and compliance flags. Sends Day 0 welcome with compliance-specific note, Day 3 feature email, Day 7 trial-end sequence.
The Day 0 note for BROKER_DEALER_SAAS includes the SEC Rule 17a-4(f) WORM storage analysis.
The Day 0 note for ROBO_ADVISOR_PLATFORM includes the Reg BI supervision boundary analysis.
{
"name": "WealthTech SaaS \u2014 Tier-Segmented Customer Onboarding Drip",
"nodes": [
{
"id": "1",
"name": "Webhook \u2014 trial_started",
"type": "n8n-nodes-base.webhook",
"parameters": {
"path": "wealthtech-trial-started",
"responseMode": "onReceived"
},
"position": [
0,
0
]
},
{
"id": "2",
"name": "Code \u2014 Tier + Flag Classifier",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst d = $input.first().json;\nconst plan = (d.plan || '').toLowerCase();\nconst userCount = d.user_count || 0;\nconst product = (d.product_type || '').toLowerCase();\nconst aum = d.aum_under_management || 0;\n\n// Tier classification\nlet tier = 'WEALTHTECH_STARTUP';\nif (product.includes('broker') || product.includes('bd')) tier = 'BROKER_DEALER_SAAS';\nelse if (product.includes('ria') || product.includes('adviser') || product.includes('advisor')) tier = 'RIA_SAAS_VENDOR';\nelse if (product.includes('crypto') || product.includes('digital_asset')) tier = 'CRYPTO_TRADING_SAAS';\nelse if (product.includes('robo') || product.includes('automated_advice')) tier = 'ROBO_ADVISOR_PLATFORM';\nelse if (product.includes('hedge') || product.includes('alt') || product.includes('private_equity')) tier = 'ALTERNATIVE_INVESTMENT_SAAS';\nelse if (userCount >= 1000 || aum >= 1000000000 || plan === 'enterprise') tier = 'ENTERPRISE_WEALTH_MGMT_PLATFORM';\n\n// Compliance flags\nconst flags = [];\nif (tier === 'BROKER_DEALER_SAAS') { flags.push('SEC_17A4_WORM_SUBJECT'); flags.push('FINRA_MEMBER_FIRM'); flags.push('REG_BI_SUBJECT'); }\nif (tier === 'RIA_SAAS_VENDOR') { flags.push('RIA_REGISTERED_ADVISER'); flags.push('REG_BI_SUBJECT'); }\nif (tier === 'ROBO_ADVISOR_PLATFORM') { flags.push('RIA_REGISTERED_ADVISER'); flags.push('REG_BI_SUBJECT'); }\nif (tier === 'CRYPTO_TRADING_SAAS') { flags.push('CFTC_SWAP_DEALER'); }\nif (tier === 'ALTERNATIVE_INVESTMENT_SAAS') { flags.push('RIA_REGISTERED_ADVISER'); flags.push('SEC_FORM_PF_FILER'); }\nif (tier === 'ENTERPRISE_WEALTH_MGMT_PLATFORM') { flags.push('SEC_17A4_WORM_SUBJECT'); flags.push('RIA_REGISTERED_ADVISER'); flags.push('FINRA_MEMBER_FIRM'); flags.push('REG_BI_SUBJECT'); }\nif (userCount >= 250 || tier === 'ENTERPRISE_WEALTH_MGMT_PLATFORM') flags.push('SOC2_REQUIRED');\n\n// Tier-specific Day 0 note\nconst day0Notes = {\n ENTERPRISE_WEALTH_MGMT_PLATFORM: 'SEC Rule 17a-4 WORM: cloud iPaaS routing order and trade records = electronic record storage outside your SEC-compliant system = examination finding risk. Reg BI: automation routing client recommendation data through cloud iPaaS = third-party data handler outside supervision boundary.',\n RIA_SAAS_VENDOR: 'SEC Advisers Act \u00a7204 recordkeeping: adviser client records in cloud iPaaS = third-party storage without explicit SEC books and records authority. Form ADV Part 2 disclosure obligation: cloud automation vendor relationship may require disclosure.',\n BROKER_DEALER_SAAS: 'SEC Rule 17a-4(f) WORM: electronically stored records must be non-rewriteable and non-erasable. Cloud iPaaS that processes trade records does not meet WORM standard. FINRA Rule 4370: BCP must account for third-party technology dependencies.',\n CRYPTO_TRADING_SAAS: 'CFTC Dodd-Frank \u00a7731: swap data reporting obligations require audit-grade recordkeeping. Cloud iPaaS routing swap confirmation data = reportable transaction records outside CFTC-compliant boundary.',\n ROBO_ADVISOR_PLATFORM: 'Reg BI \u00a717 CFR \u00a7240.15l-1: automated investment advice = recommendation subject to Best Interest obligation. Cloud iPaaS routing algorithm inputs and outputs = supervision gap outside your control boundary.',\n ALTERNATIVE_INVESTMENT_SAAS: 'SEC Form PF: quarterly systemic risk reporting for hedge funds and private equity. Fund data routing through cloud iPaaS = third-party data processor requiring Form ADV Part 2 disclosure + SEC examination exposure.',\n WEALTHTECH_STARTUP: 'SEC examination readiness: cloud iPaaS creates record production gaps. When the SEC requests records, you produce from your systems \u2014 not from your cloud automation vendor. Self-hosted n8n keeps all workflow data inside your perimeter.'\n};\n\nreturn [{json: {\n ...d,\n tier,\n flags,\n day0_compliance_note: day0Notes[tier] || day0Notes.WEALTHTECH_STARTUP\n}}];\n"
},
"position": [
250,
0
]
},
{
"id": "3",
"name": "Sheets \u2014 Log Trial",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"documentId": "YOUR_SHEET_ID",
"sheetName": "trials",
"dataMode": "autoMapInputData"
},
"position": [
500,
0
]
},
{
"id": "4",
"name": "Gmail \u2014 Day 0 Welcome",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{ $json.email }}",
"subject": "Welcome to {{ $json.product_name }} \u2014 your compliance automation setup guide",
"emailType": "html",
"message": "={{ '<p>Hi ' + $json.first_name + ',</p><p>You are now on the ' + $json.plan + ' trial.</p><p><strong>Compliance Note:</strong> ' + $json.day0_compliance_note + '</p><p>Your onboarding checklist is ready. Reply to this email with any questions.</p>' }}"
},
"position": [
750,
0
]
},
{
"id": "5",
"name": "Wait \u2014 3 days",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": 3,
"unit": "days"
},
"position": [
1000,
0
]
},
{
"id": "6",
"name": "Gmail \u2014 Day 3 Feature",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{ $json.email }}",
"subject": "The automation your {{ $json.tier.replace(/_/g, ' ').toLowerCase() }} customers ask about most",
"emailType": "html",
"message": "<p>Based on what similar vendors are automating: SEC/FINRA deadline tracking, API health monitoring for trading systems, and incident response pipelines. All run inside your infrastructure \u2014 no trade records or client data egressing to third-party servers.</p>"
},
"position": [
1250,
0
]
},
{
"id": "7",
"name": "Wait \u2014 4 days",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": 4,
"unit": "days"
},
"position": [
1500,
0
]
},
{
"id": "8",
"name": "Gmail \u2014 Day 7 Trial End",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{ $json.email }}",
"subject": "Your trial ends in 48 hours \u2014 3 things to do before then",
"emailType": "html",
"message": "<p>Export your workflow JSON, schedule a 15-min call with our team, and review the SEC Rule 17a-4 / Reg BI self-hosting checklist we prepared for your tier.</p>"
},
"position": [
1750,
0
]
}
],
"connections": {
"Webhook \u2014 trial_started": {
"main": [
[
{
"node": "Code \u2014 Tier + Flag Classifier",
"type": "main",
"index": 0
}
]
]
},
"Code \u2014 Tier + Flag Classifier": {
"main": [
[
{
"node": "Sheets \u2014 Log Trial",
"type": "main",
"index": 0
}
]
]
},
"Sheets \u2014 Log Trial": {
"main": [
[
{
"node": "Gmail \u2014 Day 0 Welcome",
"type": "main",
"index": 0
}
]
]
},
"Gmail \u2014 Day 0 Welcome": {
"main": [
[
{
"node": "Wait \u2014 3 days",
"type": "main",
"index": 0
}
]
]
},
"Wait \u2014 3 days": {
"main": [
[
{
"node": "Gmail \u2014 Day 3 Feature",
"type": "main",
"index": 0
}
]
]
},
"Gmail \u2014 Day 3 Feature": {
"main": [
[
{
"node": "Wait \u2014 4 days",
"type": "main",
"index": 0
}
]
]
},
"Wait \u2014 4 days": {
"main": [
[
{
"node": "Gmail \u2014 Day 7 Trial End",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 2 — SEC / FINRA / CFTC / OCC Compliance Deadline Tracker
Reads a Google Sheet of compliance deadlines daily. Classifies as OVERDUE / CRITICAL / URGENT / WARNING / NOTICE. Routes critical items to Slack #compliance-urgent and emails the owner.
12 deadline types covered:
| Deadline Type | Statute | Window |
|---|---|---|
| SEC_EXAMINATION_REQUEST | SEC Rule 17a-4 | IMMEDIATE — record production required |
| SEC_FORM_ADV_ANNUAL_UPDATE | Advisers Act §203 | Annual — within 90d of fiscal year end |
| SEC_FORM_PF_QUARTERLY | Dodd-Frank §404 | 45d after quarter end (15d for large advisers) |
| FINRA_4370_BCP_ANNUAL_REVIEW | FINRA Rule 4370 | Annual |
| FINRA_INQUIRY_RESPONSE | FINRA Rule 8210 | 10-15 business days standard |
| REG_BI_BEST_INTEREST_ANNUAL_REVIEW | 17 CFR §240.15l-1 | Annual |
| SEC_17A4_RECORDS_EXAMINATION | 17 CFR §240.17a-4(f) | IMMEDIATE upon exam |
| CFTC_SWAP_DATA_REPORTING | Dodd-Frank §731 | Same-day for new swaps |
| MSRB_RULE_G36_DISCLOSURE | MSRB Rule G-36 | Within 1 business day |
| OCC_SUPERVISORY_RESPONSE | OCC 12 CFR §30 | IMMEDIATE upon notice |
| SOC2_TYPE2_RENEWAL | — | Annual |
| ANNUAL_PENTEST | — | Annual |
{
"name": "WealthTech SaaS \u2014 SEC/FINRA/CFTC/OCC Compliance Deadline Tracker",
"nodes": [
{
"id": "1",
"name": "Schedule \u2014 Daily 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"position": [
0,
0
]
},
{
"id": "2",
"name": "Sheets \u2014 Read Deadlines",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"documentId": "YOUR_SHEET_ID",
"sheetName": "compliance_deadlines"
},
"position": [
250,
0
]
},
{
"id": "3",
"name": "Code \u2014 Urgency Classifier",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst today = new Date();\nconst urgent = [];\nfor (const row of $input.all()) {\n const d = row.json;\n const due = new Date(d.due_date);\n const days = Math.ceil((due - today) / 86400000);\n // 12 WealthTech deadline types\n const deadlineTypes = [\n 'SEC_EXAMINATION_REQUEST', // IMMEDIATE \u2014 record production required\n 'SEC_FORM_ADV_ANNUAL_UPDATE', // Annual \u2014 within 90d of fiscal year end\n 'SEC_FORM_PF_QUARTERLY', // 45d after quarter end (large advisers: 15d)\n 'FINRA_4370_BCP_ANNUAL_REVIEW', // Annual\n 'FINRA_INQUIRY_RESPONSE', // 10-15 business days standard\n 'REG_BI_BEST_INTEREST_ANNUAL_REVIEW', // Annual\n 'SEC_17A4_RECORDS_EXAMINATION', // IMMEDIATE upon exam\n 'CFTC_SWAP_DATA_REPORTING', // Same-day for new swaps\n 'MSRB_RULE_G36_DISCLOSURE', // Within 1 business day\n 'OCC_SUPERVISORY_RESPONSE', // IMMEDIATE upon notice\n 'SOC2_TYPE2_RENEWAL', // Annual\n 'ANNUAL_PENTEST' // Annual\n ];\n let urgency = 'UPCOMING';\n if (days < 0) urgency = 'OVERDUE';\n else if (days <= 3) urgency = 'CRITICAL';\n else if (days <= 7) urgency = 'URGENT';\n else if (days <= 14) urgency = 'WARNING';\n else if (days <= 30) urgency = 'NOTICE';\n if (days <= 30) urgent.push({...d, days_remaining: days, urgency});\n}\nreturn urgent.map(r => ({json: r}));\n"
},
"position": [
500,
0
]
},
{
"id": "4",
"name": "IF \u2014 Critical or Overdue",
"type": "n8n-nodes-base.if",
"parameters": {
"conditions": {
"options": {
"caseSensitive": false
},
"conditions": [
{
"leftValue": "={{ $json.urgency }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "CRITICAL"
},
{
"leftValue": "={{ $json.urgency }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "OVERDUE"
}
],
"combinator": "or"
}
},
"position": [
750,
0
]
},
{
"id": "5",
"name": "Slack \u2014 Critical Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#compliance-urgent",
"text": "={{ '\ud83d\udea8 ' + $json.urgency + ': ' + $json.deadline_type + ' \u2014 ' + $json.customer_name + ' \u2014 ' + $json.days_remaining + 'd remaining. Owner: ' + $json.owner }}"
},
"position": [
1000,
100
]
},
{
"id": "6",
"name": "Gmail \u2014 Owner Notice",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{ $json.owner_email }}",
"subject": "={{ '[' + $json.urgency + '] ' + $json.deadline_type + ' \u2014 ' + $json.days_remaining + ' days' }}",
"emailType": "html",
"message": "={{ '<p><strong>' + $json.deadline_type + '</strong></p><p>Customer: ' + $json.customer_name + '</p><p>Due: ' + $json.due_date + ' (' + $json.days_remaining + ' days remaining)</p><p>Action required: ' + $json.action_required + '</p>' }}"
},
"position": [
1000,
-100
]
},
{
"id": "7",
"name": "Sheets \u2014 Log",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"documentId": "YOUR_SHEET_ID",
"sheetName": "deadline_audit"
},
"position": [
1250,
0
]
}
],
"connections": {
"Schedule \u2014 Daily 8AM": {
"main": [
[
{
"node": "Sheets \u2014 Read Deadlines",
"type": "main",
"index": 0
}
]
]
},
"Sheets \u2014 Read Deadlines": {
"main": [
[
{
"node": "Code \u2014 Urgency Classifier",
"type": "main",
"index": 0
}
]
]
},
"Code \u2014 Urgency Classifier": {
"main": [
[
{
"node": "IF \u2014 Critical or Overdue",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 Critical or Overdue": {
"main": [
[
{
"node": "Slack \u2014 Critical Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Gmail \u2014 Owner Notice",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Critical Alert": {
"main": [
[
{
"node": "Sheets \u2014 Log",
"type": "main",
"index": 0
}
]
]
},
"Gmail \u2014 Owner Notice": {
"main": [
[
{
"node": "Sheets \u2014 Log",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 3 — Trading & Compliance API Health Monitor
Checks order management, portfolio management, trade reporting, compliance screening, and client portal APIs every 15 minutes.
Each endpoint is mapped to its compliance context:
-
order_management_api→ SEC Rule 17a-3/17a-4 — downtime = record creation gap = examination finding -
trade_reporting_api→ FINRA TRACE/MSRB RTRS — same-day reporting; downtime = late report -
compliance_screening_api→ OFAC SDN — trading without screening = regulatory violation
{
"name": "WealthTech SaaS \u2014 Trading & Compliance API Health Monitor",
"nodes": [
{
"id": "1",
"name": "Schedule \u2014 Every 15min",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "*/15 * * * *"
}
]
}
},
"position": [
0,
0
]
},
{
"id": "2",
"name": "Sheets \u2014 Endpoints",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"documentId": "YOUR_SHEET_ID",
"sheetName": "api_endpoints"
},
"position": [
250,
0
]
},
{
"id": "3",
"name": "HTTP \u2014 Check Endpoint",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"url": "={{ $json.endpoint_url }}",
"method": "GET",
"timeout": 10000,
"continueOnFail": true
},
"position": [
500,
0
]
},
{
"id": "4",
"name": "Code \u2014 Classify Health",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\n// WealthTech API endpoints with SEC/FINRA compliance context:\n// order_management_api = SEC 17a-3/17a-4 order records \u2014 downtime = record creation gap\n// portfolio_mgmt_api = Reg BI \u00a7240.15l-1 \u2014 best interest obligation continues during outage\n// trade_reporting_api = FINRA TRACE/MSRB RTRS \u2014 late reporting = examination finding\n// compliance_screening_api = OFAC SDN screening \u2014 trading without screening = regulatory violation\n// client_portal_api = SEC Advisers Act \u00a7204 \u2014 client record access obligation\nconst item = $input.first().json;\nconst statusCode = item.statusCode || 0;\nconst endpoint = item.endpoint_name || 'unknown';\nconst complianceNote = {\n order_management_api: 'SEC Rule 17a-3/17a-4 \u2014 order records must be created and retained. Downtime = record creation gap = examination finding.',\n portfolio_mgmt_api: 'Reg BI \u00a7240.15l-1 \u2014 Best Interest obligation continues during API downtime. Recommendation pipeline break creates supervision gap.',\n trade_reporting_api: 'FINRA TRACE/MSRB RTRS \u2014 same-day trade reporting required. Downtime = late reporting = examination finding.',\n compliance_screening_api: 'OFAC SDN / FINRA OFAC \u2014 screening must occur before trade execution. API downtime = unsupported trading without sanctions screening.',\n client_portal_api: 'SEC Advisers Act \u00a7204 \u2014 client access to account statements. Downtime creates access rights gap.'\n}[endpoint] || 'Financial services compliance dependency';\nconst healthy = statusCode >= 200 && statusCode < 300;\nreturn [{json: {endpoint, statusCode, healthy, complianceNote, checked_at: new Date().toISOString()}}];\n"
},
"position": [
750,
0
]
},
{
"id": "5",
"name": "IF \u2014 Down",
"type": "n8n-nodes-base.if",
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.healthy }}",
"operator": {
"type": "boolean",
"operation": "false"
}
}
]
}
},
"position": [
1000,
0
]
},
{
"id": "6",
"name": "Slack \u2014 API Down Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#platform-ops",
"text": "={{ '\ud83d\udd34 API DOWN: ' + $json.endpoint + ' (HTTP ' + $json.statusCode + ') \u2014 Compliance note: ' + $json.complianceNote }}"
},
"position": [
1250,
100
]
},
{
"id": "7",
"name": "Sheets \u2014 Health Log",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"documentId": "YOUR_SHEET_ID",
"sheetName": "api_health_log"
},
"position": [
1250,
-100
]
}
],
"connections": {
"Schedule \u2014 Every 15min": {
"main": [
[
{
"node": "Sheets \u2014 Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Sheets \u2014 Endpoints": {
"main": [
[
{
"node": "HTTP \u2014 Check Endpoint",
"type": "main",
"index": 0
}
]
]
},
"HTTP \u2014 Check Endpoint": {
"main": [
[
{
"node": "Code \u2014 Classify Health",
"type": "main",
"index": 0
}
]
]
},
"Code \u2014 Classify Health": {
"main": [
[
{
"node": "IF \u2014 Down",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 Down": {
"main": [
[
{
"node": "Slack \u2014 API Down Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Sheets \u2014 Health Log",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 4 — Incident Pipeline
Webhook-triggered. Classifies 8 incident types. Routes to Slack and emails compliance lead.
SEC_EXAMINATION_REQUEST is the fastest clock — immediate record production required.
Cloud iPaaS routing trade records = records outside your direct-access perimeter = production delay = examination finding.
| Incident Type | Clock | Statute |
|---|---|---|
| SEC_EXAMINATION_REQUEST | IMMEDIATE | SEC Rule 17a-4 |
| FINRA_INVESTIGATION_NOTICE | 10-15 business days | FINRA Rule 8210 |
| REG_BI_SUITABILITY_COMPLAINT | IMMEDIATE | 17 CFR §240.15l-1 |
| SEC_17A4_RECORD_PRODUCTION | IMMEDIATE upon request | 17 CFR §240.17a-4(f) |
| CFTC_ENFORCEMENT_ACTION | 30d to respond | Dodd-Frank §731 |
| DATA_BREACH_INVESTOR_PII | 72h + SEC Reg S-P | 17 CFR §248 |
| SYSTEM_OUTAGE_TRADING | SLA + FINRA 4370 BCP | FINRA Rule 4370 |
| OCC_SUPERVISORY_AGREEMENT | IMMEDIATE | OCC 12 CFR §30 |
{
"name": "WealthTech SaaS \u2014 Incident Pipeline (SEC / FINRA / Reg BI / CFTC)",
"nodes": [
{
"id": "1",
"name": "Webhook \u2014 Incident",
"type": "n8n-nodes-base.webhook",
"parameters": {
"path": "wealthtech-incident",
"responseMode": "onReceived"
},
"position": [
0,
0
]
},
{
"id": "2",
"name": "Code \u2014 Classify Incident",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst d = $input.first().json;\nconst type = d.incident_type || 'UNKNOWN';\n// 8 WealthTech incident types with response clocks:\nconst clocks = {\n SEC_EXAMINATION_REQUEST: {\n clock: 'IMMEDIATE',\n note: 'SEC examination request requires immediate record production. Cloud iPaaS routing trade records = records outside your direct-access perimeter = production delay = examination finding. Self-hosted n8n = records stay in your infrastructure.',\n actions: ['Preserve all workflow execution logs', 'Notify CCO and general counsel', 'Identify all record types requested', 'Engage securities counsel', 'Prepare document production from your systems']\n },\n FINRA_INVESTIGATION_NOTICE: {\n clock: '10-15 business days standard',\n note: 'FINRA Rule 8210 \u2014 information request. FINRA can demand records from member firms and associated persons. Third-party automation vendor records may require separate subpoena if hosted externally.',\n actions: ['Notify CCO immediately', 'Identify all records within FINRA scope', 'Engage outside counsel', 'Respond within stated deadline', 'Document production completeness']\n },\n REG_BI_SUITABILITY_COMPLAINT: {\n clock: 'IMMEDIATE',\n note: 'Reg BI \u00a7240.15l-1 \u2014 Best Interest standard. Customer complaint triggers supervision review. Recommendation data routing through cloud iPaaS = data handler outside supervision boundary = gap in oversight obligation.',\n actions: ['Pull recommendation audit trail', 'Review algorithm decision log', 'Notify compliance officer', 'Respond to customer within 3 business days', 'Document Best Interest analysis']\n },\n SEC_17A4_RECORD_PRODUCTION: {\n clock: 'IMMEDIATE upon request',\n note: 'SEC Rule 17a-4(f) \u2014 electronic records must be immediately accessible for 2 years, then accessible for 6 years. Cloud iPaaS trade data = records outside WORM-compliant storage = production failure risk.',\n actions: ['Identify all 17a-4 record categories', 'Produce immediately accessible records (2yr)', 'Confirm WORM storage compliance', 'Notify CCO', 'Engage securities counsel']\n },\n CFTC_ENFORCEMENT_ACTION: {\n clock: '30d to respond',\n note: 'CFTC Dodd-Frank \u00a7731 swap dealer reporting. Enforcement action for failure to report swap data same-day. Cloud iPaaS routing swap confirmations = reportable data outside direct CFTC submission control.',\n actions: ['Preserve all swap confirmation records', 'Audit CFTC SDR submission completeness', 'Engage CFTC-specialized counsel', 'Prepare response within 30d', 'Document remediation plan']\n },\n DATA_BREACH_INVESTOR_PII: {\n clock: '72h state law + SEC notification',\n note: 'State breach notification + SEC Reg S-P (17 CFR \u00a7248) \u2014 safeguards rule. Customer financial data breach requires state notification and SEC examination disclosure.',\n actions: ['Engage breach counsel', 'Notify affected customers', 'File state notification within 72h', 'Prepare SEC examination response', 'Assess Reg S-P safeguards rule compliance']\n },\n SYSTEM_OUTAGE_TRADING: {\n clock: 'SLA + regulatory reporting',\n note: 'Platform SLA. FINRA Rule 4370 BCP: member firms must maintain business continuity. Extended outage may trigger FINRA notification obligation.',\n actions: ['Activate BCP', 'Post status page update', 'Notify FINRA if outage exceeds BCP threshold', 'Track SEC 17a-4 record creation gaps', 'Document restoration timeline']\n },\n OCC_SUPERVISORY_AGREEMENT: {\n clock: 'IMMEDIATE',\n note: 'OCC safety and soundness \u2014 supervisory agreement or consent order. Technology dependencies including third-party automation vendors may be in scope for OCC examination.',\n actions: ['Notify board and senior management', 'Engage OCC-specialized counsel', 'Document all third-party technology dependencies', 'Prepare corrective action plan', 'Identify cloud automation as TPSP per OCC guidance']\n }\n};\nconst info = clocks[type] || clocks.SYSTEM_OUTAGE_TRADING;\nreturn [{json: {\n ...d,\n incident_type: type,\n response_clock: info.clock,\n compliance_note: info.note,\n required_actions: info.actions,\n logged_at: new Date().toISOString()\n}}];\n"
},
"position": [
250,
0
]
},
{
"id": "3",
"name": "Sheets \u2014 Log Incident",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"documentId": "YOUR_SHEET_ID",
"sheetName": "incident_log"
},
"position": [
500,
0
]
},
{
"id": "4",
"name": "Slack \u2014 Incident Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#compliance-incident",
"text": "={{ '\ud83d\udea8 WealthTech Incident: ' + $json.incident_type + ' | Clock: ' + $json.response_clock + ' | ' + $json.compliance_note }}"
},
"position": [
750,
0
]
},
{
"id": "5",
"name": "Gmail \u2014 Compliance Lead",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "compliance@yourcompany.com",
"subject": "={{ '[INCIDENT] ' + $json.incident_type + ' \u2014 ' + $json.response_clock + ' clock' }}",
"emailType": "html",
"message": "={{ '<p><strong>Incident Type:</strong> ' + $json.incident_type + '</p><p><strong>Clock:</strong> ' + $json.response_clock + '</p><p><strong>Note:</strong> ' + $json.compliance_note + '</p><p><strong>Actions:</strong> ' + $json.required_actions.join(', ') + '</p>' }}"
},
"position": [
1000,
0
]
}
],
"connections": {
"Webhook \u2014 Incident": {
"main": [
[
{
"node": "Code \u2014 Classify Incident",
"type": "main",
"index": 0
}
]
]
},
"Code \u2014 Classify Incident": {
"main": [
[
{
"node": "Sheets \u2014 Log Incident",
"type": "main",
"index": 0
}
]
]
},
"Sheets \u2014 Log Incident": {
"main": [
[
{
"node": "Slack \u2014 Incident Alert",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Incident Alert": {
"main": [
[
{
"node": "Gmail \u2014 Compliance Lead",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 5 — Weekly WealthTech KPI Dashboard
Monday 8AM. Queries Postgres for account counts by tier, MRR, compliance flag distribution, and open incidents. Sends HTML report to CEO and one-liner to Slack.
{
"name": "WealthTech SaaS \u2014 Weekly KPI Dashboard",
"nodes": [
{
"id": "1",
"name": "Schedule \u2014 Monday 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
},
"position": [
0,
0
]
},
{
"id": "2",
"name": "Postgres \u2014 KPI Query",
"type": "n8n-nodes-base.postgres",
"parameters": {
"operation": "executeQuery",
"query": "\nSELECT\n COUNT(DISTINCT account_id) FILTER (WHERE tier = 'ENTERPRISE_WEALTH_MGMT_PLATFORM') AS enterprise_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE tier = 'RIA_SAAS_VENDOR') AS ria_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE tier = 'BROKER_DEALER_SAAS') AS broker_dealer_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE tier = 'CRYPTO_TRADING_SAAS') AS crypto_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE tier = 'ROBO_ADVISOR_PLATFORM') AS robo_advisor_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE status = 'trial') AS active_trials,\n COUNT(DISTINCT account_id) FILTER (WHERE status = 'active') AS paying_accounts,\n SUM(mrr) AS total_mrr,\n AVG(mrr) AS avg_mrr,\n COUNT(DISTINCT account_id) FILTER (WHERE flags @> ARRAY['SEC_17A4_WORM_SUBJECT']) AS sec_17a4_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE flags @> ARRAY['REG_BI_SUBJECT']) AS reg_bi_accounts,\n COUNT(DISTINCT account_id) FILTER (WHERE flags @> ARRAY['FINRA_MEMBER_FIRM']) AS finra_member_accounts,\n COUNT(*) FILTER (WHERE event_type = 'SEC_EXAMINATION_REQUEST' AND created_at >= NOW() - INTERVAL '7 days') AS sec_exam_requests_7d,\n COUNT(*) FILTER (WHERE event_type = 'FINRA_INVESTIGATION_NOTICE' AND created_at >= NOW() - INTERVAL '7 days') AS finra_inquiries_7d,\n COUNT(*) FILTER (WHERE event_type = 'REG_BI_SUITABILITY_COMPLAINT' AND created_at >= NOW() - INTERVAL '7 days') AS reg_bi_complaints_7d\nFROM accounts LEFT JOIN events USING (account_id)\n"
},
"position": [
250,
0
]
},
{
"id": "3",
"name": "Code \u2014 Format Report",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst d = $input.first().json;\nconst html = `<h2>FlowKit WealthTech SaaS \u2014 Weekly KPI</h2>\n<table border='1' cellpadding='6'>\n<tr><th>Metric</th><th>Value</th></tr>\n<tr><td>Enterprise Accounts</td><td>${d.enterprise_accounts}</td></tr>\n<tr><td>RIA SaaS Accounts</td><td>${d.ria_accounts}</td></tr>\n<tr><td>Broker-Dealer SaaS Accounts</td><td>${d.broker_dealer_accounts}</td></tr>\n<tr><td>Crypto Trading SaaS Accounts</td><td>${d.crypto_accounts}</td></tr>\n<tr><td>Robo-Advisor Accounts</td><td>${d.robo_advisor_accounts}</td></tr>\n<tr><td>Active Trials</td><td>${d.active_trials}</td></tr>\n<tr><td>Paying Accounts</td><td>${d.paying_accounts}</td></tr>\n<tr><td>Total MRR</td><td>$${Number(d.total_mrr||0).toLocaleString()}</td></tr>\n<tr><td>Avg MRR</td><td>$${Number(d.avg_mrr||0).toFixed(0)}</td></tr>\n<tr><th colspan='2'>Compliance Coverage</th></tr>\n<tr><td>SEC Rule 17a-4 Subject Accounts</td><td>${d.sec_17a4_accounts}</td></tr>\n<tr><td>Reg BI Subject Accounts</td><td>${d.reg_bi_accounts}</td></tr>\n<tr><td>FINRA Member Firm Accounts</td><td>${d.finra_member_accounts}</td></tr>\n<tr><th colspan='2'>Incident Activity (7d)</th></tr>\n<tr><td>SEC Examination Requests</td><td>${d.sec_exam_requests_7d}</td></tr>\n<tr><td>FINRA Inquiries</td><td>${d.finra_inquiries_7d}</td></tr>\n<tr><td>Reg BI Complaints</td><td>${d.reg_bi_complaints_7d}</td></tr>\n</table>`;\nreturn [{json: {...d, html_report: html}}];\n"
},
"position": [
500,
0
]
},
{
"id": "4",
"name": "Gmail \u2014 KPI Report",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "ceo@yourcompany.com",
"subject": "WealthTech SaaS Weekly KPI \u2014 {{ $now.format('YYYY-MM-DD') }}",
"emailType": "html",
"message": "={{ $json.html_report }}"
},
"position": [
750,
0
]
},
{
"id": "5",
"name": "Slack \u2014 One-liner",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#go-to-market",
"text": "={{ 'Weekly KPI: ' + $json.paying_accounts + ' paying / ' + $json.active_trials + ' trials / MRR $' + Number($json.total_mrr||0).toLocaleString() + ' | SEC17a4: ' + $json.sec_17a4_accounts + ' accts | RegBI: ' + $json.reg_bi_accounts + ' | FINRA: ' + $json.finra_member_accounts + ' | Incidents 7d: SEC=' + $json.sec_exam_requests_7d + ' FINRA=' + $json.finra_inquiries_7d + ' RegBI=' + $json.reg_bi_complaints_7d }}"
},
"position": [
1000,
0
]
}
],
"connections": {
"Schedule \u2014 Monday 8AM": {
"main": [
[
{
"node": "Postgres \u2014 KPI Query",
"type": "main",
"index": 0
}
]
]
},
"Postgres \u2014 KPI Query": {
"main": [
[
{
"node": "Code \u2014 Format Report",
"type": "main",
"index": 0
}
]
]
},
"Code \u2014 Format Report": {
"main": [
[
{
"node": "Gmail \u2014 KPI Report",
"type": "main",
"index": 0
}
]
]
},
"Gmail \u2014 KPI Report": {
"main": [
[
{
"node": "Slack \u2014 One-liner",
"type": "main",
"index": 0
}
]
]
}
}
}
Why Self-Hosted n8n Wins the WealthTech Procurement Conversation
| Factor | Cloud iPaaS (Zapier/Make) | Self-Hosted n8n |
|---|---|---|
| SEC Rule 17a-4 WORM | iPaaS logs contain trade records outside WORM-compliant storage | Trade workflow data stays inside your WORM-compliant perimeter |
| SEC examination production | Records in cloud vendor systems = production detour or delay | Immediate production from your systems |
| Reg BI supervision | Algorithm I/O routing through cloud iPaaS = supervision gap | Recommendation pipeline runs inside supervision boundary |
| FINRA Rule 4370 BCP | Cloud iPaaS is TPSP requiring BCP dependency documentation | Self-hosted n8n is part of your own BCP |
| CFTC swap reporting | Swap data routing through cloud iPaaS = reportable data outside direct CFTC submission control | Swap workflow data inside your audit boundary |
| Form ADV disclosure | Cloud automation vendor = third-party relationship requiring ADV Part 2 disclosure | Internal tool, no additional disclosure required |
| Cost at scale | $299+/mo growing with task volume | One Docker container, unlimited workflows |
SEC Rule 17a-4 is a binary gate for broker-dealer and RIA procurement.
Cloud iPaaS fails the WORM standard by architecture. Self-hosted n8n passes it by architecture.
If you're building WealthTech SaaS and your automation stack routes trade records or client recommendation data through cloud iPaaS,
you're one SEC examination request away from a record production gap.
These workflows run on self-hosted n8n. Download the JSON, import, configure your Sheets IDs and API keys.
The complete FlowKit n8n Automation Template library (15 templates) is at stripeai.gumroad.com.
Top comments (0)