Add Enrich Client Excel from Email.json

main
bill 2025-11-02 03:26:03 +00:00
parent ca803ddf58
commit 2f5c19c206
1 changed files with 901 additions and 0 deletions

View File

@ -0,0 +1,901 @@
{
"createdAt": "2025-11-01T05:48:54.245Z",
"updatedAt": "2025-11-01T05:48:54.245Z",
"id": "sMcGBE1qq5fln6EM",
"name": "Enrich Client Excel from Email",
"active": false,
"isArchived": false,
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"id": "a96f3a61-9bbb-47cb-a53c-2c42c5fe4d64",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"options": {
"systemMessage": "You enrich missing client fields from a single email.\n\nYou are given:\n- email: { from, to, cc, bcc, subject, body }\n- clients: [ { id, name, company, address, city, state, zip, phone, cell, fax, email, projects, last, followUp }, ... ]\n\nYour job:\n1) Identify which client(s) the email refers to via name/email/signature/routing or explicit textual cues.\n2) Extract ONLY fields that are currently missing/blank in the matched client(s). Do not overwrite any non-empty value.\n3) If there is reference to a job or project those should be appended and added under \"projects\"\n4) If there was a request for some type of follow up that should be noted under \"followUp\"\n5) Normalize:\n - email: lowercase, trimmed\n - phone/cell/fax: digits+dashes; e.g., 832-691-6430\n - zip: 5 digits (or 9 with dash if present)\n - dates (e.g., \"last\"): YYYY-MM-DD\n6) separate out full addresses into their component parts (e.g., street separate from city, separate from state, etc.)\n7) Note that most of the time the persons e-mail address is actually in the to, from, cc or bcc data elements. Be sure to capture those.\n8) If ambiguous, skip that field—do not guess.\n\nSTRICT OUTPUT (no commentary):\nReturn a single JSON object:\n{\n \"updates\": [\n {\n \"name\": \"John Doe\",\n \"id\": \"<client-id-as-string-or-number>\",\n // include only fields you actually found and that were previously missing\n \"email\": \"name@example.com\",\n \"phone\": \"832-691-6430\",\n \"address\": \"123 Main St\",\n \"city\": \"Olalla\",\n \"state\": \"WA\",\n \"zip\": \"98359\",\n \"cell\": \"832-555-1212\",\n \"fax\": \"555-1212\",\n \"company\": \"Acme Co\",\n \"projects\": \"Kitchen Remodel\",\n \"last\": \"2025-10-28\",\n \"followUp\": \"Call next week\"\n }\n ]\n}\n\nRules:\n- If nothing to update, return { \"updates\": [] }.\n- Do NOT include the full client list in the output.\n- Output JSON only (no code fences, no prose).\n",
"enableStreaming": true
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 2.2,
"position": [
2112,
160
],
"id": "4f1fde5e-f803-4773-947b-2e56761dc942",
"name": "AI Agent1"
},
{
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [
2064,
384
],
"id": "a4da7f57-763c-4a02-9162-87cdef00cc46",
"name": "OpenAI Chat Model1"
},
{
"parameters": {},
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [
2256,
384
],
"id": "fd56efeb-4b9b-42d8-b753-051a865fc380",
"name": "Simple Memory1"
},
{
"parameters": {
"operation": "xlsx",
"options": {
"headerRow": true,
"includeEmptyCells": true,
"rawData": true
}
},
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
592,
0
],
"id": "48ce1be0-3249-4ea4-a4fc-136d7f7c9413",
"name": "formatClientList",
"alwaysOutputData": true
},
{
"parameters": {
"fileSelector": "/data/bill/clientList.xlsx",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
384,
0
],
"id": "e2667bd1-2ba9-45d4-8ce2-ddd512926541",
"name": "importClientList"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "b73ca669-5c9b-4a23-ab78-d1a111c8f129",
"name": "sessionId",
"value": "={{ $now }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
176,
0
],
"id": "a505f8e2-21e1-421c-8943-9b7511f0b616",
"name": "sessionIdCreate"
},
{
"parameters": {
"dataTableId": {
"__rl": true,
"value": "RE5GmewdBpOuPS4E",
"mode": "list",
"cachedResultName": "clientList",
"cachedResultUrl": "/projects/MAbDV0ZMuTHgonhb/datatables/RE5GmewdBpOuPS4E"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {
"name": "={{ $json.name }}"
},
"matchingColumns": [],
"schema": [
{
"id": "name",
"displayName": "name",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "company",
"displayName": "company",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "address",
"displayName": "address",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "city",
"displayName": "city",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "state",
"displayName": "state",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "zip",
"displayName": "zip",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "phone",
"displayName": "phone",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "cell",
"displayName": "cell",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "fax",
"displayName": "fax",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "email",
"displayName": "email",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "projects",
"displayName": "projects",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "last",
"displayName": "last",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "followUp",
"displayName": "followUp",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
1088,
144
],
"id": "37663988-fdc0-4dbc-8900-761186658c6e",
"name": "createClientDataTable"
},
{
"parameters": {
"fileSelector": "/data/bill/Inbox",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
1264,
144
],
"id": "804c8f42-0b5a-4c83-b5bf-f606b47883f4",
"name": "importEmailBinary"
},
{
"parameters": {
"jsCode": "// Access base64 string from binary.data.data\nconst base64Str = $input.first().binary?.data?.data;\n\nif (!base64Str) {\n throw new Error('No base64 string found in binary data');\n}\n\n// Decode base64 to UTF-8 text\nconst buffer = Buffer.from(base64Str, 'base64');\nconst raw = buffer.toString('utf8');\n\n// Split into individual emails by mbox-style delimiter\nconst rawEmails = raw.split(/\\n(?=From - )/);\n\n// Utility to extract headers\nfunction extractHeader(line, field) {\n const regex = new RegExp(`^${field}: (.+)`, 'i');\n const match = line.match(regex);\n return match ? match[1].trim() : null;\n}\n\n// Parse each email block\nconst parsed = rawEmails.map(block => {\n const lines = block.split('\\n');\n const headers = {\n from: null,\n to: null,\n cc: null,\n bcc: null,\n subject: null,\n body: '',\n };\n\n let isHeader = true;\n const bodyLines = [];\n\n for (let line of lines) {\n if (isHeader) {\n if (line.trim() === '') {\n isHeader = false;\n continue;\n }\n headers.from = headers.from || extractHeader(line, 'From');\n headers.to = headers.to || extractHeader(line, 'To');\n headers.cc = headers.cc || extractHeader(line, 'Cc');\n headers.bcc = headers.bcc || extractHeader(line, 'Bcc');\n headers.subject = headers.subject || extractHeader(line, 'Subject');\n } else {\n bodyLines.push(line);\n }\n }\n\n headers.body = bodyLines.join('\\n').trim();\n return { json: headers };\n});\n\nreturn parsed;\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1440,
144
],
"id": "8d6eca1e-e5bc-49a4-af6d-2d25bf373490",
"name": "createEmailString"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
1648,
144
],
"id": "adaec926-df6f-46dc-b06d-5d033710d1e9",
"name": "loopOverEmail"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "0c87872b-222c-47f0-94c8-84d0692e03ff",
"name": "sessionId",
"value": "={{ $('sessionIdCreate').first().json.sessionId }}",
"type": "string"
},
{
"id": "6c9d3fd3-1405-4422-a47b-89b356efa616",
"name": "chatInput",
"value": "={{ JSON.stringify({\n instruction: \"You are a data assistant. Given a single email and a list of clients with potentially incomplete records, scan the email to find any client it refers to. If you find a match, extract any missing information and return a list of only the updated fields. Do not change any existing data.\",\n email: {\n from: $json.from,\n to: $json.to,\n cc: $json.cc,\n bcc: $json.bcc,\n subject: $json.subject,\n body: $json.body\n },\n clients: $('formatClientList').all().map(client => ({\n id: client.json.id ?? client.itemIndex + 1,\n ...client.json\n }))\n}) }}\n",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1904,
160
],
"id": "0c27a0df-6313-43aa-9381-135de87eeaae",
"name": "createPrompt"
},
{
"parameters": {
"jsCode": "// ---- helpers ----\nfunction normalizePhone(v){ if (typeof v !== 'string') return v; const d=v.replace(/\\D+/g,''); if(d.length===10)return`${d.slice(0,3)}-${d.slice(3,6)}-${d.slice(6)}`; if(d.length===11&&d.startsWith('1'))return`${d.slice(1,4)}-${d.slice(4,7)}-${d.slice(7)}`; return String(v).trim(); }\nconst normalizeEmail = v => (typeof v === 'string' ? v.trim().toLowerCase() : v);\nfunction normalizeZip(v){ if(v==null)return v; const s=String(v).trim(); const m=s.match(/^(\\d{5})(\\d{4})$/); if(m)return`${m[1]}-${m[2]}`; if(/^\\d{5}$/.test(s))return s; const x=s.match(/^(\\d{5})[- ](\\d{4})$/); if(x)return`${x[1]}-${x[2]}`; return s; }\nfunction normalizeDateYMD(v){ if(!v)return v; const s=String(v).trim(); if(/^\\d{4}-\\d{2}-\\d{2}$/.test(s))return s; const d=new Date(s); if(!isNaN(d.valueOf())){ const y=d.getUTCFullYear(); const m=String(d.getUTCMonth()+1).padStart(2,'0'); const day=String(d.getUTCDate()).padStart(2,'0'); return `${y}-${m}-${day}`;} return s; }\nconst isBlank = v => v === '' || v === null || typeof v === 'undefined';\nconst allowed = new Set(['id','name','company','address','city','state','zip','phone','cell','fax','email','projects','last','followUp']);\n\n// ---- get BOTH inputs safely ----\nlet inputs = $input.all().filter(arr => Array.isArray(arr) && arr.length > 0);\n\n// Identify which input is the updates bundle and which is the table rows\nlet updatesArr = [];\nlet tableRows = [];\n\nfor (const arr of inputs) {\n const j = arr[0]?.json ?? {};\n if (Array.isArray(j.updates)) {\n updatesArr = j.updates;\n } else if (j && (j.id !== undefined || j.name !== undefined)) {\n // Looks like a client row\n tableRows = arr.map(i => ({ ...i.json }));\n }\n}\n\n// If your n8n wiring is reversed, fall back by position\nif (updatesArr.length === 0 && inputs[0]?.[0]?.json?.updates) {\n updatesArr = inputs[0][0].json.updates;\n}\nif (tableRows.length === 0 && inputs[1]?.length) {\n tableRows = inputs[1].map(i => ({ ...i.json }));\n}\n\n// If still nothing, just pass through\nif (tableRows.length === 0) {\n console.log('No table rows arrived; passing nothing.');\n return [];\n}\n\n// Build id -> row map\nconst byId = new Map();\nfor (const row of tableRows) {\n const id = String(row.id ?? row.ID ?? row.Id ?? '');\n if (id) byId.set(id, row);\n}\n\n// Apply updates (fill only blanks)\nfor (const u of updatesArr) {\n if (!u || u.id === undefined || u.id === null) continue;\n const id = String(u.id);\n const row = byId.get(id);\n if (!row) continue;\n\n for (const [k, vRaw] of Object.entries(u)) {\n if (k === 'id' || !allowed.has(k)) continue;\n if (isBlank(vRaw) || !isBlank(row[k])) continue;\n\n let v = vRaw;\n if (k === 'email') v = normalizeEmail(vRaw);\n if (k === 'phone' || k === 'cell' || k === 'fax') v = normalizePhone(vRaw);\n if (k === 'zip') v = normalizeZip(vRaw);\n if (k === 'last') v = normalizeDateYMD(vRaw);\n\n row[k] = v;\n }\n}\n\n// Emit updated rows for Upsert\nreturn tableRows.map(r => ({ json: r }));\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2880,
160
],
"id": "f50ea076-1b07-4367-af7f-b4cc0c0f9fd1",
"name": "Parse & Apply Client Updates",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "// AI Agent1 puts JSON as a STRING in `output`.\n// Parse it here and emit a clean object with { updates: [...] }\n\nconst raw = $json.output ?? '';\nlet updates = [];\n\nif (typeof raw === 'string') {\n try {\n const obj = JSON.parse(raw);\n if (obj && Array.isArray(obj.updates)) updates = obj.updates;\n } catch (e) {\n // leave updates as []\n }\n} else if (raw && Array.isArray(raw.updates)) {\n updates = raw.updates; // already an object (just in case)\n}\n\n// For visibility during testing\nconsole.log('Extracted updates:', updates);\n\nreturn [{ json: { updates } }];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2464,
160
],
"id": "6a834e6e-d437-4d7a-a6fb-c9f57791ba15",
"name": "Extract Updates"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "RE5GmewdBpOuPS4E",
"mode": "list",
"cachedResultName": "clientList",
"cachedResultUrl": "/projects/MAbDV0ZMuTHgonhb/datatables/RE5GmewdBpOuPS4E"
},
"filters": {
"conditions": [
{
"keyValue": "={{ $json.updates[0].id }}"
}
]
},
"returnAll": true
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
2672,
160
],
"id": "d80698d9-963d-4c92-8c54-16f39057af4d",
"name": "Get row(s)",
"alwaysOutputData": true
},
{
"parameters": {
"operation": "update",
"dataTableId": {
"__rl": true,
"value": "RE5GmewdBpOuPS4E",
"mode": "list",
"cachedResultName": "clientList",
"cachedResultUrl": "/projects/MAbDV0ZMuTHgonhb/datatables/RE5GmewdBpOuPS4E"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "name",
"keyValue": "={{ $('Extract Updates').item.json.updates[0].name }}"
},
{
"keyValue": "={{ $('Extract Updates').item.json.updates[0].id }}"
}
]
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"email": "={{ $('Extract Updates').item.json.updates[0].email }}",
"company": "={{ $('Extract Updates').item.json.updates[0].company }}",
"address": "={{ $('Extract Updates').item.json.updates[0].address }}",
"city": "={{ $('Extract Updates').item.json.updates[0].city }}",
"state": "={{ $('Extract Updates').item.json.updates[0].state }}",
"zip": "={{ $('Extract Updates').item.json.updates[0].zip }}",
"phone": "={{ $('Extract Updates').item.json.updates[0].phone }}",
"cell": "={{ $('Extract Updates').item.json.updates[0].cell }}",
"fax": "={{ $('Extract Updates').item.json.updates[0].fax }}",
"projects": "={{ $('Extract Updates').item.json.updates[0].projects }}",
"last": "={{ $('Extract Updates').item.json.updates[0].last }}",
"followUp": "={{ $('Extract Updates').item.json.updates[0].followUp }}"
},
"matchingColumns": [],
"schema": [
{
"id": "name",
"displayName": "name",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": true
},
{
"id": "company",
"displayName": "company",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "address",
"displayName": "address",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "city",
"displayName": "city",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "state",
"displayName": "state",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "zip",
"displayName": "zip",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "phone",
"displayName": "phone",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "cell",
"displayName": "cell",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "fax",
"displayName": "fax",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "email",
"displayName": "email",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "projects",
"displayName": "projects",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "last",
"displayName": "last",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "followUp",
"displayName": "followUp",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
3072,
160
],
"id": "39110f9d-d801-489b-b71e-1beb570659b6",
"name": "updateClientList",
"alwaysOutputData": true
},
{
"parameters": {
"content": "to do:\nextract e-amil from the router header\nremove css/html from body for tocken prseervations"
},
"type": "n8n-nodes-base.stickyNote",
"position": [
1184,
640
],
"typeVersion": 1,
"id": "4511268c-de79-4a93-99d2-f484a0da7531",
"name": "Sticky Note"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "RE5GmewdBpOuPS4E",
"mode": "list",
"cachedResultName": "clientList",
"cachedResultUrl": "/projects/MAbDV0ZMuTHgonhb/datatables/RE5GmewdBpOuPS4E"
},
"filters": {
"conditions": [
{
"keyValue": "1"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
784,
0
],
"id": "e5fe4479-acf9-4762-a310-2fe33e50cfd8",
"name": "checkForClientList"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "98efa086-199d-4922-abfd-2df24514c2ee",
"leftValue": "={{ $json.id }}",
"rightValue": "1",
"operator": {
"type": "number",
"operation": "exists",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
944,
0
],
"id": "248f1064-6cfb-4a1b-8772-acb351b26b51",
"name": "doesClientListExist"
}
],
"connections": {
"When clicking Execute workflow": {
"main": [
[
{
"node": "sessionIdCreate",
"type": "main",
"index": 0
}
]
]
},
"AI Agent1": {
"main": [
[
{
"node": "Extract Updates",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model1": {
"ai_languageModel": [
[
{
"node": "AI Agent1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Simple Memory1": {
"ai_memory": [
[
{
"node": "AI Agent1",
"type": "ai_memory",
"index": 0
}
]
]
},
"formatClientList": {
"main": [
[
{
"node": "checkForClientList",
"type": "main",
"index": 0
}
]
]
},
"importClientList": {
"main": [
[
{
"node": "formatClientList",
"type": "main",
"index": 0
}
]
]
},
"sessionIdCreate": {
"main": [
[
{
"node": "importClientList",
"type": "main",
"index": 0
}
]
]
},
"createClientDataTable": {
"main": [
[
{
"node": "importEmailBinary",
"type": "main",
"index": 0
}
]
]
},
"importEmailBinary": {
"main": [
[
{
"node": "createEmailString",
"type": "main",
"index": 0
}
]
]
},
"createEmailString": {
"main": [
[
{
"node": "loopOverEmail",
"type": "main",
"index": 0
}
]
]
},
"loopOverEmail": {
"main": [
[],
[
{
"node": "createPrompt",
"type": "main",
"index": 0
}
]
]
},
"createPrompt": {
"main": [
[
{
"node": "AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"Parse & Apply Client Updates": {
"main": [
[
{
"node": "updateClientList",
"type": "main",
"index": 0
}
]
]
},
"Extract Updates": {
"main": [
[
{
"node": "Get row(s)",
"type": "main",
"index": 0
}
]
]
},
"Get row(s)": {
"main": [
[
{
"node": "Parse & Apply Client Updates",
"type": "main",
"index": 0
}
]
]
},
"updateClientList": {
"main": [
[
{
"node": "loopOverEmail",
"type": "main",
"index": 0
}
]
]
},
"checkForClientList": {
"main": [
[
{
"node": "doesClientListExist",
"type": "main",
"index": 0
}
]
]
},
"doesClientListExist": {
"main": [
[
{
"node": "importEmailBinary",
"type": "main",
"index": 0
}
],
[
{
"node": "createClientDataTable",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"meta": null,
"pinData": {},
"versionId": "5245ff56-5391-4c67-948b-df21811ac123",
"triggerCount": 0,
"shared": [
{
"createdAt": "2025-11-01T05:48:54.248Z",
"updatedAt": "2025-11-01T05:48:54.248Z",
"role": "workflow:owner",
"workflowId": "sMcGBE1qq5fln6EM",
"projectId": "oI3LZpkceKxAFXfg"
}
],
"tags": [
{
"createdAt": "2025-11-01T05:48:51.009Z",
"updatedAt": "2025-11-01T05:48:51.009Z",
"id": "Lf8JGZly51m5AWJv",
"name": "TAG"
}
]
}