If you sell software to airlines, online travel agencies, hotel operators, or vacation rental platforms — your product sits inside one of the most enforcement-active consumer protection environments in US and EU technology.
The DOT's 2024 Final Rule on Airline Refunds (14 CFR Part 399) now requires automatic refunds — no customer request needed — within 7 business days for credit card purchases and 20 calendar days for other forms of payment, following cancellation or significant itinerary change. The enforcement target is not just the airline. It is the booking platform that processed the transaction, the OTA that confirmed the itinerary, and the tech vendor whose automation sits between the cancellation event and the refund trigger.
Here is the architecture problem: if your booking or payment automation runs through Zapier, Make, or any cloud iPaaS, the DOT's investigation reaches your vendor's logs before it reaches your legal team. The DOT subpoenas cloud automation platforms as third-party record holders. By the time your legal counsel files a protective order motion, Zapier has already responded.
Who This Article Is For
This is for engineering and ops teams at TravelTech and HospitalityTech SaaS vendors — the companies building the software that airlines, hotels, OTAs, and vacation rental operators run on. If you build:
- Online Travel Agency (OTA) platforms — booking engines, itinerary management, fare search
- Hotel Property Management Systems (PMS) — check-in, checkout, payment, guest data
- Airline technology — distribution, revenue management, NDC APIs, passenger services
- Vacation rental SaaS — Airbnb/VRBO-style platform technology
- Restaurant technology — POS, reservations, kitchen management, delivery integration
- Travel payment SaaS — loyalty, multi-currency, travel fintech
...then these workflows are built for your stack.
Customer Tiers
Seven customer tiers: ONLINE_TRAVEL_AGENCY_PLATFORM / HOTEL_PMS_SAAS_VENDOR / AIRLINE_TECH_SAAS_VENDOR / VACATION_RENTAL_SAAS_PLATFORM / RESTAURANT_TECH_SAAS / TRAVEL_PAYMENT_SAAS_VENDOR / TRAVELTECH_STARTUP
Seven compliance flags: DOT_14_CFR_399_SUBJECT / ADA_TITLE_III_WEB_ACCESSIBLE / PSD2_SCA_EU_UK_REQUIRED / PCI_DSS_LEVEL_1_MERCHANT / GDPR_TRAVEL_DATA_PROCESSOR / CCPA_COVERED_ENTITY / SOC2_REQUIRED
The 12 Deadline Types
DOT_REFUND_CREDIT_CARD_7_BUSINESS_DAYSDOT_REFUND_OTHER_PAYMENT_20_CALENDAR_DAYSDOT_BAGGAGE_FEE_DISCLOSURE_ANNUALADA_TITLE_III_WEB_ACCESSIBILITY_AUDITPSD2_SCA_EBA_RTS_COMPLIANCE_ANNUALPCI_DSS_ANNUAL_QSA_ASSESSMENTPCI_DSS_QUARTERLY_ASV_SCANGDPR_ART28_DPA_RENEWAL_ANNUALGDPR_ART17_ERASURE_REQUEST_30DCCPA_CONSUMER_REQUEST_RESPONSE_45DILLINOIS_BIPA_BIOMETRIC_CONSENT_3YRSOC2_TYPE2_ANNUAL_RENEWAL
The 8 Incident Types — Fastest Clock First
| Incident | Severity | Clock | Authority |
|---|---|---|---|
PSD2_MAJOR_PAYMENT_INCIDENT |
CRITICAL | IMMEDIATE (4 hours — initial EBA notification) | EBA / national competent authority PSD2 Art.96 |
ADA_TITLE_III_DOJ_INVESTIGATION |
CRITICAL | IMMEDIATE — pattern discrimination | DOJ Civil Rights Division / private plaintiffs 42 USC §12188 |
PCI_DSS_CARDHOLDER_DATA_BREACH |
CRITICAL | IMMEDIATE to card networks + forensic investigation | Visa/MC/Amex/Discover forensic investigator (PFI) |
DOT_SYSTEMATIC_REFUND_FAILURE |
HIGH | 7 business days per refund + DOT enforcement IMMEDIATE | DOT Office of Aviation Consumer Protection 14 CFR §399.80 |
GDPR_DATA_BREACH_TRAVELER_PII |
HIGH | 72 hours Art.33 | Lead supervisory authority (DPA) GDPR Art.55 |
ILLINOIS_BIPA_BIOMETRIC_VIOLATION |
HIGH | IMMEDIATE — no cure period | Illinois AG + private right of action — $1,000-$5,000/person 740 ILCS 14/20 |
CCPA_STATUTORY_VIOLATION |
MEDIUM | 30-day cure period §1798.155 | California AG / CA Privacy Protection Agency |
DOT_ACCESSIBILITY_COMPLAINT_ACAA |
MEDIUM | 30 days §382.65 | DOT Office of Aviation Consumer Protection — Air Carrier Access Act |
PSD2_MAJOR_PAYMENT_INCIDENTis the fastest clock — IMMEDIATE (4 hours). PSD2 Art.96 requires notification to your national competent authority within 4 hours of classifying an operational or security incident as 'major.' If your payment automation runs through a cloud iPaaS, the incident classification latency of that vendor is part of your 4-hour window.
5 Workflows — Full Import-Ready JSON
All five workflows are import-ready. In n8n: Settings → Import workflow → paste JSON.
Workflow 1: Tier-Segmented Customer Onboarding Drip
Classifies each new customer by TravelTech tier and compliance flags. Day 0 welcome email carries a tier-specific compliance architecture note: OTA platforms get the DOT refund subpoena boundary briefing; Hotel PMS vendors get PCI DSS log integrity and GDPR Art.28 processor notes; Airline tech vendors get the DOT 7-business-day refund clock; Restaurant tech vendors get the Illinois BIPA fingerprint-POS note. Includes a 3-day check-in with tier-specific FAQs.
{
"name": "TravelTech SaaS \u2014 Tier-Segmented Customer Onboarding Drip",
"nodes": [
{
"id": "1",
"name": "Trigger: New Customer Signup",
"type": "n8n-nodes-base.sheetsTrigger",
"position": [
240,
300
],
"parameters": {
"operation": "appendOrUpdate",
"sheetId": "={{ $env.ONBOARDING_SHEET_ID }}",
"range": "A:Z"
}
},
{
"id": "2",
"name": "Code: Classify Tier + Flags",
"type": "n8n-nodes-base.code",
"position": [
460,
300
],
"parameters": {
"jsCode": "const r = $input.first().json;\nconst tier = (r.tier || '').toUpperCase();\nconst flags = (r.flags || '').toUpperCase().split(',').map(f => f.trim());\n\nconst tierNotes = {\n ONLINE_TRAVEL_AGENCY_PLATFORM: 'Your booking confirmation, refund processing, and fare display automation are subject to DOT 14 CFR Part 399. When DOT opens a refund enforcement investigation, they subpoena booking platform logs and automation system records \u2014 not just your customer service queue. If those records live in Zapier cloud, DOT reaches them before your legal team.',\n HOTEL_PMS_SAAS_VENDOR: 'Your PMS handles check-in/checkout automation, payment processing, and guest data. Under GDPR Art.28, every cloud automation node processing EU guest data must be covered by a Data Processing Agreement. PCI DSS Requirement 10 mandates complete audit logs of all payment system access \u2014 cloud iPaaS log aggregation falls outside your QSA assessment boundary.',\n AIRLINE_TECH_SAAS_VENDOR: 'DOT 14 CFR \u00a7399.80 requires credit card refunds within 7 business days of a cancellation or significant change. Your distribution and booking automation is the clock \u2014 the refund obligation attaches at the moment your system receives the cancellation event, not when a human processes it. Cloud iPaaS delay in that pipeline = DOT enforcement window opens.',\n VACATION_RENTAL_SAAS_PLATFORM: 'GDPR Art.17 right to erasure applies to all guest data your platform processes \u2014 including booking histories stored in cloud automation logs. Zapier/Make retain task execution data; that retention may conflict with your Art.17 deletion obligations. Self-hosted n8n gives you complete control over retention and deletion.',\n RESTAURANT_TECH_SAAS: 'Illinois BIPA (740 ILCS 14) requires written consent before collecting biometric data, including fingerprint-based POS login data. No cure period \u2014 a single violation triggers $1,000\u2013$5,000 per-person liability. If your platform automates fingerprint/face scan enrollment via cloud integration, BIPA applies and there is no grace period.',\n TRAVEL_PAYMENT_SAAS_VENDOR: 'PSD2 Art.96 requires notification to your national competent authority within 4 hours of classifying a major operational or security incident. If your payment processing automation runs through cloud iPaaS, that incident classification pipeline may not meet the Art.96 timeliness requirement \u2014 the 4-hour clock does not pause for vendor response times.',\n TRAVELTECH_STARTUP: 'Welcome to FlowKit. As you grow toward enterprise hotel and airline customers, they will ask you about your DOT compliance architecture, GDPR processor posture, and PCI DSS scope documentation before procurement. These workflows give you a compliance-ready automation stack before your first enterprise RFP.'\n};\n\nconst hasDot = flags.includes('DOT_14_CFR_399_SUBJECT');\nconst hasAda = flags.includes('ADA_TITLE_III_WEB_ACCESSIBLE');\nconst hasPsd2 = flags.includes('PSD2_SCA_EU_UK_REQUIRED');\nconst hasPci = flags.includes('PCI_DSS_LEVEL_1_MERCHANT');\n\nreturn [{\n json: {\n ...r,\n tier,\n flags,\n tier_note: tierNotes[tier] || tierNotes['TRAVELTECH_STARTUP'],\n has_dot: hasDot,\n has_ada: hasAda,\n has_psd2: hasPsd2,\n has_pci: hasPci,\n onboarding_subject: 'Welcome to FlowKit \u2014 Your TravelTech Automation Is Live',\n cta_url: 'https://stripeai.gumroad.com'\n }\n}];"
}
},
{
"id": "3",
"name": "Gmail: Day 0 Welcome",
"type": "n8n-nodes-base.gmail",
"position": [
680,
300
],
"parameters": {
"operation": "send",
"toList": "={{ $json.email }}",
"subject": "={{ $json.onboarding_subject }}",
"message": "Hi {{ $json.name }},\n\nWelcome to FlowKit.\n\nImportant for your compliance architecture:\n{{ $json.tier_note }}\n\nYour automation workflows are ready. Browse templates: {{ $json.cta_url }}\n\nAlex Kane\nFlowKit"
}
},
{
"id": "4",
"name": "Slack: CSM Notification",
"type": "n8n-nodes-base.slack",
"position": [
680,
440
],
"parameters": {
"channel": "#cs-new-customers",
"text": "New {{ $json.tier }} customer: {{ $json.name }} ({{ $json.email }}). DOT: {{ $json.has_dot }}, ADA: {{ $json.has_ada }}, PSD2: {{ $json.has_psd2 }}, PCI: {{ $json.has_pci }}."
}
},
{
"id": "5",
"name": "Wait: 3 days",
"type": "n8n-nodes-base.wait",
"position": [
900,
300
],
"parameters": {
"amount": 3,
"unit": "days"
}
},
{
"id": "6",
"name": "Gmail: Day 3 Check-in",
"type": "n8n-nodes-base.gmail",
"position": [
1120,
300
],
"parameters": {
"operation": "send",
"toList": "={{ $json.email }}",
"subject": "Your TravelTech automation check-in",
"message": "Hi {{ $json.name }},\n\nHow are the workflows running? Common questions at day 3:\n- {{ $json.has_dot ? 'DOT refund pipeline setup (7 biz day credit card clock)' : 'Compliance deadline tracker configuration' }}\n- {{ $json.has_psd2 ? 'PSD2 SCA incident notification (Art.96 4-hour clock)' : 'GDPR erasure request automation' }}\n- {{ $json.has_pci ? 'PCI DSS log integrity workflow' : 'SOC2 evidence collection automation' }}\n\nReply to this email \u2014 happy to help.\n\nAlex Kane\nFlowKit"
}
},
{
"id": "7",
"name": "Sheets: Log Onboarding",
"type": "n8n-nodes-base.googleSheets",
"position": [
1340,
300
],
"parameters": {
"operation": "append",
"sheetId": "={{ $env.ONBOARDING_LOG_SHEET_ID }}",
"columns": {
"mappingMode": "defineBelow",
"value": {
"customer_name": "={{ $json.name }}",
"tier": "={{ $json.tier }}",
"day0_sent": "={{ new Date().toISOString() }}",
"dot_flag": "={{ $json.has_dot }}",
"ada_flag": "={{ $json.has_ada }}",
"psd2_flag": "={{ $json.has_psd2 }}",
"pci_flag": "={{ $json.has_pci }}"
}
}
}
}
],
"connections": {
"Trigger: New Customer Signup": {
"main": [
[
{
"node": "Code: Classify Tier + Flags",
"type": "main",
"index": 0
}
]
]
},
"Code: Classify Tier + Flags": {
"main": [
[
{
"node": "Gmail: Day 0 Welcome",
"type": "main",
"index": 0
},
{
"node": "Slack: CSM Notification",
"type": "main",
"index": 0
}
]
]
},
"Gmail: Day 0 Welcome": {
"main": [
[
{
"node": "Wait: 3 days",
"type": "main",
"index": 0
}
]
]
},
"Wait: 3 days": {
"main": [
[
{
"node": "Gmail: Day 3 Check-in",
"type": "main",
"index": 0
}
]
]
},
"Gmail: Day 3 Check-in": {
"main": [
[
{
"node": "Sheets: Log Onboarding",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 2: DOT/ADA/PCI/GDPR Compliance Deadline Tracker
Runs daily at 08:00 UTC. Reads your compliance deadlines sheet, classifies urgency as OVERDUE / CRITICAL (<7d) / URGENT (<14d) / WARNING (<30d) / NOTICE (<60d). Critical PSD2, ADA Title III, and PCI breach incidents fire immediately without waiting for calendar-based logic. Routes critical alerts to #travel-compliance-critical + Gmail to compliance owner; non-critical to #travel-compliance-watch.
{
"name": "TravelTech SaaS \u2014 DOT/ADA/PCI/GDPR Compliance Deadline Tracker",
"nodes": [
{
"id": "1",
"name": "Schedule: Daily 08:00 UTC",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
240,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
}
},
{
"id": "2",
"name": "Sheets: Read Compliance Deadlines",
"type": "n8n-nodes-base.googleSheets",
"position": [
460,
300
],
"parameters": {
"operation": "readRows",
"sheetId": "={{ $env.TRAVEL_DEADLINES_SHEET_ID }}",
"range": "A:F"
}
},
{
"id": "3",
"name": "Code: Classify Urgency",
"type": "n8n-nodes-base.code",
"position": [
680,
300
],
"parameters": {
"jsCode": "const rows = $input.all();\nconst now = new Date();\nconst alerts = [];\n\nfor (const row of rows) {\n const d = row.json;\n const deadline = new Date(d.deadline_date);\n const daysLeft = Math.ceil((deadline - now) / 86400000);\n const t = (d.deadline_type || '').toUpperCase();\n\n // DOT refund clocks: treat as rolling per-event (not calendar deadline)\n // Track in sheet as next_batch_refund_due to catch systematic failures\n let urgency = null;\n if (t === 'PSD2_MAJOR_PAYMENT_INCIDENT' || t === 'ADA_TITLE_III_DOJ_INVESTIGATION' || t === 'PCI_DSS_CARDHOLDER_DATA_BREACH') {\n urgency = 'CRITICAL';\n } else if (daysLeft < 0) {\n urgency = 'OVERDUE';\n } else if (daysLeft <= 7) {\n urgency = 'CRITICAL';\n } else if (daysLeft <= 14) {\n urgency = 'URGENT';\n } else if (daysLeft <= 30) {\n urgency = 'WARNING';\n } else if (daysLeft <= 60) {\n urgency = 'NOTICE';\n }\n\n if (urgency) {\n alerts.push({...d, days_left: daysLeft, urgency});\n }\n}\n\nreturn alerts.map(a => ({json: a}));"
}
},
{
"id": "4",
"name": "IF: Critical or Overdue",
"type": "n8n-nodes-base.if",
"position": [
900,
300
],
"parameters": {
"conditions": {
"options": {
"combineOperation": "any"
},
"conditions": [
{
"leftValue": "={{ $json.urgency }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "CRITICAL"
},
{
"leftValue": "={{ $json.urgency }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "OVERDUE"
}
]
}
}
},
{
"id": "5",
"name": "Slack: #travel-compliance-critical",
"type": "n8n-nodes-base.slack",
"position": [
1120,
200
],
"parameters": {
"channel": "#travel-compliance-critical",
"text": "[{{ $json.urgency }}] {{ $json.deadline_type }} \u2014 {{ $json.days_left }} days. Customer: {{ $json.customer_name }}. Authority: {{ $json.authority }}."
}
},
{
"id": "6",
"name": "Gmail: Compliance Owner Alert",
"type": "n8n-nodes-base.gmail",
"position": [
1120,
340
],
"parameters": {
"operation": "send",
"toList": "={{ $json.owner_email }}",
"subject": "[{{ $json.urgency }}] TravelTech Compliance Deadline: {{ $json.deadline_type }}",
"message": "Deadline: {{ $json.deadline_type }}\nDays remaining: {{ $json.days_left }}\nAuthority: {{ $json.authority }}\nCustomer: {{ $json.customer_name }}\nUrgency: {{ $json.urgency }}\n\nAction required immediately."
}
},
{
"id": "7",
"name": "Slack: #travel-compliance-watch",
"type": "n8n-nodes-base.slack",
"position": [
1120,
480
],
"parameters": {
"channel": "#travel-compliance-watch",
"text": "[{{ $json.urgency }}] {{ $json.deadline_type }} \u2014 {{ $json.days_left }} days remaining. Customer: {{ $json.customer_name }}."
}
}
],
"connections": {
"Schedule: Daily 08:00 UTC": {
"main": [
[
{
"node": "Sheets: Read Compliance Deadlines",
"type": "main",
"index": 0
}
]
]
},
"Sheets: Read Compliance Deadlines": {
"main": [
[
{
"node": "Code: Classify Urgency",
"type": "main",
"index": 0
}
]
]
},
"Code: Classify Urgency": {
"main": [
[
{
"node": "IF: Critical or Overdue",
"type": "main",
"index": 0
}
]
]
},
"IF: Critical or Overdue": {
"main": [
[
{
"node": "Slack: #travel-compliance-critical",
"type": "main",
"index": 0
},
{
"node": "Gmail: Compliance Owner Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack: #travel-compliance-watch",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 3: TravelTech Platform API Health Monitor
Checks five critical endpoints every 15 minutes — booking engine API (DOT refund clock annotation), payment processing API (PSD2 Art.96 4-hour clock annotation), SCA authentication API (EBA RTS Art.4 annotation), GDPR erasure request API (Art.17 30-day clock), and PCI DSS log integrity API (Req.10.3/10.6 annotation). Downtime on the PSD2 payment API requires immediate assessment of Art.96 major incident classification. All status events logged to Google Sheets for QSA evidence.
{
"name": "TravelTech SaaS \u2014 Platform API Health Monitor",
"nodes": [
{
"id": "1",
"name": "Schedule: Every 15 min",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
240,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 15
}
]
}
}
},
{
"id": "2",
"name": "Code: Define Endpoints",
"type": "n8n-nodes-base.code",
"position": [
460,
300
],
"parameters": {
"jsCode": "return [\n {json: {name: 'booking_engine_api', url: process.env.BOOKING_API_URL, standard: 'DOT 14 CFR \u00a7399.80 \u2014 refund clock starts at booking confirmation webhook receipt', critical_note: 'DOT refund clock starts when booking system receives cancellation event \u2014 downtime = clock running without acknowledgment'}},\n {json: {name: 'payment_processing_api', url: process.env.PAYMENT_API_URL, standard: 'PSD2 Art.96 + PCI DSS v4.0 Req.6 \u2014 4-hour major incident clock', critical_note: 'PSD2 Art.96 major incident clock starts at classification \u2014 payment API downtime must be assessed for Art.96 reporting obligation within 4 hours'}},\n {json: {name: 'sca_authentication_api', url: process.env.SCA_API_URL, standard: 'EBA RTS Art.4 Strong Customer Authentication \u2014 3DS2 server', critical_note: 'SCA outage = EU/UK payment processing halted + possible EBA RTS noncompliance if fallback exemptions exceed approved thresholds'}},\n {json: {name: 'gdpr_erasure_request_api', url: process.env.GDPR_ERASURE_API_URL, standard: 'GDPR Art.17 right to erasure \u2014 30-day response clock per request', critical_note: 'Erasure API downtime = Art.17 30-day clock running without processing \u2014 DPA complaint risk if requests queue unacknowledged'}},\n {json: {name: 'pci_log_integrity_api', url: process.env.PCI_LOG_API_URL, standard: 'PCI DSS v4.0 Req.10.3 \u2014 log integrity monitoring, Req.10.6 daily log review', critical_note: 'PCI DSS Req.10 requires daily log review; downtime in log collection pipeline = compliance gap in QSA evidence'}}\n];"
}
},
{
"id": "3",
"name": "HTTP: Health Check Each",
"type": "n8n-nodes-base.httpRequest",
"position": [
680,
300
],
"parameters": {
"method": "GET",
"url": "={{ $json.url }}/health",
"options": {
"timeout": 10000,
"response": {
"response": {
"neverError": true
}
}
}
}
},
{
"id": "4",
"name": "Code: Classify Status",
"type": "n8n-nodes-base.code",
"position": [
900,
300
],
"parameters": {
"jsCode": "const d = $input.first().json;\nconst status = d.$response?.statusCode || 0;\nconst ms = d.$response?.headers?.['x-response-time'] || 0;\nlet level = 'OK';\nif (status === 0 || status >= 500) level = 'DOWN';\nelse if (status >= 400) level = 'DEGRADED';\nelse if (parseInt(ms) > 3000) level = 'SLOW';\nreturn [{json: {...d, http_status: status, response_ms: ms, level}}];"
}
},
{
"id": "5",
"name": "IF: Not OK",
"type": "n8n-nodes-base.if",
"position": [
1120,
300
],
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.level }}",
"operator": {
"type": "string",
"operation": "notEquals"
},
"rightValue": "OK"
}
]
}
}
},
{
"id": "6",
"name": "Slack: #traveltech-platform-ops",
"type": "n8n-nodes-base.slack",
"position": [
1340,
200
],
"parameters": {
"channel": "#traveltech-platform-ops",
"text": "[{{ $json.level }}] {{ $json.name }} \u2014 HTTP {{ $json.http_status }} / {{ $json.response_ms }}ms. Standard: {{ $json.standard }}. Note: {{ $json.critical_note }}"
}
},
{
"id": "7",
"name": "Sheets: SLA Log",
"type": "n8n-nodes-base.googleSheets",
"position": [
1340,
380
],
"parameters": {
"operation": "append",
"sheetId": "={{ $env.SLA_LOG_SHEET_ID }}",
"columns": {
"mappingMode": "defineBelow",
"value": {
"endpoint": "={{ $json.name }}",
"level": "={{ $json.level }}",
"http_status": "={{ $json.http_status }}",
"response_ms": "={{ $json.response_ms }}",
"checked_at": "={{ new Date().toISOString() }}"
}
}
}
}
],
"connections": {
"Schedule: Every 15 min": {
"main": [
[
{
"node": "Code: Define Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Code: Define Endpoints": {
"main": [
[
{
"node": "HTTP: Health Check Each",
"type": "main",
"index": 0
}
]
]
},
"HTTP: Health Check Each": {
"main": [
[
{
"node": "Code: Classify Status",
"type": "main",
"index": 0
}
]
]
},
"Code: Classify Status": {
"main": [
[
{
"node": "IF: Not OK",
"type": "main",
"index": 0
}
]
]
},
"IF: Not OK": {
"main": [
[
{
"node": "Slack: #traveltech-platform-ops",
"type": "main",
"index": 0
}
],
[
{
"node": "Sheets: SLA Log",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 4: Travel Compliance Incident Response Pipeline
Webhook-triggered. Classifies 8 incident types with mandatory response clocks. PSD2 major payment incident fires IMMEDIATE (4-hour Art.96 clock) with full EBA notification action brief. ADA Title III DOJ investigation and PCI cardholder data breach also CRITICAL/IMMEDIATE. DOT systematic refund failure triggers the 7-business-day credit card clock audit. Illinois BIPA biometric violation fires IMMEDIATE with no cure period note ($1,000–$5,000/person). All critical incidents → #travel-incidents-critical + CCO + Legal Gmail. All incidents logged.
{
"name": "TravelTech SaaS \u2014 Travel Compliance Incident Response Pipeline",
"nodes": [
{
"id": "1",
"name": "Webhook: Incident Ingest",
"type": "n8n-nodes-base.webhook",
"position": [
240,
300
],
"parameters": {
"path": "travel-incident",
"responseMode": "lastNode"
}
},
{
"id": "2",
"name": "Code: Classify Incident",
"type": "n8n-nodes-base.code",
"position": [
460,
300
],
"parameters": {
"jsCode": "const d = $input.first().json;\nconst t = (d.incident_type || '').toUpperCase();\n\nconst clocks = {\n PSD2_MAJOR_PAYMENT_INCIDENT: {\n severity: 'CRITICAL', clock: 'IMMEDIATE (4 hours \u2014 initial EBA notification)',\n authority: 'EBA / national competent authority PSD2 Art.96',\n action: 'Classify incident severity per EBA Art.96 criteria + notify national supervisory authority within 4 hours (initial report) + 24 hours (intermediate) + final report + engage PSD2 counsel + preserve payment system logs'\n },\n ADA_TITLE_III_DOJ_INVESTIGATION: {\n severity: 'CRITICAL', clock: 'IMMEDIATE \u2014 pattern discrimination claim',\n authority: 'DOJ Civil Rights Division / private plaintiffs 42 USC \u00a712188',\n action: 'Preserve all booking flow UI/automation logs + WCAG 2.1 AA audit + engage ADA counsel + document accessibility accommodation history'\n },\n PCI_DSS_CARDHOLDER_DATA_BREACH: {\n severity: 'CRITICAL', clock: 'IMMEDIATE to card networks + PFI forensic',\n authority: 'Visa/MC/Amex/Discover + acquiring bank',\n action: 'Contain breach + notify acquiring bank immediately + engage PFI (forensic investigator) + preserve all log data + comply with forensic investigation + calculate exposure per CHD records'\n },\n DOT_SYSTEMATIC_REFUND_FAILURE: {\n severity: 'HIGH', clock: '7 business days per credit card refund (14 CFR \u00a7399.80)',\n authority: 'DOT Office of Aviation Consumer Protection',\n action: 'Audit pending refund queue + process all overdue credit card refunds (7 biz day clock) + process other-payment refunds (20 cal day clock) + document correction timeline for DOT + review automation pipeline for systematic delay'\n },\n GDPR_DATA_BREACH_TRAVELER_PII: {\n severity: 'HIGH', clock: '72 hours Art.33',\n authority: 'Lead supervisory authority (DPA) GDPR Art.55',\n action: 'Contain breach + notify lead DPA within 72h + assess Art.34 customer notification obligation + preserve audit trail + engage DPA counsel'\n },\n ILLINOIS_BIPA_BIOMETRIC_VIOLATION: {\n severity: 'HIGH', clock: 'IMMEDIATE \u2014 no cure period',\n authority: 'Illinois AG + private right of action 740 ILCS 14/20',\n action: 'Halt biometric data collection immediately + audit consent records + assess $1,000-$5,000/person exposure + notify all affected individuals + engage BIPA defense counsel + review all biometric data flows for retroactive consent gaps'\n },\n CCPA_STATUTORY_VIOLATION: {\n severity: 'MEDIUM', clock: '30-day cure period \u00a71798.155',\n authority: 'California AG + CA Privacy Protection Agency',\n action: 'Identify violation scope + implement cure within 30 days + document cure for AG + review all CCPA consumer request workflows for compliance gaps'\n },\n DOT_ACCESSIBILITY_COMPLAINT_ACAA: {\n severity: 'MEDIUM', clock: '30 days \u00a7382.65',\n authority: 'DOT Office of Aviation Consumer Protection \u2014 Air Carrier Access Act 49 USC \u00a741705',\n action: 'Acknowledge complaint + investigate alleged discrimination + provide written disposition within 30 days + document accommodation offered + retain records per \u00a7382.151'\n }\n};\n\nconst info = clocks[t] || {severity: 'MEDIUM', clock: '30 days', authority: 'Internal compliance team', action: 'Triage and escalate per TravelTech incident runbook'};\n\nreturn [{json: {...d, incident_type: t, ...info, created_at: new Date().toISOString()}}];"
}
},
{
"id": "3",
"name": "IF: Critical",
"type": "n8n-nodes-base.if",
"position": [
680,
300
],
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.severity }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "CRITICAL"
}
]
}
}
},
{
"id": "4",
"name": "Slack: #travel-incidents-critical",
"type": "n8n-nodes-base.slack",
"position": [
900,
200
],
"parameters": {
"channel": "#travel-incidents-critical",
"text": "[CRITICAL] {{ $json.incident_type }} \u2014 Clock: {{ $json.clock }}. Authority: {{ $json.authority }}. ACTION: {{ $json.action }}"
}
},
{
"id": "5",
"name": "Gmail: CCO + Legal",
"type": "n8n-nodes-base.gmail",
"position": [
900,
320
],
"parameters": {
"operation": "send",
"toList": "={{ $env.CCO_EMAIL }}",
"ccList": "={{ $env.LEGAL_EMAIL }}",
"subject": "[CRITICAL] TravelTech Compliance Incident: {{ $json.incident_type }} \u2014 {{ $json.clock }}",
"message": "Incident: {{ $json.incident_type }}\nSeverity: {{ $json.severity }}\nResponse clock: {{ $json.clock }}\nAuthority: {{ $json.authority }}\nRequired action: {{ $json.action }}\nCustomer: {{ $json.customer_name }}\nReported: {{ $json.created_at }}"
}
},
{
"id": "6",
"name": "Slack: #travel-incidents (non-critical)",
"type": "n8n-nodes-base.slack",
"position": [
900,
480
],
"parameters": {
"channel": "#travel-incidents",
"text": "[{{ $json.severity }}] {{ $json.incident_type }} \u2014 {{ $json.clock }} clock. Authority: {{ $json.authority }}. Action: {{ $json.action }}"
}
},
{
"id": "7",
"name": "Sheets: Incident Log",
"type": "n8n-nodes-base.googleSheets",
"position": [
1120,
300
],
"parameters": {
"operation": "append",
"sheetId": "={{ $env.INCIDENT_LOG_SHEET_ID }}",
"columns": {
"mappingMode": "defineBelow",
"value": {
"incident_type": "={{ $json.incident_type }}",
"severity": "={{ $json.severity }}",
"clock": "={{ $json.clock }}",
"authority": "={{ $json.authority }}",
"customer": "={{ $json.customer_name }}",
"created_at": "={{ $json.created_at }}"
}
}
}
},
{
"id": "8",
"name": "Respond: 200 OK",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1340,
300
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({received: true, severity: $json.severity, clock: $json.clock}) }}"
}
}
],
"connections": {
"Webhook: Incident Ingest": {
"main": [
[
{
"node": "Code: Classify Incident",
"type": "main",
"index": 0
}
]
]
},
"Code: Classify Incident": {
"main": [
[
{
"node": "IF: Critical",
"type": "main",
"index": 0
}
]
]
},
"IF: Critical": {
"main": [
[
{
"node": "Slack: #travel-incidents-critical",
"type": "main",
"index": 0
},
{
"node": "Gmail: CCO + Legal",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack: #travel-incidents (non-critical)",
"type": "main",
"index": 0
}
]
]
},
"Gmail: CCO + Legal": {
"main": [
[
{
"node": "Sheets: Incident Log",
"type": "main",
"index": 0
}
]
]
},
"Slack: #travel-incidents (non-critical)": {
"main": [
[
{
"node": "Sheets: Incident Log",
"type": "main",
"index": 0
}
]
]
},
"Sheets: Incident Log": {
"main": [
[
{
"node": "Respond: 200 OK",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 5: Weekly TravelTech Platform KPI Report
Fires Monday 08:00 UTC. Queries Postgres for active customers by tier, MRR with WoW percentage change (via $getWorkflowStaticData), DOT §399 subject count, PSD2 SCA required count, PCI DSS Level 1 count, GDPR travel data processor count, critical incidents in 7 days, DOT refund incidents in 7 days, and critical deadlines in 14 days. Sends HTML report to CEO + CCO + Slack #travel-go-to-market.
{
"name": "TravelTech SaaS \u2014 Weekly Platform KPI Report",
"nodes": [
{
"id": "1",
"name": "Schedule: Monday 08:00 UTC",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
240,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
}
},
{
"id": "2",
"name": "Postgres: Weekly Travel Metrics",
"type": "n8n-nodes-base.postgres",
"position": [
460,
300
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT\n COUNT(DISTINCT c.id) FILTER (WHERE c.status='active') as active_customers,\n COUNT(DISTINCT c.id) FILTER (WHERE c.created_at >= NOW()-INTERVAL '7 days') as new_this_week,\n SUM(s.mrr_usd) as total_mrr,\n COUNT(DISTINCT c.id) FILTER (WHERE c.tier='ONLINE_TRAVEL_AGENCY_PLATFORM') as ota_count,\n COUNT(DISTINCT c.id) FILTER (WHERE c.flags LIKE '%DOT_14_CFR_399_SUBJECT%') as dot_subject_count,\n COUNT(DISTINCT c.id) FILTER (WHERE c.flags LIKE '%PSD2_SCA_EU_UK_REQUIRED%') as psd2_count,\n COUNT(DISTINCT c.id) FILTER (WHERE c.flags LIKE '%PCI_DSS_LEVEL_1_MERCHANT%') as pci_count,\n COUNT(DISTINCT c.id) FILTER (WHERE c.flags LIKE '%GDPR_TRAVEL_DATA_PROCESSOR%') as gdpr_count,\n COUNT(i.id) FILTER (WHERE i.severity='CRITICAL' AND i.created_at >= NOW()-INTERVAL '7 days') as critical_incidents_7d,\n COUNT(i.id) FILTER (WHERE i.incident_type='DOT_SYSTEMATIC_REFUND_FAILURE' AND i.created_at >= NOW()-INTERVAL '7 days') as dot_refund_incidents_7d,\n COUNT(d.id) FILTER (WHERE d.urgency='CRITICAL' AND d.deadline_date <= NOW()+INTERVAL '14 days') as critical_deadlines_14d\nFROM customers c\nLEFT JOIN subscriptions s ON s.customer_id = c.id\nLEFT JOIN incidents i ON i.customer_id = c.id\nLEFT JOIN deadlines d ON d.customer_id = c.id"
}
},
{
"id": "3",
"name": "Code: Build KPI Report",
"type": "n8n-nodes-base.code",
"position": [
680,
300
],
"parameters": {
"jsCode": "const d = $input.first().json;\nconst snap = $getWorkflowStaticData('global');\nconst prevMrr = snap.prev_mrr || d.total_mrr;\nconst mrrWow = prevMrr > 0 ? (((d.total_mrr - prevMrr) / prevMrr) * 100).toFixed(1) : '0.0';\nsnap.prev_mrr = d.total_mrr;\n\nconst html = `\n<h2>FlowKit \u2014 TravelTech SaaS Weekly KPI Report</h2>\n<p><strong>Week ending: ${new Date().toISOString().split('T')[0]}</strong></p>\n<table border=\"1\" cellpadding=\"6\" style=\"border-collapse:collapse;\">\n <tr><th>Metric</th><th>Value</th><th>Notes</th></tr>\n <tr><td>Active Customers</td><td>${d.active_customers}</td><td></td></tr>\n <tr><td>New This Week</td><td>${d.new_this_week}</td><td></td></tr>\n <tr><td>Total MRR</td><td>$${Number(d.total_mrr).toLocaleString()}</td><td>WoW: ${mrrWow}%</td></tr>\n <tr><td>OTA Platforms</td><td>${d.ota_count}</td><td>DOT \u00a7399.80 subject</td></tr>\n <tr><td>DOT \u00a7399 Subject</td><td>${d.dot_subject_count}</td><td>14 CFR Part 399 refund obligation</td></tr>\n <tr><td>PSD2 SCA Required</td><td>${d.psd2_count}</td><td>EBA RTS Art.30</td></tr>\n <tr><td>PCI DSS Level 1</td><td>${d.pci_count}</td><td>QSA annual assessment</td></tr>\n <tr><td>GDPR Travel Processors</td><td>${d.gdpr_count}</td><td>Art.28 DPA required</td></tr>\n <tr><td>Critical Incidents (7d)</td><td>${d.critical_incidents_7d}</td><td>${d.critical_incidents_7d > 0 ? 'Review required' : 'Clean'}</td></tr>\n <tr><td>DOT Refund Incidents (7d)</td><td>${d.dot_refund_incidents_7d}</td><td>${d.dot_refund_incidents_7d > 0 ? 'DOT enforcement risk' : 'Clear'}</td></tr>\n <tr><td>Critical Deadlines (14d)</td><td>${d.critical_deadlines_14d}</td><td>${d.critical_deadlines_14d > 0 ? 'Immediate action' : 'Clear'}</td></tr>\n</table>\n<p><em>FlowKit TravelTech SaaS Compliance Templates \u2014 <a href=\"https://stripeai.gumroad.com\">stripeai.gumroad.com</a></em></p>`;\n\nreturn [{json: {...d, html_report: html, mrr_wow: mrrWow}}];"
}
},
{
"id": "4",
"name": "Gmail: Weekly Report to CEO + CCO",
"type": "n8n-nodes-base.gmail",
"position": [
900,
300
],
"parameters": {
"operation": "send",
"toList": "={{ $env.CEO_EMAIL }}",
"ccList": "={{ $env.CCO_EMAIL }}",
"subject": "FlowKit TravelTech Weekly KPI \u2014 {{ new Date().toISOString().split('T')[0] }}",
"message": "={{ $json.html_report }}",
"options": {
"isBodyHtml": true
}
}
},
{
"id": "5",
"name": "Slack: #travel-go-to-market",
"type": "n8n-nodes-base.slack",
"position": [
900,
440
],
"parameters": {
"channel": "#travel-go-to-market",
"text": "Weekly TravelTech KPI: {{ $json.active_customers }} customers, MRR ${{ $json.total_mrr }} (WoW {{ $json.mrr_wow }}%). DOT subjects: {{ $json.dot_subject_count }}, PSD2: {{ $json.psd2_count }}, PCI: {{ $json.pci_count }}. Critical incidents 7d: {{ $json.critical_incidents_7d }}."
}
}
],
"connections": {
"Schedule: Monday 08:00 UTC": {
"main": [
[
{
"node": "Postgres: Weekly Travel Metrics",
"type": "main",
"index": 0
}
]
]
},
"Postgres: Weekly Travel Metrics": {
"main": [
[
{
"node": "Code: Build KPI Report",
"type": "main",
"index": 0
}
]
]
},
"Code: Build KPI Report": {
"main": [
[
{
"node": "Gmail: Weekly Report to CEO + CCO",
"type": "main",
"index": 0
},
{
"node": "Slack: #travel-go-to-market",
"type": "main",
"index": 0
}
]
]
}
}
}
Why Self-Hosted n8n Is the Right Architecture for TravelTech SaaS
| Requirement | Cloud iPaaS (Zapier/Make) | Self-Hosted n8n |
|---|---|---|
| DOT refund enforcement — booking log production | ❌ DOT subpoenas cloud vendor before your legal team | ✅ All refund automation logs inside your legal hold boundary |
| ADA Title III — DOJ pattern discrimination evidence | ❌ Cloud iPaaS booking flow logs outside attorney-client privilege | ✅ Accessibility incident records inside your legal environment |
| PSD2 Art.96 — 4-hour incident notification | ❌ Cloud vendor response time consumes your notification window | ✅ Incident pipeline runs in your environment, no third-party latency |
| PCI DSS Req.10 — log integrity and daily review | ❌ Cloud iPaaS log aggregation falls outside QSA assessed scope | ✅ Complete payment log chain inside PCI DSS cardholder data environment |
| GDPR Art.17 — traveler data erasure | ❌ Zapier/Make task execution logs contain traveler PII + separate retention policy | ✅ Erasure pipeline deletes from every table you control |
| Illinois BIPA — biometric data processing records | ❌ Fingerprint POS enrollment events in cloud vendor's US infrastructure | ✅ Biometric processing records inside your BIPA consent boundary |
The DOT's 2024 refund rule is the most significant change to US travel consumer protection in a decade. It shifts the enforcement posture from reactive complaint-handling to systematic platform audits — DOT investigators look for patterns in OTA and airline system automation, not just individual customer complaints. If your platform's refund pipeline runs through cloud iPaaS, you have third-party witnesses to that audit you cannot control.
Get the full workflow pack at stripeai.gumroad.com.
Questions? Drop a comment or reply to this post. I answer everything.
Top comments (0)