{"workflow":{"id":14209,"name":"Build an omnichannel OTP verification flow","views":26,"recentViews":1,"totalViews":26,"createdAt":"2026-03-20T23:18:52.112Z","description":"**How it works**\n\n\n• Receives user identity data from multiple channels (WhatsApp, Telegram, email).\n• Generates and stores secure one-time passwords (OTP).\n• Validates OTP codes against Postgres records.\n• Centralizes user identity across channels.\n• Maintains session continuity for onboarding and verification.\n\n**Set up steps**\n\n• Import the workflow into n8n.\n• Configure Postgres or Supabase credentials.\n• Download and create the required database tables in Supabase.\n• Connect messaging channel credentials.\n• Define OTP expiration and validation rules.\n• Test using sample user verification scenarios.","workflow":{"id":"sTHPXMtsLWWknYKf","meta":{"instanceId":"fc542c1c50834db93f4c2ec54f0b22e845aa07e55bbdcab4ae51fd60fe13f015"},"name":"1. User verification OTP Onmichannel Workflow N8N","tags":[],"nodes":[{"id":"870cf631-17bf-45bf-a865-afcb775b48b6","name":"Webhook","type":"n8n-nodes-base.webhook","position":[736,1360],"webhookId":"8e947f01-96d1-47ed-bc4d-e28bcc71821a","parameters":{"path":"8e947f01-96d1-47ed-bc4d-e28bcc71821a","options":{},"httpMethod":"POST"},"typeVersion":2.1},{"id":"32ac0aaf-aefd-4259-83af-c4730711c3f7","name":"If","type":"n8n-nodes-base.if","position":[1360,1360],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"a8ceb413-8575-4879-8849-ce6dd3831d01","operator":{"type":"number","operation":"gt"},"leftValue":"={{ Object.keys($json).length }}","rightValue":0}]}},"typeVersion":2.3},{"id":"318e9acf-08ff-4087-b899-f9046bc55e32","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[1280,896],"parameters":{"content":"## the user exists\n"},"typeVersion":1},{"id":"4f624126-8d43-4161-a36b-eaf0a6a16b83","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[1248,1856],"parameters":{"content":"## the user does not exist"},"typeVersion":1},{"id":"f124e921-285b-4933-b89c-9aad8f6dcfa8","name":"Execute a SQL query","type":"n8n-nodes-base.postgres","position":[1664,1632],"parameters":{"query":"INSERT INTO onboarding_sessions (channel, platform_user_id, step)\nVALUES ($1, $2, 'waiting_for_email')\nON CONFLICT (channel, platform_user_id)\nDO NOTHING;","options":{"queryReplacement":"={{ [\n  $json.channel ?? $node[\"Universal normalization\"].json.channel,\n  $json.platform_user_id ?? $node[\"Universal normalization\"].json.platform_user_id\n] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"b3bb2f0a-a796-4a3a-9b7a-8de5e6638165","name":"If1","type":"n8n-nodes-base.if","position":[2256,1552],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"9184710a-ce1e-4938-80b9-cf97eb291012","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.step }}","rightValue":"waiting_for_email"}]}},"typeVersion":2.3},{"id":"df899e6e-2829-4824-897a-b38ce6cd1341","name":"waiting_for_otp","type":"n8n-nodes-base.postgres","position":[4016,288],"parameters":{"query":"UPDATE onboarding_sessions\nSET step = 'waiting_for_otp'\nWHERE channel = $1\nAND platform_user_id = $2;","options":{"queryReplacement":"={{ $node[\"Universal normalization\"].json.channel }}\n{{ $node[\"Universal normalization\"].json.platform_user_id }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"ba17533b-03ac-4216-a042-9fd10c113a77","name":"If2- extracted_email","type":"n8n-nodes-base.if","position":[2928,304],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"4c27bcc3-d6c0-4311-9a3e-770e7588975d","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $('Extract email').item.json.extracted_email }}","rightValue":""}]}},"typeVersion":2.3},{"id":"0b532844-bc77-429d-80c0-4d2b42656f87","name":"Send email","type":"n8n-nodes-base.emailSend","position":[3792,288],"webhookId":"ed85b76d-13fc-489f-a0cf-92820faab726","parameters":{"html":"=<h2>Your verification code</h2>\n\n<p>Your code is:</p>\n\n<h1>{{ $('Generate OTP').item.json.otp_code }}</h1>\n\n<p>This code expires in 5 minutes.</p>\n\n<p>Este código expira en 5 minutos.</p>","options":{},"subject":"Tu código de verificación","toEmail":"={{ $('Extract email').item.json.extracted_email }}","fromEmail":"user@example.com"},"credentials":{"smtp":{"id":"credential-id","name":"SMTP account"}},"typeVersion":2.1},{"id":"8f1b6e70-2b32-4ea7-aa0c-801e17f54c3f","name":"If2","type":"n8n-nodes-base.if","position":[4240,288],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"6c058e84-ffa0-4d4b-bac0-e94f57daa328","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.step }}","rightValue":"waiting_for_otp"}]}},"typeVersion":2.3},{"id":"450bbb83-2d89-4236-8a5f-c122fcbd16b6","name":"Execute a SQL query1","type":"n8n-nodes-base.postgres","position":[2928,2080],"parameters":{"query":"SELECT *\nFROM user_otps\nWHERE channel = $1\nAND platform_user_id = $2\nAND otp_code = $3\nAND is_used = false\nAND expires_at > now()\nORDER BY created_at DESC\nLIMIT 1;","options":{"queryReplacement":"={{ [ $('Universal normalization').item.json.channel, $('Universal normalization').item.json.platform_user_id, (($('Universal normalization').item.json.message || '').trim()) ] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6,"alwaysOutputData":true},{"id":"9ac99506-f4f4-4913-9692-38392c909e26","name":"Execute a SQL query2","type":"n8n-nodes-base.postgres","position":[3920,2064],"parameters":{"query":"UPDATE onboarding_sessions\nSET step = 'verified'\nWHERE channel = $1\nAND platform_user_id = $2;","options":{"queryReplacement":"={{ [ $('Universal normalization').item.json.channel, $('Universal normalization').item.json.platform_user_id ] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"57cc8561-a7ad-4b68-bb16-2f9d640e61c5","name":"IF_resend_otp","type":"n8n-nodes-base.if","position":[2720,1856],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"10e988ab-b186-4e6e-928a-20e5a00c7533","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ /^\\d{4,6}$/.test(($json.message || '').trim()) }}","rightValue":"true"}]}},"typeVersion":2.3},{"id":"5b96d50b-4395-4243-ab57-6a40cd2d3267","name":"Execute a SQL query3","type":"n8n-nodes-base.postgres","position":[1728,1248],"parameters":{"query":"SELECT global_user_id, email\nFROM users\nWHERE global_user_id = $1\nLIMIT 1;","options":{"queryReplacement":"={{ $json.global_user_id }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6,"alwaysOutputData":true},{"id":"a3eda303-0fd6-4507-b9a9-55846e0c0691","name":"Execute a SQL query5","type":"n8n-nodes-base.postgres","position":[3216,288],"parameters":{"query":"UPDATE onboarding_sessions\nSET email = $1,\n    step = 'waiting_for_otp'\nWHERE channel = $2\nAND platform_user_id = $3;","options":{"queryReplacement":"={{ [\n  $json.extracted_email,\n  $node[\"Universal normalization\"].json.channel,\n  $node[\"Universal normalization\"].json.platform_user_id\n] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"d5bfed53-4155-4210-8498-166d3de79e71","name":"If4","type":"n8n-nodes-base.if","position":[2688,832],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"f4260b1b-2e1d-470f-8d1d-b41751fe5a5d","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json.extracted_email }}","rightValue":""}]}},"typeVersion":2.3},{"id":"b1465b3c-179e-4d80-b811-9de62413e731","name":"IF_step- waiting_otp","type":"n8n-nodes-base.if","position":[2512,2144],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"9d29eb8f-66ea-4d49-a4ac-d012bcc7c52b","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.step }}","rightValue":"waiting_for_otp"}]}},"typeVersion":2.3},{"id":"924f50e9-8d46-4dd8-aeec-78a2fa213710","name":"If email en session","type":"n8n-nodes-base.if","position":[4336,2064],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"489b46e1-5e8c-4a34-b764-c9190d2ac4a7","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json.email }}","rightValue":""}]}},"typeVersion":2.3},{"id":"bf02cbaf-d67f-4038-a262-c0184606b8e5","name":"Upsert user_channel","type":"n8n-nodes-base.postgres","position":[4848,2048],"parameters":{"query":"INSERT INTO user_channels (global_user_id, channel, platform_user_id)\nVALUES ($1, $2, $3)\nON CONFLICT (channel, platform_user_id)\nDO UPDATE SET global_user_id = EXCLUDED.global_user_id\nRETURNING global_user_id, channel, platform_user_id;","options":{"queryReplacement":"={{ [ $json.global_user_id, $('Universal normalization').item.json.channel, $('Universal normalization').item.json.platform_user_id ] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"a1e122d2-e5c9-4298-9bc3-9858f5f7030e","name":"Universal normalization","type":"n8n-nodes-base.code","position":[944,1360],"parameters":{"jsCode":"// Tomamos el body real del webhook\nconst data = $json.body || {};\n\nlet channel = null;\nlet platform_user_id = null;\nlet message = null;\n\n// Caso Telegram (simulado simple)\nif (data.message) {\n  channel = \"telegram\";\n  platform_user_id = data.message.from?.id?.toString();\n  message = data.message.text;\n}\n\n// Caso WhatsApp (Meta Cloud API estructura real)\nelse if (data.entry) {\n  channel = \"whatsapp\";\n  platform_user_id = data.entry[0].changes[0].value.messages[0].from;\n  message = data.entry[0].changes[0].value.messages[0].text?.body;\n}\n\n// Caso Email simple\nelse if (data.from && data.subject) {\n  channel = \"email\";\n  platform_user_id = data.from;\n  message = data.text || data.body;\n}\n\n// Fallback\nelse {\n  channel = \"unknown\";\n  platform_user_id = \"unknown\";\n  message = JSON.stringify(data);\n}\n\nreturn [{\n  channel,\n  platform_user_id,\n  message\n}];"},"typeVersion":2},{"id":"4cd10c7d-62f7-4b15-9480-f6e7c6577c31","name":"Check if the channel already exists","type":"n8n-nodes-base.postgres","position":[1152,1360],"parameters":{"query":"SELECT global_user_id\nFROM user_channels\nWHERE channel = $1\nAND platform_user_id = $2;","options":{"queryReplacement":"={{ $json.channel }} {{ $json.platform_user_id }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6,"alwaysOutputData":true},{"id":"2c85064f-863e-407c-827c-14922c94bbf9","name":"Channel already verified","type":"n8n-nodes-base.set","position":[2000,1248],"parameters":{"options":{},"assignments":{"assignments":[{"id":"51e7da67-e385-4551-9558-a4d1ab99a67d","name":"response_message","type":"string","value":"={{ `✅ Channel already verified for ${$json.email}. Continuamos con tu perfil.` }}"}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"5211c7a7-472c-4da3-8cd1-06b766a18968","name":"Search onboarding_session","type":"n8n-nodes-base.postgres","position":[1984,1632],"parameters":{"query":"SELECT step, email\nFROM onboarding_sessions\nWHERE channel = $1\nAND platform_user_id = $2;","options":{"queryReplacement":"={{ [   $node[\"Universal normalization\"].json.channel,   $node[\"Universal normalization\"].json.platform_user_id ] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"fbb4941f-3b12-4871-8ab4-57db409d046a","name":"Extract email","type":"n8n-nodes-base.code","position":[2480,832],"parameters":{"jsCode":"const message = $node[\"Universal normalization\"].json.message;\n\n// Robust Regex to detect emails\nconst emailMatch = message\n  ? message.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/i)\n  : null;\n\nreturn [{\n  ...$json,\n  extracted_email: emailMatch ? emailMatch[0].toLowerCase() : null\n}];"},"typeVersion":2},{"id":"aba11586-756c-455d-a229-30ce2870366b","name":"Greeting 1 - send your email","type":"n8n-nodes-base.set","position":[2800,1008],"parameters":{"options":{},"assignments":{"assignments":[{"id":"90cba22b-1b98-4e69-9a8f-27db89359e74","name":"response_message","type":"string","value":"👋 Welcome to Zyntha ☕ To continue, I need your email address to create or verify your profile."}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"c8913fe3-9a74-49af-8bdf-94ba27ffb10d","name":"Generate OTP","type":"n8n-nodes-base.code","position":[3440,288],"parameters":{"jsCode":"const otp = Math.floor(100000 + Math.random() * 900000).toString();\n\nreturn [{\n  ...$json,\n  otp_code: otp,\n  otp_expires_at: new Date(Date.now() + 5 * 60 * 1000) // 5 minutos\n}];"},"typeVersion":2},{"id":"647aa9aa-aecc-4836-9e83-c3d5d8c968ea","name":"Save OTP","type":"n8n-nodes-base.postgres","position":[3616,288],"parameters":{"query":"INSERT INTO user_otps (channel, platform_user_id, otp_code, expires_at)\nVALUES ($1, $2, $3, $4);","options":{"queryReplacement":"={{ $node[\"Universal normalization\"].json.channel }}\n{{ $node[\"Universal normalization\"].json.platform_user_id }}\n{{ $json.otp_code }}\n{{ $json.otp_expires_at }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"2cf8c2a4-0f5c-438c-9aeb-fb4d061506f7","name":"response_message1 - verification code sent","type":"n8n-nodes-base.set","position":[4512,416],"parameters":{"options":{},"assignments":{"assignments":[{"id":"90cba22b-1b98-4e69-9a8f-27db89359e74","name":"response_message","type":"string","value":"I sent you a verification code. Enter it here to continue."}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"b1f87e35-0a19-4331-8d65-eb6d8eab28cd","name":"IF_code_exists?","type":"n8n-nodes-base.if","position":[3264,2080],"parameters":{"options":{},"conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"7acf0a8e-7ae4-4124-a27c-6ee01b140038","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json.id }}","rightValue":""}]}},"typeVersion":2.3},{"id":"f9f76032-3329-4e84-9abd-cc7a09da59a2","name":"code does not exist","type":"n8n-nodes-base.set","position":[3328,2464],"parameters":{"options":{},"assignments":{"assignments":[{"id":"90cba22b-1b98-4e69-9a8f-27db89359e74","name":"response_message","type":"string","value":"❌ Invalid code. Please try again with the correct code."}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"bcc811a6-d8ab-481e-9c1c-8fc92cb00d90","name":"valid OTP","type":"n8n-nodes-base.postgres","position":[3696,2064],"parameters":{"query":"UPDATE user_otps\nSET is_used = true\nWHERE id = $1;","options":{"queryReplacement":"={{ $('Execute a SQL query1').item.json.id }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"b9ef2797-fd43-4faf-bf9a-24eb24fd5c49","name":"Get verified session email","type":"n8n-nodes-base.postgres","position":[4112,2064],"parameters":{"query":"SELECT email\nFROM onboarding_sessions\nWHERE channel = $1\nAND platform_user_id = $2\nLIMIT 1;","options":{"queryReplacement":"={{ [ $('Universal normalization').item.json.channel, $('Universal normalization').item.json.platform_user_id ] }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6,"alwaysOutputData":true},{"id":"514fc91c-ad13-461a-b77e-07eb259bdb91","name":"Missing email response","type":"n8n-nodes-base.set","position":[4592,2400],"parameters":{"options":{},"assignments":{"assignments":[{"id":"7616b83a-63f1-41b4-a625-9db26036d52e","name":"response_message","type":"string","value":"⚠️ I couldn’t find the session email. Please send your email to continue."}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"fb6eb345-fe1b-4898-8b51-4b7a2ad43cf4","name":"Upsert user by email","type":"n8n-nodes-base.postgres","position":[4576,2048],"parameters":{"query":"INSERT INTO users (email, verified)\nVALUES ($1, true)\nON CONFLICT (email)\nDO UPDATE SET verified = true, updated_at = now()\nRETURNING global_user_id, email;","options":{"queryReplacement":"={{ $json.email }}"},"operation":"executeQuery"},"credentials":{"postgres":{"id":"credential-id","name":"Postgres account 2"}},"typeVersion":2.6},{"id":"8d44f896-f774-4853-a82d-ad5be67b13b0","name":"Verification completed response","type":"n8n-nodes-base.set","position":[5152,2048],"parameters":{"options":{},"assignments":{"assignments":[{"id":"7a0603f0-8c66-4e82-abcd-5c797a46301a","name":"response_message","type":"string","value":"✅ Verification completed. This channel has been linked to your user."}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"922a8ec9-3581-421e-973d-1209bfa0f4fb","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[96,1136],"parameters":{"width":544,"height":608,"content":"## Omnichannel OTP Verification & User Onboarding\n\n### How it works\nThis workflow centralizes user verification across WhatsApp, Telegram, and email using OTP validation.\n\nIt detects the channel, manages onboarding sessions, generates secure OTP codes, and links verified channels to a single global user identity.\n\n### How to set up\n1. Import the workflow into n8n.\n2. Configure Postgres or Supabase credentials.\n3. Download and create the required database tables (users, user_channels, user_otps, onboarding_sessions).\n4. Connect email and messaging channel credentials.\n5. Test with new and returning users.\n\n### Customization\n• Adjust OTP expiration time.\n• Modify onboarding steps or validation logic.\n• Add additional communication channels."},"typeVersion":1},{"id":"6c92564b-02cf-47a8-9881-4ce41dd45f2c","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[720,1152],"parameters":{"color":7,"width":752,"height":512,"content":"## Section 1 — Channel Detection & Normalization\n\nReceives incoming requests from multiple platforms and identifies the communication channel.\n\nNormalizes user data into a unified structure before checking if the channel is already linked."},"typeVersion":1},{"id":"55666d14-9851-4b68-b504-34c708dcc145","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1600,1024],"parameters":{"color":7,"width":672,"height":384,"content":"## Section 2 — Existing Channel Validation\n\n- Checks if the incoming channel is already associated with a verified user.\n\n- If found, skips the verification process and continues with the existing profile."},"typeVersion":1},{"id":"0c7ce79c-bc41-447b-a17c-f8e2434796a8","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1600,1472],"parameters":{"color":7,"width":624,"height":384,"content":"## Section 3 — Session Initialization\n\n- Creates or retrieves the onboarding session for the current channel.\n\n- Tracks the current step of the verification process."},"typeVersion":1},{"id":"0c099410-84a3-46c3-95a2-5671b2bc88f1","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[2304,576],"parameters":{"color":7,"width":704,"height":608,"content":"## Section 4 — Email Extraction & Validation\n\n- Extracts a valid email from the user message using regex detection.\n\n- If no email is found, prompts the user to provide one before continuing."},"typeVersion":1},{"id":"b8f1b027-e7b3-401d-86c9-45a26752a4cd","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[3152,64],"parameters":{"color":7,"width":1568,"height":576,"content":"## Section 5 — OTP Generation & Delivery\n\n- Generates a secure one-time password and stores it with an expiration timestamp.\n\n- Sends the OTP via email and updates the session to waiting_for_otp.\n\n- A confirmation message is sent to the email used for delivering the OTP."},"typeVersion":1},{"id":"37e80802-135a-419c-968c-23ed5c222b4e","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[2480,1648],"parameters":{"color":7,"width":1088,"height":1072,"content":"## Section 4 — Email Extraction & Validation\n\n- Extracts a valid email from the user message using regex detection.\n\n- If no email is found, prompts the user to provide one before continuing.\n\n- A message is sent to the user if the code does not exist, asking them to verify it and send it again."},"typeVersion":1},{"id":"3b112758-2051-4a1d-85b7-cd5ebf9210a8","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[3664,1728],"parameters":{"color":7,"width":1760,"height":976,"content":"## Section 7 — Identity Consolidation\n\n- Marks the OTP as used and updates the session as verified in the Supabase database.\n\n- Links the verified channel to a single global user ID to ensure omnichannel continuity.\n\n- A confirmation message is sent via email if the verification has been completed and successfully linked to the user."},"typeVersion":1},{"id":"fac105f0-454d-4905-8d2d-5322c67b897e","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[3792,2880],"parameters":{"color":3,"width":544,"height":272,"content":"## DATABASE REQUIRED\n\nThis workflow depends on predefined Postgres tables.\n\nYou must create users, user_channels, user_otps, and onboarding_sessions before running the flow."},"typeVersion":1},{"id":"5c4adad1-c940-427d-a7d5-1d3b6eba74e3","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[3408,-272],"parameters":{"color":3,"width":304,"height":208,"content":"## Security Notice\n- Do not log OTP codes in production environments.\n\n- Always define an expiration time and mark codes as used after validation."},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"02aace02-c27d-4c6b-bde2-d9df86bef1fc","connections":{"If":{"main":[[{"node":"Execute a SQL query3","type":"main","index":0}],[{"node":"Execute a SQL query","type":"main","index":0}]]},"If1":{"main":[[{"node":"Extract email","type":"main","index":0}],[{"node":"IF_step- waiting_otp","type":"main","index":0}]]},"If2":{"main":[[],[{"node":"response_message1 - verification code sent","type":"main","index":0}]]},"If4":{"main":[[{"node":"If2- extracted_email","type":"main","index":0}],[{"node":"Greeting 1 - send your email","type":"main","index":0}]]},"Webhook":{"main":[[{"node":"Universal normalization","type":"main","index":0}]]},"Save OTP":{"main":[[{"node":"Send email","type":"main","index":0}]]},"valid OTP":{"main":[[{"node":"Execute a SQL query2","type":"main","index":0}]]},"Send email":{"main":[[{"node":"waiting_for_otp","type":"main","index":0}]]},"Generate OTP":{"main":[[{"node":"Save OTP","type":"main","index":0}]]},"Extract email":{"main":[[{"node":"If4","type":"main","index":0}]]},"IF_resend_otp":{"main":[[],[{"node":"Execute a SQL query1","type":"main","index":0}]]},"IF_code_exists?":{"main":[[{"node":"valid OTP","type":"main","index":0}],[{"node":"code does not exist","type":"main","index":0}]]},"waiting_for_otp":{"main":[[{"node":"If2","type":"main","index":0}]]},"Execute a SQL query":{"main":[[{"node":"Search onboarding_session","type":"main","index":0}]]},"If email en session":{"main":[[{"node":"Upsert user by email","type":"main","index":0}],[{"node":"Missing email response","type":"main","index":0}]]},"Upsert user_channel":{"main":[[{"node":"Verification completed response","type":"main","index":0}]]},"Execute a SQL query1":{"main":[[{"node":"IF_code_exists?","type":"main","index":0}]]},"Execute a SQL query2":{"main":[[{"node":"Get verified session email","type":"main","index":0}]]},"Execute a SQL query3":{"main":[[{"node":"Channel already verified","type":"main","index":0}]]},"Execute a SQL query5":{"main":[[{"node":"Generate OTP","type":"main","index":0}]]},"IF_step- waiting_otp":{"main":[[{"node":"IF_resend_otp","type":"main","index":0}]]},"If2- extracted_email":{"main":[[{"node":"Execute a SQL query5","type":"main","index":0}]]},"Upsert user by email":{"main":[[{"node":"Upsert user_channel","type":"main","index":0}]]},"Universal normalization":{"main":[[{"node":"Check if the channel already exists","type":"main","index":0}]]},"Search onboarding_session":{"main":[[{"node":"If1","type":"main","index":0}]]},"Get verified session email":{"main":[[{"node":"If email en session","type":"main","index":0}]]},"Check if the channel already exists":{"main":[[{"node":"If","type":"main","index":0}]]}}},"lastUpdatedBy":29,"workflowInfo":{"nodeCount":45,"nodeTypes":{"n8n-nodes-base.if":{"count":9},"n8n-nodes-base.set":{"count":6},"n8n-nodes-base.code":{"count":3},"n8n-nodes-base.webhook":{"count":1},"n8n-nodes-base.postgres":{"count":13},"n8n-nodes-base.emailSend":{"count":1},"n8n-nodes-base.stickyNote":{"count":12}}},"status":"published","readyToDemo":null,"user":{"name":"Yenire","username":"yenire","bio":"Founder of Swiftline. Automation specialist building AI-powered workflows with n8n, focused on conversational agents with memory, real-time business context, and human-like interactions.","verified":false,"links":["https://www.linkedin.com/in/yenireeleal/"],"avatar":"https://gravatar.com/avatar/cb8e908dce26354bed9ef452c9dd10d5b706e7bfd9c8e66fad5ae3f4ce6cced7?r=pg&d=retro&size=200"},"nodes":[{"id":11,"icon":"fa:envelope","name":"n8n-nodes-base.emailSend","codex":{"data":{"alias":["SMTP","email","human","form","wait","hitl","approval"],"resources":{"generic":[{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/build-your-own-virtual-assistant-with-n8n-a-step-by-step-guide/","icon":"👦","label":"Build your own virtual assistant with n8n: A step by step guide"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.sendemail/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/sendemail/"}]},"categories":["Communication","HITL","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"HITL":["Human in the Loop"]}}},"group":"[\"output\"]","defaults":{"name":"Send Email","color":"#00bb88"},"iconData":{"icon":"envelope","type":"icon"},"displayName":"Send Email","typeVersion":2,"nodeCategories":[{"id":6,"name":"Communication"},{"id":9,"name":"Core Nodes"},{"id":28,"name":"HITL"}]},{"id":20,"icon":"fa:map-signs","name":"n8n-nodes-base.if","codex":{"data":{"alias":["Router","Filter","Condition","Logic","Boolean","Branch"],"details":"The IF node can be used to implement binary conditional logic in your workflow. You can set up one-to-many conditions to evaluate each item of data being inputted into the node. That data will either evaluate to TRUE or FALSE and route out of the node accordingly.\n\nThis node has multiple types of conditions: Bool, String, Number, and Date & Time.","resources":{"generic":[{"url":"https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/","icon":"🏭","label":"Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide"},{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/create-a-toxic-language-detector-for-telegram/","icon":"🤬","label":"Create a toxic language detector for Telegram in 4 step"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/","icon":"🔗","label":"How to build a low-code, self-hosted URL shortener in 3 steps"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/automation-for-maintainers-of-open-source-projects/","icon":"🏷️","label":"How to automatically manage contributions to open-source projects"},{"url":"https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/","icon":" 🕸️","label":"How uProc scraped a multi-page website with a low-code workflow"},{"url":"https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/","icon":"🤖","label":"5 workflow automations for Mattermost that we love at n8n"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/","icon":"🎡","label":"How to set up a no-code CI/CD pipeline with GitHub and TravisCI"},{"url":"https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/","icon":"🎖","label":"Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.if/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow"]}}},"group":"[\"transform\"]","defaults":{"name":"If","color":"#408000"},"iconData":{"icon":"map-signs","type":"icon"},"displayName":"If","typeVersion":2,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":30,"icon":"file:postgres.svg","name":"n8n-nodes-base.postgres","codex":{"data":{"resources":{"generic":[{"url":"https://n8n.io/blog/love-at-first-sight-ricardos-n8n-journey/","icon":"❤️","label":"Love at first sight: Ricardo’s n8n journey"},{"url":"https://n8n.io/blog/why-i-chose-n8n-over-zapier-in-2020/","icon":"😍","label":"Why I chose n8n over Zapier in 2020"},{"url":"https://n8n.io/blog/database-monitoring-and-alerting-with-n8n/","icon":"📡","label":"Database Monitoring and Alerting with n8n"},{"url":"https://n8n.io/blog/running-n8n-on-ships-an-interview-with-maranics/","icon":"🛳","label":"Running n8n on ships: An interview with Maranics"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-honest-burgers-use-automation-to-save-100k-per-year/","icon":"🍔","label":"How Honest Burgers Use Automation to Save $100k per year"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.postgres/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/postgres/"}]},"categories":["Development","Data & Storage"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\"]","defaults":{"name":"Postgres"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiB2aWV3Qm94PSIwIDAgNzkgODEiPjx1c2UgeGxpbms6aHJlZj0iI2EiIHg9Ii41IiB5PSIuNSIvPjxzeW1ib2wgaWQ9ImEiIG92ZXJmbG93PSJ2aXNpYmxlIj48ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZD0iTTc3LjM5MSA0Ny45MjJjLS40NjYtMS40MTItMS42ODgtMi4zOTYtMy4yNjgtMi42MzItLjc0NS0uMTExLTEuNTk4LS4wNjQtMi42MDguMTQ0LTEuNzYuMzYzLTMuMDY1LjUwMS00LjAxOC41MjggMy41OTYtNi4wNzIgNi41MjEtMTIuOTk3IDguMjA0LTE5LjUxNSAyLjcyMi0xMC41NCAxLjI2OC0xNS4zNDEtLjQzMi0xNy41MTNDNzAuNzcgMy4xODUgNjQuMjA2LjA5NyA1Ni4yODcuMDAyYy00LjIyNC0uMDUyLTcuOTMzLjc4Mi05Ljg2NyAxLjM4MmEzNyAzNyAwIDAgMC01Ljc3LS41MjhjLTMuODA5LS4wNjEtNy4xNzQuNzctMTAuMDUgMi40NzZhNDYgNDYgMCAwIDAtNy4wOTgtMS43ODJDMTYuNTYxLjQxMSAxMC45NjggMS4yOTkgNi44NzYgNC4xOSAxLjkyMiA3LjY4OS0uMzc1IDEzLjc3LjA1IDIyLjI2MmMuMTM1IDIuNjk2IDEuNjQzIDEwLjkgNC4wMTggMTguNjggMS4zNjUgNC40NzIgMi44MiA4LjE4NSA0LjMyNiAxMS4wMzggMi4xMzUgNC4wNDYgNC40MTkgNi40MjggNi45ODQgNy4yODQgMS40MzguNDc5IDQuMDQ5LjgxNCA2Ljc5Ny0xLjQ3M2E2IDYgMCAwIDAgMS40MjkgMS4yM2MuNzgzLjQ5NCAxLjc0Ljg5NyAyLjY5NiAxLjEzNiAzLjQ0Ni44NjIgNi42NzQuNjQ2IDkuNDI3LS41NjFsLjA0MSAxLjM2Mi4wNiAxLjg5OWMuMTYzIDQuMDY0LjQ0IDcuMjIzIDEuMjU5IDkuNDM0LjA0NS4xMjIuMTA1LjMwNy4xNjkuNTAzLjQwOSAxLjI1MSAxLjA5MiAzLjM0NiAyLjgzIDQuOTg3IDEuOCAxLjY5OSAzLjk3OCAyLjIyIDUuOTcyIDIuMjIgMSAwIDEuOTU1LS4xMzEgMi43OTItLjMxMSAyLjk4NC0uNjM5IDYuMzczLTEuNjE0IDguODI0LTUuMTA0IDIuMzE4LTMuMyAzLjQ0NC04LjI3IDMuNjQ4LTE2LjEwMWwuMDc0LS42MzQuMDQ4LS40MTQuNTQ2LjA0OC4xNDEuMDFjMy4wMzkuMTM4IDYuNzU1LS41MDYgOS4wMzctMS41NjYgMS44MDMtLjgzNyA3LjU4Mi0zLjg4OCA2LjIyMS04LjAwNyIvPjxwYXRoIGZpbGw9IiMzMzY3OTEiIGQ9Ik03Mi4xOTUgNDguNzIzYy05LjAzNiAxLjg2NC05LjY1Ny0xLjE5NS05LjY1Ny0xLjE5NSA5LjU0MS0xNC4xNTcgMTMuNTI5LTMyLjEyNyAxMC4wODctMzYuNTI1QzYzLjIzNS0uOTk0IDQ2Ljk4MSA0LjY4IDQ2LjcxIDQuODI3bC0uMDg3LjAxNmMtMS43ODUtLjM3MS0zLjc4My0uNTkxLTYuMDI5LS42MjgtNC4wODktLjA2Ny03LjE5IDEuMDcyLTkuNTQ0IDIuODU3IDAgMC0yOC45OTUtMTEuOTQ1LTI3LjY0NyAxNS4wMjMuMjg3IDUuNzM3IDguMjIzIDQzLjQxIDE3LjY4OSAzMi4wMzEgMy40Ni00LjE2MSA2LjgwMy03LjY3OSA2LjgwMy03LjY3OSAxLjY2IDEuMTAzIDMuNjQ4IDEuNjY2IDUuNzMyIDEuNDYzbC4xNjItLjEzN2E2LjMgNi4zIDAgMCAwIC4wNjUgMS42MmMtMi40MzkgMi43MjUtMS43MjIgMy4yMDMtNi41OTcgNC4yMDYtNC45MzMgMS4wMTctMi4wMzUgMi44MjYtLjE0MyAzLjI5OSAyLjI5NC41NzQgNy42IDEuMzg2IDExLjE4NS0zLjYzM2wtLjE0My41NzNjLjk1Ni43NjUgMS42MjYgNC45NzggMS41MTQgOC43OTdzLS4xODggNi40NDEuNTY1IDguNDg5IDEuNTAzIDYuNjU2IDcuOTEyIDUuMjgyYzUuMzU1LTEuMTQ4IDguMTMtNC4xMjEgOC41MTYtOS4wODEuMjc0LTMuNTI2Ljg5NC0zLjAwNS45MzMtNi4xNThsLjQ5Ny0xLjQ5M2MuNTczLTQuNzguMDkxLTYuMzIyIDMuMzktNS42MDVsLjgwMi4wN2MyLjQyOC4xMSA1LjYwNi0uMzkxIDcuNDcxLTEuMjU3IDQuMDE2LTEuODY0IDYuMzk4LTQuOTc2IDIuNDM4LTQuMTU4Ii8+PHBhdGggZD0iTTMyLjc0NyAyNC42NmMtLjgxNC0uMTEzLTEuNTUyLS4wMDgtMS45MjUuMjc0YS43LjcgMCAwIDAtLjI5Mi40N2MtLjA0Ny4zMzYuMTg4LjcwNy4zMzMuODk4LjQwOS41NDIgMS4wMDYuOTE1IDEuNTk4Ljk5N2EyIDIgMCAwIDAgLjI1Ni4wMThjLjk4NiAwIDEuODgzLS43NjggMS45NjItMS4zMzUuMDk5LS43MS0uOTMyLTEuMTgzLTEuOTMxLTEuMzIybTI2Ljk3NS4wMjJjLS4wNzgtLjU1Ni0xLjA2OC0uNzE1LTIuMDA3LS41ODRzLTEuODQ4LjU1NC0xLjc3MiAxLjExMmMuMDYxLjQzNC44NDQgMS4xNzQgMS43NzEgMS4xNzRxLjExNyAwIC4yMzctLjAxNmMuNjE5LS4wODYgMS4wNzMtLjQ3OSAxLjI4OC0uNzA1LjMyOS0uMzQ1LjUxOC0uNzMuNDg0LS45OG0xNS40NzcgMjMuODI4Yy0uMzQ1LTEuMDQyLTEuNDUzLTEuMzc3LTMuMjk2LS45OTctNS40NzEgMS4xMjktNy40My4zNDctOC4wNzMtLjEyNyA0LjI1Mi02LjQ3OCA3Ljc1LTE0LjMwOCA5LjYzNy0yMS42MTQuODk0LTMuNDYxIDEuMzg4LTYuNjc1IDEuNDI4LTkuMjk0LjA0NS0yLjg3Ni0uNDQ1LTQuOTg4LTEuNDU1LTYuMjc5LTQuMDcyLTUuMjAzLTEwLjA0OC03Ljk5NC0xNy4yODMtOC4wNy00Ljk3My0uMDU2LTkuMTc1IDEuMjE3LTkuOTkgMS41NzVhMjUgMjUgMCAwIDAtNS42MjItLjcyMmMtMy43MzQtLjA2LTYuOTYxLjgzNC05LjYzMyAyLjY1NWE0MyA0MyAwIDAgMC03LjgyOC0yLjA1MmMtNi4zNDItMS4wMjEtMTEuMzgxLS4yNDgtMTQuOTc4IDIuMy00LjI5MSAzLjA0LTYuMjcyIDguNDc1LTUuODg4IDE2LjE1Mi4xMjkgMi41ODMgMS42MDEgMTAuNTI5IDMuOTIzIDE4LjEzOSAzLjA1NyAxMC4wMTYgNi4zOCAxNS42ODYgOS44NzcgMTYuODUyYTQuNCA0LjQgMCAwIDAgMS40MDIuMjMyYzEuMjc2IDAgMi44MzktLjU3NSA0LjQ2Ni0yLjUzMWExNjEgMTYxIDAgMCAxIDYuMTU2LTYuOTY2IDkuOSA5LjkgMCAwIDAgNC40MjkgMS4xOTFsLjAxLjEyMWMtLjMxLjM2OC0uNTY0LjY5LS43ODEuOTY1LTEuMDcgMS4zNTgtMS4yOTMgMS42NDEtNC43MzggMi4zNTEtLjk4LjIwMi0zLjU4Mi43MzgtMy42MiAyLjU2My0uMDQxIDEuOTkzIDMuMDc2IDIuODMgMy40MzEgMi45MTkgMS4yMzguMzEgMi40My40NjMgMy41NjguNDYzIDIuNzY2IDAgNS4yLS45MDkgNy4xNDUtMi42NjgtLjA2IDcuMTA2LjIzNiAxNC4xMDcgMS4wODkgMTYuMjQxLjY5OSAxLjc0NiAyLjQwNiA2LjAxNCA3Ljc5OCA2LjAxNC43OTEgMCAxLjY2Mi0uMDkyIDIuNjItLjI5NyA1LjYyNy0xLjIwNyA4LjA3MS0zLjY5NCA5LjAxNi05LjE3Ny41MDYtMi45MyAxLjM3NC05LjkyOCAxLjc4Mi0xMy42ODIuODYyLjI2OSAxLjk3MS4zOTIgMy4xNy4zOTIgMi41MDEgMCA1LjM4Ny0uNTMxIDcuMTk3LTEuMzcyIDIuMDMzLS45NDQgNS43MDItMy4yNjEgNS4wMzctNS4yNzR6TTYxLjggMjMuMTQ3Yy0uMDE5IDEuMTA4LS4xNzEgMi4xMTQtLjMzMyAzLjE2NC0uMTc0IDEuMTI5LS4zNTQgMi4yOTctLjM5OSAzLjcxNS0uMDQ1IDEuMzc5LjEyOCAyLjgxNC4yOTQgNC4yLjMzNyAyLjgwMS42ODIgNS42ODUtLjY1NSA4LjUzMWExMSAxMSAwIDAgMS0uNTkyLTEuMjE4Yy0uMTY2LS40MDMtLjUyNy0xLjA1LTEuMDI3LTEuOTQ2LTEuOTQ0LTMuNDg3LTYuNDk3LTExLjY1Mi00LjE2Ny0xNC45ODQuNjk0LS45OTIgMi40NTYtMi4wMTEgNi44NzktMS40NjN6TTU2LjQzOSA0LjM3NGM2LjQ4Mi4xNDMgMTEuNjA5IDIuNTY4IDE1LjI0IDcuMjA3IDIuNzg0IDMuNTU4LS4yODIgMTkuNzQ5LTkuMTU4IDMzLjcxNmwtLjI2OS0uMzM5LS4xMTItLjE0YzIuMjk0LTMuNzg4IDEuODQ1LTcuNTM2IDEuNDQ2LTEwLjg1OS0uMTY0LTEuMzY0LS4zMTktMi42NTItLjI4LTMuODYxLjA0MS0xLjI4My4yMS0yLjM4Mi4zNzQtMy40NDYuMjAyLTEuMzExLjQwNy0yLjY2Ny4zNS00LjI2NWExLjggMS44IDAgMCAwIC4wMzctLjYwMWMtLjE0NC0xLjUzMy0xLjg5NC02LjEyLTUuNDYyLTEwLjI3My0xLjk1MS0yLjI3MS00Ljc5Ny00LjgxMy04LjY4Mi02LjUyN2EyOS4zIDI5LjMgMCAwIDEgNi41MTUtLjYxMnpNMjAuMTY3IDUzLjI5OGMtMS43OTMgMi4xNTUtMy4wMzEgMS43NDItMy40MzggMS42MDctMi42NTMtLjg4NS01LjczLTYuNDkxLTguNDQ0LTE1LjM4Mi0yLjM0OC03LjY5My0zLjcyLTE1LjQyOC0zLjgyOS0xNy41OTctLjM0My02Ljg2IDEuMzItMTEuNjQxIDQuOTQzLTE0LjIxIDUuODk2LTQuMTgxIDE1LjU4OS0xLjY3OSAxOS40ODQtLjQwOWwtLjE3LjE2M2MtNi4zOTEgNi40NTUtNi4yNCAxNy40ODMtNi4yMjQgMTguMTU3YTIyIDIyIDAgMCAwIC4wNTEgMS4xMzVjLjExIDEuODU1LjMxNSA1LjMwNy0uMjMyIDkuMjE3LS41MDggMy42MzMuNjEyIDcuMTg5IDMuMDcyIDkuNzU2cS4zODMuMzk4Ljc5NS43NWExNjQgMTY0IDAgMCAwLTYuMDA4IDYuODE0em02LjgzLTkuMTEzYy0xLjk4My0yLjA2OS0yLjg4NC00Ljk0Ny0yLjQ3MS03Ljg5Ni41NzctNC4xMy4zNjQtNy43MjcuMjUtOS42NTlsLS4wMzktLjY5NGMuOTM0LS44MjggNS4yNjEtMy4xNDYgOC4zNDYtMi40MzkgMS40MDguMzIzIDIuMjY2IDEuMjgxIDIuNjIzIDIuOTMxIDEuODQ2IDguNTM5LjI0NCAxMi4wOTgtMS4wNDMgMTQuOTU3LS4yNjUuNTg5LS41MTYgMS4xNDYtLjczIDEuNzIybC0uMTY2LjQ0NWMtLjQyIDEuMTI2LS44MTEgMi4xNzMtMS4wNTMgMy4xNjctMi4xMDgtLjAwNi00LjE1OS0uOTA3LTUuNzE4LTIuNTM0em0uMzI0IDExLjUxNmE1IDUgMCAwIDEtMS40OTQtLjY0MmMuMjcxLS4xMjguNzU0LS4zMDEgMS41OTEtLjQ3NCA0LjA1Mi0uODM0IDQuNjc4LTEuNDIzIDYuMDQ1LTMuMTU4LjMxMy0uMzk4LjY2OS0uODQ5IDEuMTYtMS4zOTguNzMzLS44MjEgMS4wNjgtLjY4MiAxLjY3Ni0uNDMuNDkzLjIwNC45NzIuODIxIDEuMTY3IDEuNTAxLjA5Mi4zMjEuMTk1LjkzLS4xNDMgMS40MDQtMi44NTUgMy45OTctNy4wMTUgMy45NDYtMTAuMDAzIDMuMTk4em0yMS4yMDcgMTkuNzM1Yy00Ljk1NyAxLjA2Mi02LjcxMy0xLjQ2Ny03Ljg2OS00LjM1OS0uNzQ3LTEuODY3LTEuMTEzLTEwLjI4NS0uODUzLTE5LjU4MmExLjEgMS4xIDAgMCAwLS4wNDgtLjM1NiA1IDUgMCAwIDAtLjEzOS0uNjU3Yy0uMzg3LTEuMzUzLTEuMzMxLTIuNDg0LTIuNDYyLTIuOTUzLS40NS0uMTg2LTEuMjc1LS41MjgtMi4yNjctLjI3NC4yMTItLjg3MS41NzgtMS44NTUuOTc2LTIuOTIxbC4xNjctLjQ0OGMuMTg4LS41MDUuNDIzLTEuMDI5LjY3My0xLjU4MyAxLjM0Ny0yLjk5MiAzLjE5Mi03LjA5MSAxLjE5LTE2LjM1LS43NS0zLjQ2OC0zLjI1NC01LjE2MS03LjA1LTQuNzY4LTIuMjc2LjIzNS00LjM1OCAxLjE1NC01LjM5NiAxLjY4cS0uMzM0LjE2OS0uNjE4LjMyOWMuMjktMy40OTQgMS4zODUtMTAuMDI0IDUuNDgxLTE0LjE1NiAyLjU3OS0yLjYwMSA2LjAxNC0zLjg4NiAxMC4xOTktMy44MTcgOC4yNDYuMTM1IDEzLjUzNCA0LjM2NyAxNi41MTggNy44OTMgMi41NzEgMy4wMzkgMy45NjQgNi4xIDQuNTIgNy43NTEtNC4xNzktLjQyNS03LjAyMi40LTguNDYzIDIuNDYtMy4xMzUgNC40ODEgMS43MTUgMTMuMTc4IDQuMDQ2IDE3LjM1OC40MjcuNzY2Ljc5NiAxLjQyOC45MTIgMS43MDkuNzU5IDEuODM5IDEuNzQyIDMuMDY3IDIuNDU5IDMuOTY0LjIyLjI3NS40MzMuNTQxLjU5Ni43NzQtMS4yNjYuMzY1LTMuNTM5IDEuMjA4LTMuMzMyIDUuNDIyLS4xNjcgMi4xMTUtMS4zNTYgMTIuMDE2LTEuOTU5IDE1LjUxNC0uNzk3IDQuNjIxLTIuNDk3IDYuMzQzLTcuMjc5IDcuMzY4em0yMC42OTMtMjMuNjhjLTEuMjk0LjYwMS0zLjQ2IDEuMDUyLTUuNTE4IDEuMTQ4LTIuMjczLjEwNy0zLjQzLS4yNTUtMy43MDItLjQ3Ny0uMTI4LTIuNjI2Ljg1LTIuOTAxIDEuODg0LTMuMTkxLjE2My0uMDQ2LjMyMS0uMDkuNDc0LS4xNDRhNCA0IDAgMCAwIC4zMTMuMjNjMS44MjcgMS4yMDYgNS4wODUgMS4zMzYgOS42ODUuMzg2bC4wNS0uMDFjLS42Mi41OC0xLjY4MiAxLjM1OS0zLjE4NyAyLjA1OHoiLz48L2c+PC9zeW1ib2w+PC9zdmc+"},"displayName":"Postgres","typeVersion":3,"nodeCategories":[{"id":3,"name":"Data & Storage"},{"id":5,"name":"Development"}]},{"id":38,"icon":"fa:pen","name":"n8n-nodes-base.set","codex":{"data":{"alias":["Set","JS","JSON","Filter","Transform","Map"],"resources":{"generic":[{"url":"https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/","icon":"🏭","label":"Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide"},{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/automatically-pulling-and-visualizing-data-with-n8n/","icon":"📈","label":"Automatically pulling and visualizing data with n8n"},{"url":"https://n8n.io/blog/database-monitoring-and-alerting-with-n8n/","icon":"📡","label":"Database Monitoring and Alerting with n8n"},{"url":"https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/","icon":"🧾","label":"Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/","icon":"🔗","label":"How to build a low-code, self-hosted URL shortener in 3 steps"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/","icon":" 🕸️","label":"How uProc scraped a multi-page website with a low-code workflow"},{"url":"https://n8n.io/blog/building-an-expense-tracking-app-in-10-minutes/","icon":"📱","label":"Building an expense tracking app in 10 minutes"},{"url":"https://n8n.io/blog/the-ultimate-guide-to-automate-your-video-collaboration-with-whereby-mattermost-and-n8n/","icon":"📹","label":"The ultimate guide to automate your video collaboration with Whereby, Mattermost, and n8n"},{"url":"https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/","icon":"🤖","label":"5 workflow automations for Mattermost that we love at n8n"},{"url":"https://n8n.io/blog/learn-to-build-powerful-api-endpoints-using-webhooks/","icon":"🧰","label":"Learn to Build Powerful API Endpoints Using Webhooks"},{"url":"https://n8n.io/blog/how-a-membership-development-manager-automates-his-work-and-investments/","icon":"📈","label":"How a Membership Development Manager automates his work and investments"},{"url":"https://n8n.io/blog/a-low-code-bitcoin-ticker-built-with-questdb-and-n8n-io/","icon":"📈","label":"A low-code bitcoin ticker built with QuestDB and n8n.io"},{"url":"https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/","icon":"🎡","label":"How to set up a no-code CI/CD pipeline with GitHub and TravisCI"},{"url":"https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/","icon":"🎖","label":"Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"},{"url":"https://n8n.io/blog/how-goomer-automated-their-operations-with-over-200-n8n-workflows/","icon":"🛵","label":"How Goomer automated their operations with over 200 n8n workflows"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.set/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Data Transformation"]}}},"group":"[\"input\"]","defaults":{"name":"Edit Fields"},"iconData":{"icon":"pen","type":"icon"},"displayName":"Edit Fields (Set)","typeVersion":3,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":47,"icon":"file:webhook.svg","name":"n8n-nodes-base.webhook","codex":{"data":{"alias":["HTTP","API","Build","WH"],"resources":{"generic":[{"url":"https://n8n.io/blog/learn-how-to-automatically-cross-post-your-content-with-n8n/","icon":"✍️","label":"Learn how to automatically cross-post your content with n8n"},{"url":"https://n8n.io/blog/running-n8n-on-ships-an-interview-with-maranics/","icon":"🛳","label":"Running n8n on ships: An interview with Maranics"},{"url":"https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/","icon":"🔗","label":"How to build a low-code, self-hosted URL shortener in 3 steps"},{"url":"https://n8n.io/blog/what-are-apis-how-to-use-them-with-no-code/","icon":" 🪢","label":"What are APIs and how to use them with no code"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/how-a-digital-strategist-uses-n8n-for-online-marketing/","icon":"💻","label":"How a digital strategist uses n8n for online marketing"},{"url":"https://n8n.io/blog/the-ultimate-guide-to-automate-your-video-collaboration-with-whereby-mattermost-and-n8n/","icon":"📹","label":"The ultimate guide to automate your video collaboration with Whereby, Mattermost, and n8n"},{"url":"https://n8n.io/blog/how-to-automatically-give-kudos-to-contributors-with-github-slack-and-n8n/","icon":"👏","label":"How to automatically give kudos to contributors with GitHub, Slack, and n8n"},{"url":"https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/","icon":"🤖","label":"5 workflow automations for Mattermost that we love at n8n"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/creating-custom-incident-response-workflows-with-n8n/","label":"How to automate every step of an incident response workflow"},{"url":"https://n8n.io/blog/learn-to-build-powerful-api-endpoints-using-webhooks/","icon":"🧰","label":"Learn to Build Powerful API Endpoints Using Webhooks"},{"url":"https://n8n.io/blog/learn-how-to-use-webhooks-with-mattermost-slash-commands/","icon":"🦄","label":"Learn how to use webhooks with Mattermost slash commands"},{"url":"https://n8n.io/blog/how-goomer-automated-their-operations-with-over-200-n8n-workflows/","icon":"🛵","label":"How Goomer automated their operations with over 200 n8n workflows"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"trigger\"]","defaults":{"name":"Webhook"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCI+PHBhdGggZmlsbD0iIzM3NDc0ZiIgZD0iTTM1IDM3Yy0yLjIgMC00LTEuOC00LTRzMS44LTQgNC00IDQgMS44IDQgNC0xLjggNC00IDQiLz48cGF0aCBmaWxsPSIjMzc0NzRmIiBkPSJNMzUgNDNjLTMgMC01LjktMS40LTcuOC0zLjdsMy4xLTIuNWMxLjEgMS40IDIuOSAyLjMgNC43IDIuMyAzLjMgMCA2LTIuNyA2LTZzLTIuNy02LTYtNmMtMSAwLTIgLjMtMi45LjdsLTEuNyAxTDIzLjMgMTZsMy41LTEuOSA1LjMgOS40YzEtLjMgMi0uNSAzLS41IDUuNSAwIDEwIDQuNSAxMCAxMFM0MC41IDQzIDM1IDQzIi8+PHBhdGggZmlsbD0iIzM3NDc0ZiIgZD0iTTE0IDQzQzguNSA0MyA0IDM4LjUgNCAzM2MwLTQuNiAzLjEtOC41IDcuNS05LjdsMSAzLjlDOS45IDI3LjkgOCAzMC4zIDggMzNjMCAzLjMgMi43IDYgNiA2czYtMi43IDYtNnYtMmgxNXY0SDIzLjhjLS45IDQuNi01IDgtOS44IDgiLz48cGF0aCBmaWxsPSIjZTkxZTYzIiBkPSJNMTQgMzdjLTIuMiAwLTQtMS44LTQtNHMxLjgtNCA0LTQgNCAxLjggNCA0LTEuOCA0LTQgNCIvPjxwYXRoIGZpbGw9IiMzNzQ3NGYiIGQ9Ik0yNSAxOWMtMi4yIDAtNC0xLjgtNC00czEuOC00IDQtNCA0IDEuOCA0IDQtMS44IDQtNCA0Ii8+PHBhdGggZmlsbD0iI2U5MWU2MyIgZD0ibTE1LjcgMzQtMy40LTIgNS45LTkuN2MtMi0xLjktMy4yLTQuNS0zLjItNy4zIDAtNS41IDQuNS0xMCAxMC0xMHMxMCA0LjUgMTAgMTBjMCAuOS0uMSAxLjctLjMgMi41bC0zLjktMWMuMS0uNS4yLTEgLjItMS41IDAtMy4zLTIuNy02LTYtNnMtNiAyLjctNiA2YzAgMi4xIDEuMSA0IDIuOSA1LjFsMS43IDF6Ii8+PC9zdmc+"},"displayName":"Webhook","typeVersion":2,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]},{"id":565,"icon":"fa:sticky-note","name":"n8n-nodes-base.stickyNote","codex":{"data":{"alias":["Comments","Notes","Sticky"],"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"input\"]","defaults":{"name":"Sticky Note","color":"#FFD233"},"iconData":{"icon":"sticky-note","type":"icon"},"displayName":"Sticky Note","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":834,"icon":"file:code.svg","name":"n8n-nodes-base.code","codex":{"data":{"alias":["cpde","Javascript","JS","Python","Script","Custom Code","Function"],"details":"The Code node allows you to execute JavaScript in your workflow.","resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Code"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTcxXzQ0MSkiPgo8cGF0aCBkPSJNMTcwLjI4MyA0OEgxOTYuNUMyMDMuMTI3IDQ4IDIwOC41IDQyLjYyNzQgMjA4LjUgMzZWMTJDMjA4LjUgNS4zNzI1OCAyMDMuMTI3IDAgMTk2LjUgMEgxNzAuMjgzQzEyNi4xIDAgOTAuMjgzIDM1LjgxNzIgOTAuMjgzIDgwVjE3NkM5MC4yODMgMjA2LjkyOCA2NS4yMTA5IDIzMiAzNC4yODMgMjMySDIzQzE2LjM3MjYgMjMyIDExIDIzNy4zNzIgMTEgMjQ0VjI2OEMxMSAyNzQuNjI3IDE2LjM3MjQgMjgwIDIyLjk5OTYgMjgwTDM0LjI4MyAyODBDNjUuMjEwOSAyODAgOTAuMjgzIDMwNS4wNzIgOTAuMjgzIDMzNlY0NDBDOTAuMjgzIDQ3OS43NjQgMTIyLjUxOCA1MTIgMTYyLjI4MyA1MTJIMTk2LjVDMjAzLjEyNyA1MTIgMjA4LjUgNTA2LjYyNyAyMDguNSA1MDBWNDc2QzIwOC41IDQ2OS4zNzMgMjAzLjEyNyA0NjQgMTk2LjUgNDY0SDE2Mi4yODNDMTQ5LjAyOCA0NjQgMTM4LjI4MyA0NTMuMjU1IDEzOC4yODMgNDQwVjMzNkMxMzguMjgzIDMwOS4wMjIgMTI4LjAxMSAyODQuNDQzIDExMS4xNjQgMjY1Ljk2MUMxMDYuMTA5IDI2MC40MTYgMTA2LjEwOSAyNTEuNTg0IDExMS4xNjQgMjQ2LjAzOUMxMjguMDExIDIyNy41NTcgMTM4LjI4MyAyMDIuOTc4IDEzOC4yODMgMTc2VjgwQzEzOC4yODMgNjIuMzI2OSAxNTIuNjEgNDggMTcwLjI4MyA0OFoiIGZpbGw9IiNGRjk5MjIiLz4KPHBhdGggZD0iTTMwNSAzNkMzMDUgNDIuNjI3NCAzMTAuMzczIDQ4IDMxNyA0OEgzNDIuOTc5QzM2MC42NTIgNDggMzc0Ljk3OCA2Mi4zMjY5IDM3NC45NzggODBWMTc2QzM3NC45NzggMjAyLjk3OCAzODUuMjUxIDIyNy41NTcgNDAyLjA5OCAyNDYuMDM5QzQwNy4xNTMgMjUxLjU4NCA0MDcuMTUzIDI2MC40MTYgNDAyLjA5OCAyNjUuOTYxQzM4NS4yNTEgMjg0LjQ0MyAzNzQuOTc4IDMwOS4wMjIgMzc0Ljk3OCAzMzZWNDMyQzM3NC45NzggNDQ5LjY3MyAzNjAuNjUyIDQ2NCAzNDIuOTc5IDQ2NEgzMTdDMzEwLjM3MyA0NjQgMzA1IDQ2OS4zNzMgMzA1IDQ3NlY1MDBDMzA1IDUwNi42MjcgMzEwLjM3MyA1MTIgMzE3IDUxMkgzNDIuOTc5QzM4Ny4xNjEgNTEyIDQyMi45NzggNDc2LjE4MyA0MjIuOTc4IDQzMlYzMzZDNDIyLjk3OCAzMDUuMDcyIDQ0OC4wNTEgMjgwIDQ3OC45NzkgMjgwSDQ5MEM0OTYuNjI3IDI4MCA1MDIgMjc0LjYyOCA1MDIgMjY4VjI0NEM1MDIgMjM3LjM3MyA0OTYuNjI4IDIzMiA0OTAgMjMyTDQ3OC45NzkgMjMyQzQ0OC4wNTEgMjMyIDQyMi45NzggMjA2LjkyOCA0MjIuOTc4IDE3NlY4MEM0MjIuOTc4IDM1LjgxNzIgMzg3LjE2MSAwIDM0Mi45NzkgMEgzMTdDMzEwLjM3MyAwIDMwNSA1LjM3MjU4IDMwNSAxMlYzNloiIGZpbGw9IiNGRjk5MjIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTcxXzQ0MSI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Code","typeVersion":2,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]}],"categories":[{"id":40,"name":"Support Chatbot"},{"id":47,"name":"AI Chatbot"}],"image":[]}}