{"workflow":{"id":13941,"name":"Mask PII in documents for GDPR-safe AI processing with Postgres and Claude","views":22,"recentViews":0,"totalViews":22,"createdAt":"2026-03-08T12:52:13.436Z","description":"## Overview\n\nThis workflow implements a **privacy-preserving AI document processing pipeline** that detects, masks, and securely manages Personally Identifiable Information (PII) before any AI processing occurs.\n\nOrganizations often need to analyze documents such as invoices, forms, contracts, or reports using AI. However, sending documents containing personal data directly to AI models can create serious **privacy, compliance, and security risks**.\n\nThis workflow solves that problem by automatically **detecting sensitive information**, replacing it with secure tokens, and storing the original values in a **protected vault database**.\n\nOnly the **masked version of the document** is sent to the AI model for analysis. If required, a controlled **PII re-injection mechanism** can restore original values after processing.\n\nThe workflow also records all operations in an **audit log**, making it suitable for environments requiring strong compliance such as **GDPR, financial services, healthcare, or enterprise document processing systems**.\n\n---\n\n## How It Works\n\n### 1. Document Upload\nA webhook receives a document (typically a PDF) and triggers the workflow.\n\n### 2. OCR Text Extraction\nThe **OCR Extract** node extracts the text content from the document so it can be analyzed for sensitive information.\n\n### 3. PII Detection\nMultiple detectors analyze the text to identify different types of sensitive data:\n\n- Email addresses (regex detection)\n- Phone numbers (multi-pattern detection)\n- Identification numbers such as PAN, SSN, or bank accounts\n- Physical addresses detected using an AI model\n\nEach detection includes:\n- detected value\n- location in the text\n- confidence score\n\n### 4. Detection Consolidation\nAll detected PII results are merged into a single dataset.  \nThe workflow resolves overlapping detections and removes duplicates to produce a clean list of sensitive values.\n\n### 5. Tokenization and Secure Vault Storage\nEach detected PII value is replaced with a secure token, for example:\n\n```\n&lt;&lt;EMAIL_7F3A&gt;&gt;\n&lt;&lt;PHONE_A12B&gt;&gt;\n```\n\nThe original values are securely stored in a **Postgres vault table**.\n\nThis ensures sensitive data is **never exposed to AI models**.\n\n### 6. Masked AI Processing\nThe masked document is sent to an AI model for structured analysis.\n\nPossible AI tasks include:\n\n- Document classification\n- Data extraction\n- Document summarization\n- Entity extraction\n\nSince all sensitive data has been tokenized, the AI processes the document **without seeing any real personal data**.\n\n### 7. Controlled PII Re-Injection\nAfter AI processing, the workflow can optionally restore original values from the vault.\n\nThe **Re-Injection Controller** determines which fields are allowed to restore PII based on defined permissions.\n\n### 8. Compliance Audit Logging\nAll events are recorded in an audit table, including:\n\n- PII detection\n- token generation\n- AI processing\n- PII restoration\n\nThis provides **traceability and compliance reporting**.\n\n---\n\n## Setup Instructions\n\n### 1. Configure Postgres Database\n\nCreate two tables in your database.\n\n#### PII Vault Table\n\nExample structure:\n\n```\ntoken\noriginal_value\ntype\ndocument_id\ncreated_at\n```\n\nThis table securely stores original PII values mapped to tokens.\n\n#### Audit Log Table\n\nExample structure:\n\n```\ndocument_id\npii_types_detected\ntoken_count\nai_access_confirmed\nre_injection_events\ntimestamp\nactor\n```\n\nThis table records workflow activity for compliance tracking.\n\n---\n\n### 2. Configure AI Model Credentials\n\nThis workflow supports multiple AI models:\n\n- Anthropic Claude (used for AI document processing)\n- Ollama local models (used for address detection)\n\nConfigure credentials in n8n before running the workflow.\n\n---\n\n### 3. Configure Webhook Trigger\n\nThe workflow starts when a document is sent to the webhook:\n\n```\nPOST /webhook/gdpr-document-upload\n```\n\nUpload a PDF file to this endpoint to trigger processing.\n\n---\n\n### 4. Configure Alert Notifications (Optional)\n\nReplace the placeholder alert webhook URL with your monitoring or alerting system.\n\nExample use cases:\n\n- Slack alert\n- monitoring system\n- incident notification\n\nAlerts are triggered if masking fails.\n\n---\n\n## Use Cases\n\nThis workflow is useful for many privacy-sensitive automation scenarios.\n\n### GDPR-Compliant Document Processing\nSafely process documents containing personal data without exposing PII to AI models.\n\n### AI-Powered Document Analysis\nUse AI to summarize or extract data from documents while maintaining privacy.\n\n### Enterprise Data Redaction Pipelines\nAutomatically detect and tokenize sensitive data before sending documents to downstream systems.\n\n### Financial Document Processing\nProcess invoices, contracts, and financial reports securely.\n\n### Healthcare Document Automation\nAnalyze patient documents while ensuring sensitive data is protected.\n\n---\n\n## Requirements\n\nTo run this workflow you need:\n\n- **n8n**\n- **Postgres database**\n- **Anthropic Claude API access**\n- **Ollama (optional for local AI address detection)**\n- **Webhook endpoint for document uploads**\n\nOptional integrations:\n\n- Monitoring or alert system\n- Compliance audit database\n\n---\n\n## Key Features\n\n- Automated **PII detection and tokenization**\n- **AI-safe document processing**\n- Secure **vault storage for sensitive data**\n- Controlled **PII restoration**\n- Full **audit logging**\n- Works with **multiple AI models**\n- Designed for **GDPR and enterprise compliance**\n\n---\n\n## Summary\n\nThis workflow creates a **secure bridge between sensitive documents and AI systems**.\n\nBy automatically detecting, masking, and securely storing personal data, it enables organizations to safely apply AI to document processing tasks without exposing sensitive information.\n\nThe combination of **tokenization, secure vault storage, controlled re-injection, and audit logging** makes this workflow suitable for privacy-sensitive industries and enterprise automation pipelines.","workflow":{"meta":{"instanceId":"48aac30adfc5487a33ef16e0e958096f27cef40df3ed0febcbe1ca199e789786"},"nodes":[{"id":"3510f22b-6743-4ee5-ac1a-59df62cf54d0","name":"Document Upload Webhook","type":"n8n-nodes-base.webhook","position":[-2528,432],"webhookId":"c1520de7-cbb8-4219-9b7f-94215dc5c899","parameters":{"path":"gdpr-document-upload","options":{"rawBody":true},"httpMethod":"POST","responseMode":"lastNode"},"typeVersion":2.1},{"id":"bbfef060-261b-451e-982a-36408aa5f722","name":"Workflow Configuration","type":"n8n-nodes-base.set","position":[-2320,432],"parameters":{"options":{},"assignments":{"assignments":[{"id":"id-1","name":"documentId","type":"string","value":"={{ $now.toISO() }}"},{"id":"id-2","name":"confidenceThreshold","type":"number","value":0.8},{"id":"id-3","name":"vaultTable","type":"string","value":"pii_vault"},{"id":"id-4","name":"auditTable","type":"string","value":"pii_audit_log"}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"723dec91-ad38-4a6f-9eae-8c34197b76e2","name":"OCR Extract Text","type":"n8n-nodes-base.extractFromFile","position":[-2128,432],"parameters":{"options":{"keepSource":"both"},"operation":"pdf"},"typeVersion":1.1},{"id":"570e62ce-852e-41b1-889c-1e3197343ecd","name":"Email Detector","type":"n8n-nodes-base.code","position":[-1728,144],"parameters":{"jsCode":"// Email Detector - Extract all email addresses from OCR text\nconst items = $input.all();\nconst results = [];\n\n// Email regex pattern with domain validation\nconst emailRegex = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/g;\n\nfor (const item of items) {\n  const text = item.json.text || '';\n  const detectedEmails = [];\n  \n  let match;\n  while ((match = emailRegex.exec(text)) !== null) {\n    detectedEmails.push({\n      value: match[0],\n      type: 'email',\n      start_pos: match.index,\n      end_pos: match.index + match[0].length,\n      confidence: 1.0\n    });\n  }\n  \n  results.push({\n    json: {\n      detections: detectedEmails,\n      detector: 'email',\n      original_text: text\n    }\n  });\n}\n\nreturn results;"},"typeVersion":2},{"id":"f62cc18d-7992-4efa-8d32-7f70d18ac8a5","name":"Phone Detector","type":"n8n-nodes-base.code","position":[-1728,336],"parameters":{"jsCode":"// Phone number detection with country-aware patterns\nconst items = $input.all();\nconst results = [];\n\n// Get the extracted text from OCR node\nfor (const item of items) {\n  const text = item.json.text || '';\n  \n  // Comprehensive phone number patterns for various countries\n  // Matches formats like: +1234567890, +1234567890, (555) 123-4567, etc.\n  const phonePatterns = [\n    // International format with country code\n    /\\+\\d{1,3}[\\s.-]?\\(?\\d{1,4}\\)?[\\s.-]?\\d{1,4}[\\s.-]?\\d{1,4}[\\s.-]?\\d{1,9}/g,\n    // US/Canada format with parentheses\n    /\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}/g,\n    // General format with separators\n    /\\d{3,4}[\\s.-]\\d{3,4}[\\s.-]\\d{3,4}/g\n  ];\n  \n  const detectedPhones = [];\n  const seenPhones = new Set();\n  \n  for (const pattern of phonePatterns) {\n    let match;\n    while ((match = pattern.exec(text)) !== null) {\n      const phoneValue = match[0];\n      \n      // Avoid duplicates\n      if (!seenPhones.has(phoneValue)) {\n        seenPhones.add(phoneValue);\n        \n        detectedPhones.push({\n          value: phoneValue,\n          type: 'phone',\n          start_pos: match.index,\n          end_pos: match.index + phoneValue.length,\n          confidence: 0.95\n        });\n      }\n    }\n  }\n  \n  // Return results for this item\n  if (detectedPhones.length > 0) {\n    results.push({\n      json: {\n        detected_pii: detectedPhones,\n        original_text: text,\n        detection_type: 'phone',\n        count: detectedPhones.length\n      }\n    });\n  }\n}\n\n// If no phones detected, return empty result\nif (results.length === 0) {\n  return [{\n    json: {\n      detected_pii: [],\n      detection_type: 'phone',\n      count: 0\n    }\n  }];\n}\n\nreturn results;"},"typeVersion":2},{"id":"1e01d3c6-92f3-43c5-b112-e1b710915ae3","name":"ID Number Detector","type":"n8n-nodes-base.code","position":[-1728,528],"parameters":{"jsCode":"// ID Number Detector - Detects SSN, PAN, License Numbers, Bank Account Numbers\n// Returns array of objects with value, type, start_pos, end_pos, confidence\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const text = item.json.extractedText || item.json.text || '';\n  const detections = [];\n  \n  // SSN Pattern (XXX-XX-XXXX or XXXXXXXXX)\n  const ssnPattern = /\\b(?:\\d{3}-\\d{2}-\\d{4}|\\d{9})\\b/g;\n  let match;\n  \n  while ((match = ssnPattern.exec(text)) !== null) {\n    const value = match[0];\n    // Basic validation: not all zeros, not sequential\n    const digits = value.replace(/-/g, '');\n    if (digits !== '+1234567890' && digits !== '123456789') {\n      detections.push({\n        value: value,\n        type: 'id_number',\n        subtype: 'ssn',\n        start_pos: match.index,\n        end_pos: match.index + value.length,\n        confidence: 0.9\n      });\n    }\n  }\n  \n  // PAN (Permanent Account Number - India) Pattern (AAAAA9999A)\n  const panPattern = /\\b[A-Z]{5}[0-9]{4}[A-Z]\\b/g;\n  \n  while ((match = panPattern.exec(text)) !== null) {\n    const value = match[0];\n    detections.push({\n      value: value,\n      type: 'id_number',\n      subtype: 'pan',\n      start_pos: match.index,\n      end_pos: match.index + value.length,\n      confidence: 0.9\n    });\n  }\n  \n  // Driver's License Pattern (varies by region, common formats)\n  // US format: 1-2 letters followed by 6-8 digits\n  const licensePattern = /\\b[A-Z]{1,2}[0-9]{6,8}\\b/g;\n  \n  while ((match = licensePattern.exec(text)) !== null) {\n    const value = match[0];\n    detections.push({\n      value: value,\n      type: 'id_number',\n      subtype: 'drivers_license',\n      start_pos: match.index,\n      end_pos: match.index + value.length,\n      confidence: 0.9\n    });\n  }\n  \n  // Bank Account Number Pattern (8-17 digits)\n  const bankAccountPattern = /\\b[0-9]{8,17}\\b/g;\n  \n  while ((match = bankAccountPattern.exec(text)) !== null) {\n    const value = match[0];\n    // Avoid false positives by checking it's not already detected as SSN\n    const isSSN = detections.some(d => d.subtype === 'ssn' && d.value.replace(/-/g, '') === value);\n    if (!isSSN) {\n      detections.push({\n        value: value,\n        type: 'id_number',\n        subtype: 'bank_account',\n        start_pos: match.index,\n        end_pos: match.index + value.length,\n        confidence: 0.9\n      });\n    }\n  }\n  \n  // IBAN Pattern (International Bank Account Number)\n  const ibanPattern = /\\b[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}\\b/g;\n  \n  while ((match = ibanPattern.exec(text)) !== null) {\n    const value = match[0];\n    detections.push({\n      value: value,\n      type: 'id_number',\n      subtype: 'iban',\n      start_pos: match.index,\n      end_pos: match.index + value.length,\n      confidence: 0.9\n    });\n  }\n  \n  results.push({\n    json: {\n      detections: detections,\n      originalText: text,\n      detectionCount: detections.length\n    }\n  });\n}\n\nreturn results;"},"typeVersion":2},{"id":"89110cc9-a2e8-4c9d-8b21-402061b83355","name":"Address Detector AI","type":"@n8n/n8n-nodes-langchain.agent","position":[-1808,848],"parameters":{"text":"={{ $json.text }}","options":{"systemMessage":"You are a PII detection specialist. Analyze the provided text and identify all physical addresses (street, city, state, postal code, country). Return each address found with its position in the text and a confidence score between 0 and 1."},"promptType":"define","hasOutputParser":true},"typeVersion":3},{"id":"3725829c-72a7-4f14-9e91-dc32234b9813","name":"Address Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[-1616,992],"parameters":{"schemaType":"manual","inputSchema":"{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"addresses\": {\n\t\t\t\"type\": \"array\",\n\t\t\t\"items\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"value\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"enum\": [\"address\"]\n\t\t\t\t\t},\n\t\t\t\t\t\"start_pos\": {\n\t\t\t\t\t\t\"type\": \"number\"\n\t\t\t\t\t},\n\t\t\t\t\t\"end_pos\": {\n\t\t\t\t\t\t\"type\": \"number\"\n\t\t\t\t\t},\n\t\t\t\t\t\"confidence\": {\n\t\t\t\t\t\t\"type\": \"number\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"required\": [\"value\", \"type\", \"start_pos\", \"end_pos\", \"confidence\"]\n\t\t\t}\n\t\t}\n\t},\n\t\"required\": [\"addresses\"]\n}"},"typeVersion":1.3},{"id":"0c9d02ad-87f3-43d9-9e24-e72cd97e180f","name":"Merge PII Detections","type":"n8n-nodes-base.merge","position":[-1440,240],"parameters":{"mode":"combine","options":{},"combineBy":"combineAll"},"typeVersion":3.2},{"id":"93b9bdf5-468b-40fa-b6ea-b7136216de88","name":"PII Consolidation & Conflict Resolver","type":"n8n-nodes-base.code","position":[-1216,240],"parameters":{"jsCode":"// PII Consolidation & Conflict Resolver\n// Merges all PII detections, resolves overlaps, deduplicates, and returns consolidated PII map\n\nconst allDetections = [];\n\n// Collect all PII detections from all input items\nfor (const item of $input.all()) {\n  if (item.json.detections && Array.isArray(item.json.detections)) {\n    allDetections.push(...item.json.detections);\n  }\n}\n\nconsole.log(`Total detections collected: ${allDetections.length}`);\n\n// Sort detections by start position for easier overlap detection\nallDetections.sort((a, b) => a.start - b.start);\n\n// Resolve overlaps: higher confidence wins, longer span preferred if confidence is equal\nconst resolvedDetections = [];\n\nfor (const detection of allDetections) {\n  let shouldAdd = true;\n  let indexToReplace = -1;\n  \n  for (let i = 0; i < resolvedDetections.length; i++) {\n    const existing = resolvedDetections[i];\n    \n    // Check for overlap\n    const hasOverlap = (\n      (detection.start >= existing.start && detection.start < existing.end) ||\n      (detection.end > existing.start && detection.end <= existing.end) ||\n      (detection.start <= existing.start && detection.end >= existing.end)\n    );\n    \n    if (hasOverlap) {\n      const detectionLength = detection.end - detection.start;\n      const existingLength = existing.end - existing.start;\n      \n      // Higher confidence wins\n      if (detection.confidence > existing.confidence) {\n        indexToReplace = i;\n        break;\n      } else if (detection.confidence === existing.confidence) {\n        // If confidence is equal, prefer longer span\n        if (detectionLength > existingLength) {\n          indexToReplace = i;\n          break;\n        } else {\n          shouldAdd = false;\n          break;\n        }\n      } else {\n        shouldAdd = false;\n        break;\n      }\n    }\n  }\n  \n  if (indexToReplace >= 0) {\n    resolvedDetections[indexToReplace] = detection;\n  } else if (shouldAdd) {\n    resolvedDetections.push(detection);\n  }\n}\n\nconsole.log(`Detections after overlap resolution: ${resolvedDetections.length}`);\n\n// Deduplicate exact matches (same type, value, and position)\nconst deduplicatedDetections = [];\nconst seen = new Set();\n\nfor (const detection of resolvedDetections) {\n  const key = `${detection.type}|${detection.value}|${detection.start}|${detection.end}`;\n  \n  if (!seen.has(key)) {\n    seen.add(key);\n    deduplicatedDetections.push(detection);\n  }\n}\n\nconsole.log(`Detections after deduplication: ${deduplicatedDetections.length}`);\n\n// Create consolidated PII map\nconst piiMap = deduplicatedDetections.map((detection, index) => ({\n  id: `pii_${index + 1}`,\n  type: detection.type,\n  value: detection.value,\n  start: detection.start,\n  end: detection.end,\n  confidence: detection.confidence,\n  source: detection.source || 'unknown'\n}));\n\n// Sort by start position for final output\npiiMap.sort((a, b) => a.start - b.start);\n\nreturn [\n  {\n    json: {\n      piiMap: piiMap,\n      totalDetections: piiMap.length,\n      originalText: $input.first().json.extractedText || $input.first().json.text || '',\n      timestamp: new Date().toISOString()\n    }\n  }\n];"},"typeVersion":2},{"id":"40678c14-67ad-461b-9043-bcb76a86cb08","name":"Tokenization & Vault Storage","type":"n8n-nodes-base.code","position":[-992,240],"parameters":{"jsCode":"// Tokenization & Vault Storage\n// Generates secure tokens for PII and prepares vault records\n\nconst items = $input.all();\nconst vaultRecords = [];\nconst tokenMap = {};\n\n// Helper function to generate random hash\nfunction generateHash(length = 4) {\n  const chars = '0123456789ABCDEF';\n  let hash = '';\n  for (let i = 0; i < length; i++) {\n    hash += chars.charAt(Math.floor(Math.random() * chars.length));\n  }\n  return hash;\n}\n\n// Process all PII items from consolidated data\nfor (const item of items) {\n  const piiData = item.json.consolidatedPII || [];\n  const originalText = item.json.originalText || '';\n  const documentId = item.json.documentId || item.json.document_id || 'unknown';\n  \n  for (const pii of piiData) {\n    const type = pii.type.toUpperCase();\n    const originalValue = pii.value;\n    const hash = generateHash(4);\n    const token = `<<${type}_${hash}>>`;\n    \n    // Create vault record\n    vaultRecords.push({\n      token: token,\n      original_value: originalValue,\n      type: type,\n      document_id: documentId,\n      created_at: new Date().toISOString()\n    });\n    \n    // Store token mapping for text replacement\n    tokenMap[originalValue] = token;\n  }\n}\n\n// Generate masked text by replacing all PII with tokens\nlet maskedText = items[0]?.json?.originalText || '';\nfor (const [originalValue, token] of Object.entries(tokenMap)) {\n  // Use global replace to handle multiple occurrences\n  const regex = new RegExp(originalValue.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g');\n  maskedText = maskedText.replace(regex, token);\n}\n\nreturn [{\n  json: {\n    vaultRecords: vaultRecords,\n    tokenMap: tokenMap,\n    maskedText: maskedText,\n    documentId: items[0]?.json?.documentId || items[0]?.json?.document_id || 'unknown',\n    originalText: items[0]?.json?.originalText || '',\n    totalTokensGenerated: vaultRecords.length\n  }\n}];"},"typeVersion":2},{"id":"4d8bd2f6-f05e-4de5-8111-184cc985217a","name":"Store Tokens in Vault","type":"n8n-nodes-base.postgres","position":[-800,240],"parameters":{"table":{"__rl":true,"mode":"name","value":"={{ $('Workflow Configuration').first().json.vaultTable }}"},"schema":{"__rl":true,"mode":"list","value":"public"},"columns":{"value":{"type":"={{ $json.type }}","token":"YOUR_CREDENTIAL_HERE","created_at":"={{ $json.created_at }}","document_id":"={{ $json.document_id }}","original_value":"={{ $json.original_value }}"},"mappingMode":"defineBelow"},"options":{}},"typeVersion":2.6},{"id":"7811a902-0f0d-40a2-81c8-351d768f0ed1","name":"Generate Masked Text","type":"n8n-nodes-base.code","position":[-560,240],"parameters":{"jsCode":"// Generate Masked Text - Replace PII with tokens\nconst items = $input.all();\n\nif (items.length === 0) {\n  return [{\n    json: {\n      masked_text: '',\n      token_count: 0,\n      masking_success: false,\n      error: 'No input items'\n    }\n  }];\n}\n\n// Get the original text from OCR Extract Text node\nconst ocrData = $('OCR Extract Text').first().json;\nlet originalText = ocrData.text || '';\n\n// Get the tokenized PII data from Store Tokens in Vault node\nconst vaultData = $('Store Tokens in Vault').all();\n\nif (!vaultData || vaultData.length === 0) {\n  return [{\n    json: {\n      masked_text: originalText,\n      token_count: 0,\n      masking_success: false,\n      error: 'No tokenized data available'\n    }\n  }];\n}\n\nlet maskedText = originalText;\nlet tokenCount = 0;\nlet allReplacementsSucceeded = true;\nconst replacements = [];\n\n// Process each tokenized PII item\nfor (const item of vaultData) {\n  const piiData = item.json;\n  \n  if (piiData.original_value && piiData.token) {\n    const originalValue = piiData.original_value;\n    const token = piiData.token;\n    \n    // Check if the original value exists in the text\n    if (maskedText.includes(originalValue)) {\n      // Replace all occurrences of the original value with the token\n      const regex = new RegExp(originalValue.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g');\n      const beforeLength = maskedText.length;\n      maskedText = maskedText.replace(regex, token);\n      const afterLength = maskedText.length;\n      \n      // Count successful replacements\n      if (beforeLength !== afterLength || maskedText.includes(token)) {\n        tokenCount++;\n        replacements.push({\n          original: originalValue,\n          token: token,\n          type: piiData.pii_type || 'unknown',\n          replaced: true\n        });\n      } else {\n        allReplacementsSucceeded = false;\n        replacements.push({\n          original: originalValue,\n          token: token,\n          type: piiData.pii_type || 'unknown',\n          replaced: false\n        });\n      }\n    } else {\n      // Original value not found in text\n      allReplacementsSucceeded = false;\n      replacements.push({\n        original: originalValue,\n        token: token,\n        type: piiData.pii_type || 'unknown',\n        replaced: false,\n        reason: 'Value not found in text'\n      });\n    }\n  }\n}\n\n// Return the masked text with metadata\nreturn [{\n  json: {\n    masked_text: maskedText,\n    original_text: originalText,\n    token_count: tokenCount,\n    masking_success: allReplacementsSucceeded && tokenCount > 0,\n    replacements: replacements,\n    timestamp: new Date().toISOString()\n  }\n}];"},"typeVersion":2},{"id":"30e64592-f363-4ebe-9f37-2fd4d6a80218","name":"AI Processing (Masked Data)","type":"@n8n/n8n-nodes-langchain.agent","position":[-160,0],"parameters":{"text":"={{ $json.masked_text }}","options":{"systemMessage":"You are a document processing AI. Extract structured information from the provided document. IMPORTANT: You are working with masked data where PII has been replaced with tokens like <<EMAIL_7F3A>>. Process the document normally and preserve these tokens in your output exactly as they appear."},"promptType":"define","hasOutputParser":true},"typeVersion":3},{"id":"c7bf152b-79fe-417e-8d05-969ea2a47b6d","name":"AI Processing Model","type":"@n8n/n8n-nodes-langchain.lmChatAnthropic","position":[-192,160],"parameters":{"model":{"__rl":true,"mode":"list","value":"claude-sonnet-4-5-20250929","cachedResultName":"Claude Sonnet 4.5"},"options":{}},"typeVersion":1.3},{"id":"786dded9-24f5-47be-aece-b90469b04314","name":"AI Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[80,128],"parameters":{"schemaType":"manual","inputSchema":"{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"documentType\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"Type of document processed (e.g., invoice, contract, form)\"\n\t\t},\n\t\t\"summary\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"Brief summary of the document content\"\n\t\t},\n\t\t\"keyEntities\": {\n\t\t\t\"type\": \"array\",\n\t\t\t\"items\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"entityType\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"value\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"description\": \"Key entities extracted from the document\"\n\t\t},\n\t\t\"dates\": {\n\t\t\t\"type\": \"array\",\n\t\t\t\"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t},\n\t\t\t\"description\": \"Important dates found in the document\"\n\t\t},\n\t\t\"amounts\": {\n\t\t\t\"type\": \"array\",\n\t\t\t\"items\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"currency\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t},\n\t\t\t\t\t\"amount\": {\n\t\t\t\t\t\t\"type\": \"number\"\n\t\t\t\t\t},\n\t\t\t\t\t\"description\": {\n\t\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"description\": \"Monetary amounts found in the document\"\n\t\t},\n\t\t\"processedData\": {\n\t\t\t\"type\": \"object\",\n\t\t\t\"description\": \"Additional processed information specific to document type\"\n\t\t}\n\t},\n\t\"required\": [\"documentType\", \"summary\"]\n}"},"typeVersion":1.3},{"id":"6763634c-e71d-4f3b-8be2-b36d1210dd4c","name":"Re-Injection Controller","type":"n8n-nodes-base.code","position":[320,80],"parameters":{"jsCode":"// Re-Injection Controller\n// Analyzes AI output, identifies fields requiring PII restoration,\n// extracts tokens, and prepares re-injection request\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const aiOutput = item.json.aiOutput || item.json;\n  const fieldPermissions = item.json.fieldPermissions || {};\n  const tokensToRetrieve = [];\n  const reinjectionMap = {};\n  \n  // Define which fields should have PII restored based on permissions\n  // Fields marked as 'restore' or 'unmask' will have original PII restored\n  const fieldsToRestore = Object.keys(fieldPermissions).filter(\n    field => fieldPermissions[field] === 'restore' || fieldPermissions[field] === 'unmask'\n  );\n  \n  // Traverse AI output and identify token placeholders\n  function extractTokens(obj, path = '') {\n    for (const key in obj) {\n      const currentPath = path ? `${path}.${key}` : key;\n      const value = obj[key];\n      \n      if (typeof value === 'string') {\n        // Check if value contains token pattern (e.g., TOKEN_EMAIL_123, TOKEN_PHONE_456)\n        const tokenPattern = /TOKEN_([A-Z_]+)_([a-f0-9-]+)/g;\n        const matches = value.matchAll(tokenPattern);\n        \n        for (const match of matches) {\n          const fullToken = match[0];\n          const tokenType = match[1];\n          const tokenId = match[2];\n          \n          // Check if this field should be restored\n          const shouldRestore = fieldsToRestore.some(field => \n            currentPath.includes(field) || key === field\n          );\n          \n          if (shouldRestore) {\n            tokensToRetrieve.push({\n              token: fullToken,\n              tokenId: tokenId,\n              tokenType: tokenType,\n              field: currentPath,\n              originalValue: value\n            });\n            \n            if (!reinjectionMap[currentPath]) {\n              reinjectionMap[currentPath] = [];\n            }\n            reinjectionMap[currentPath].push(fullToken);\n          }\n        }\n      } else if (typeof value === 'object' && value !== null) {\n        extractTokens(value, currentPath);\n      }\n    }\n  }\n  \n  extractTokens(aiOutput);\n  \n  // Prepare output with re-injection instructions\n  results.push({\n    json: {\n      aiOutput: aiOutput,\n      tokensToRetrieve: tokensToRetrieve,\n      reinjectionMap: reinjectionMap,\n      fieldPermissions: fieldPermissions,\n      totalTokensFound: tokensToRetrieve.length,\n      fieldsToRestore: fieldsToRestore,\n      timestamp: new Date().toISOString(),\n      workflowExecutionId: $execution.id\n    }\n  });\n}\n\nreturn results;"},"typeVersion":2},{"id":"b07a8d69-9ff1-4b97-8a10-f682492b9a03","name":"Retrieve Original Values","type":"n8n-nodes-base.postgres","position":[672,80],"parameters":{"table":{"__rl":true,"mode":"name","value":"={{ $('Workflow Configuration').first().json.vaultTable }}"},"where":{"values":[{"value":"={{ $('Re-Injection Controller').item.json.token }}","column":"token"}]},"schema":{"__rl":true,"mode":"list","value":"public"},"options":{},"operation":"select","returnAll":true},"typeVersion":2.6},{"id":"ad95487c-c75a-4c60-bc59-113df00118d3","name":"Restore Original PII","type":"n8n-nodes-base.code","position":[864,80],"parameters":{"jsCode":"// Restore Original PII - Replace tokens with original values from vault\n// Only restore PII for explicitly allowed fields based on re-injection policy\n\nconst aiOutput = $input.first().json;\nconst vaultData = $('Retrieve Original Values').all();\n\n// Create a map of tokens to original values\nconst tokenMap = {};\nvaultData.forEach(item => {\n  const data = item.json;\n  tokenMap[data.token] = {\n    originalValue: data.original_value,\n    piiType: data.pii_type,\n    allowedForReinjection: data.allowed_for_reinjection\n  };\n});\n\n// Function to recursively restore PII in objects\nfunction restorePII(obj) {\n  if (typeof obj === 'string') {\n    // Check if string contains tokens (format: [TOKEN_xxxxx])\n    const tokenRegex = /\\[TOKEN_[A-Z0-9]+\\]/g;\n    return obj.replace(tokenRegex, (token) => {\n      const tokenData = tokenMap[token];\n      if (tokenData && tokenData.allowedForReinjection) {\n        return tokenData.originalValue;\n      }\n      // Keep token if not allowed for re-injection\n      return token;\n    });\n  } else if (Array.isArray(obj)) {\n    return obj.map(item => restorePII(item));\n  } else if (obj !== null && typeof obj === 'object') {\n    const restored = {};\n    for (const key in obj) {\n      restored[key] = restorePII(obj[key]);\n    }\n    return restored;\n  }\n  return obj;\n}\n\n// Restore PII in the AI output\nconst restoredOutput = restorePII(aiOutput);\n\n// Create audit trail\nconst restoredFields = [];\nfor (const token in tokenMap) {\n  if (tokenMap[token].allowedForReinjection) {\n    restoredFields.push({\n      token: token,\n      piiType: tokenMap[token].piiType\n    });\n  }\n}\n\nreturn [\n  {\n    json: {\n      finalOutput: restoredOutput,\n      restoredFields: restoredFields,\n      restorationTimestamp: new Date().toISOString(),\n      totalTokensRestored: restoredFields.length\n    }\n  }\n];"},"typeVersion":2},{"id":"b89c3f08-3277-4f3b-9089-1df0f2ee4edd","name":"Store Audit Log","type":"n8n-nodes-base.postgres","position":[1296,80],"parameters":{"table":{"__rl":true,"mode":"name","value":"={{ $('Workflow Configuration').first().json.auditTable }}"},"schema":{"__rl":true,"mode":"list","value":"public"},"columns":{"value":{"actor":"system","timestamp":"={{ $json.timestamp }}","document_id":"={{ $json.document_id }}","token_count":"={{ $json.token_count }}","pii_types_detected":"={{ $json.pii_types_detected }}","ai_access_confirmed":true,"re_injection_events":"={{ $json.re_injection_events }}"},"schema":[],"mappingMode":"defineBelow","matchingColumns":[]},"options":{}},"typeVersion":2.6},{"id":"c0acedc8-c86d-495a-93f2-06b9d23e763c","name":"Masking Success Check","type":"n8n-nodes-base.if","position":[-352,240],"parameters":{"options":{},"conditions":{"options":{"leftValue":"","caseSensitive":false,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"id-1","operator":{"type":"boolean","operation":"equals"},"leftValue":"={{ $('Generate Masked Text').item.json.masking_success }}","rightValue":"true"}]}},"typeVersion":2.3},{"id":"92d0e6fd-5fc3-4514-9b7e-242d0f0744c1","name":"Block AI Processing","type":"n8n-nodes-base.set","position":[-32,496],"parameters":{"options":{},"assignments":{"assignments":[{"id":"id-1","name":"error","type":"string","value":"Masking failed - AI processing blocked"},{"id":"id-2","name":"status","type":"string","value":"BLOCKED"},{"id":"id-3","name":"requires_manual_review","type":"boolean","value":true}]}},"typeVersion":3.4},{"id":"6b5a1df1-c718-47be-9e90-f5cfd63438a7","name":"Send Alert Notification","type":"n8n-nodes-base.httpRequest","position":[208,496],"parameters":{"url":"<__PLACEHOLDER_VALUE__Alert webhook or notification endpoint URL__>","method":"POST","options":{},"sendBody":true,"bodyParameters":{"parameters":[{"name":"error_details","value":"={{ $json.error_details }}"},{"name":"document_id","value":"={{ $json.document_id }}"},{"name":"timestamp","value":"={{ $now.toISO() }}"}]}},"typeVersion":4.3},{"id":"522979b9-1913-4023-9b69-4b4e77485c09","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-3216,224],"parameters":{"width":512,"height":528,"content":"## GDPR-Safe AI Document Processing\n\nThis workflow processes uploaded documents while protecting sensitive personal data. When a PDF is uploaded, OCR extracts the text and multiple detectors identify Personally Identifiable Information (PII) such as emails, phone numbers, ID numbers, and addresses.\n\nDetected PII is consolidated and replaced with secure tokens while the original values are stored in a Postgres vault. The AI model only processes the masked version of the document, ensuring sensitive information is never exposed.\n\nIf required, a controlled re-injection mechanism can restore original values from the vault. All masking, AI access, and restoration events are recorded in an audit log.\n\nSetup\n\nConfigure Postgres credentials.\n\nCreate pii_vault and pii_audit_log tables.\n\nConnect an AI model.\n\nSend documents to the webhook."},"typeVersion":1},{"id":"a7ff2577-87c2-4288-be8b-740f78424024","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-1840,-16],"parameters":{"color":7,"width":288,"height":736,"content":"## PII Detection Layer\n\nMultiple detectors scan the document to identify sensitive information such as emails, phone numbers, ID numbers, and physical addresses."},"typeVersion":1},{"id":"0b397b8d-bdc0-49e7-8283-c24a4de572b0","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-1008,48],"parameters":{"color":7,"width":352,"height":384,"content":"##Tokenization & Vault Storage\n\nEach detected PII value is replaced with a secure token such as:\n\n<<EMAIL_AB12>>\nThe original values are stored securely in a Postgres vault table."},"typeVersion":1},{"id":"b6fe8410-fcb8-4361-a6e7-7d05115523f6","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-2000,736],"parameters":{"color":7,"width":560,"height":368,"content":"## Address Detection (AI) local ollama\n\nAn AI model analyzes the OCR text to detect physical addresses that are harder to capture with regex patterns."},"typeVersion":1},{"id":"cc20d7c8-66ed-497e-9e73-3c4cf902b5bb","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-1504,96],"parameters":{"color":7,"width":224,"height":368,"content":"## Merge Detection Results\n\nAll detection outputs are merged into a single dataset."},"typeVersion":1},{"id":"078fd05b-a6ae-44e3-bbbb-938a61eb1722","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-2640,272],"parameters":{"color":7,"width":304,"height":368,"content":"## Document Upload\n\nA webhook receives uploaded documents.\nThis entry point triggers the workflow and passes the file to the OCR step for text extraction."},"typeVersion":1},{"id":"4299741e-35d4-4fce-965d-e32f1ebcb859","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-1264,48],"parameters":{"color":7,"height":400,"content":"## IResolve Overlapping Detections\n\nOverlapping or duplicate PII detections are resolved."},"typeVersion":1},{"id":"4c28716e-8aaf-4992-8c93-c8fbf7724cbb","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-2192,272],"parameters":{"color":7,"width":256,"height":352,"content":"## OCR Text Extraction\n\nExtracts text from uploaded PDF files."},"typeVersion":1},{"id":"1cfdffc2-3008-4cb9-9377-94fe2785925f","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[272,-176],"parameters":{"color":7,"width":336,"height":416,"content":"## PII Re-Injection Controller\n\nAnalyzes AI output to determine whether specific tokens should be replaced with original values.\n\nRestoration follows defined permissions to control where sensitive data can appear."},"typeVersion":1},{"id":"4b48d393-fa34-4c81-9835-d0ad8631646c","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[640,-176],"parameters":{"color":7,"width":432,"height":416,"content":"## Restore Original Values\n\nOriginal PII values are retrieved from the vault and restored only in approved fields.\n\nThis ensures controlled access to sensitive data."},"typeVersion":1},{"id":"ab011bb0-977f-43e9-877e-fb15d63c59be","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","position":[-128,272],"parameters":{"color":7,"width":496,"height":432,"content":"## IMasking Safety Check\n\nBefore AI processing, the workflow verifies that masking was successful.\n\nIf masking fails, AI processing is blocked to prevent accidental exposure of sensitive information."},"typeVersion":1},{"id":"f80f3a53-98a9-413e-92fc-e62b0f87d78b","name":"Sticky Note13","type":"n8n-nodes-base.stickyNote","position":[-256,-176],"parameters":{"color":7,"width":512,"height":416,"content":"## AI Processing (Masked Data)\n\nThe masked document is sent to an AI model for analysis.\n\nSince sensitive data is replaced with tokens, the AI can safely summarize or extract structured information."},"typeVersion":1},{"id":"506c70db-8cd2-4478-ae6a-a6b15b77a941","name":"Ollama Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOllama","position":[-1904,992],"parameters":{"options":{}},"typeVersion":1},{"id":"8e32d94c-dd17-4736-bc91-d8e78653d59e","name":"Sticky Note14","type":"n8n-nodes-base.stickyNote","position":[1200,-64],"parameters":{"color":7,"width":368,"height":304,"content":"## Compliance Audit Log\n\nAll detection, masking, AI access, and restoration events are recorded in a Postgres audit table.\n\nThis provides traceability and supports privacy compliance requirements."},"typeVersion":1}],"pinData":{},"connections":{"Email Detector":{"main":[[{"node":"Merge PII Detections","type":"main","index":0}]]},"Phone Detector":{"main":[[{"node":"Merge PII Detections","type":"main","index":1}]]},"AI Output Parser":{"ai_outputParser":[[{"node":"AI Processing (Masked Data)","type":"ai_outputParser","index":0}]]},"OCR Extract Text":{"main":[[{"node":"Email Detector","type":"main","index":0},{"node":"Phone Detector","type":"main","index":0},{"node":"ID Number Detector","type":"main","index":0},{"node":"Address Detector AI","type":"main","index":0}]]},"Ollama Chat Model":{"ai_languageModel":[[{"node":"Address Detector AI","type":"ai_languageModel","index":0}]]},"ID Number Detector":{"main":[[{"node":"Merge PII Detections","type":"main","index":0}]]},"AI Processing Model":{"ai_languageModel":[[{"node":"AI Processing (Masked Data)","type":"ai_languageModel","index":0}]]},"Address Detector AI":{"main":[[{"node":"Merge PII Detections","type":"main","index":1}]]},"Block AI Processing":{"main":[[{"node":"Send Alert Notification","type":"main","index":0}]]},"Generate Masked Text":{"main":[[{"node":"Masking Success Check","type":"main","index":0}]]},"Merge PII Detections":{"main":[[{"node":"PII Consolidation & Conflict Resolver","type":"main","index":0}]]},"Restore Original PII":{"main":[[{"node":"Store Audit Log","type":"main","index":0}]]},"Address Output Parser":{"ai_outputParser":[[{"node":"Address Detector AI","type":"ai_outputParser","index":0}]]},"Masking Success Check":{"main":[[{"node":"AI Processing (Masked Data)","type":"main","index":0}],[{"node":"Block AI Processing","type":"main","index":0}]]},"Store Tokens in Vault":{"main":[[{"node":"Generate Masked Text","type":"main","index":0}]]},"Workflow Configuration":{"main":[[{"node":"OCR Extract Text","type":"main","index":0}]]},"Document Upload Webhook":{"main":[[{"node":"Workflow Configuration","type":"main","index":0}]]},"Re-Injection Controller":{"main":[[{"node":"Retrieve Original Values","type":"main","index":0}]]},"Retrieve Original Values":{"main":[[{"node":"Restore Original PII","type":"main","index":0}]]},"AI Processing (Masked Data)":{"main":[[{"node":"Re-Injection Controller","type":"main","index":0}]]},"Tokenization & Vault Storage":{"main":[[{"node":"Store Tokens in Vault","type":"main","index":0}]]},"PII Consolidation & Conflict Resolver":{"main":[[{"node":"Tokenization & Vault Storage","type":"main","index":0}]]}}},"lastUpdatedBy":1,"workflowInfo":{"nodeCount":37,"nodeTypes":{"n8n-nodes-base.if":{"count":1},"n8n-nodes-base.set":{"count":2},"n8n-nodes-base.code":{"count":8},"n8n-nodes-base.merge":{"count":1},"n8n-nodes-base.webhook":{"count":1},"n8n-nodes-base.postgres":{"count":3},"n8n-nodes-base.stickyNote":{"count":13},"n8n-nodes-base.httpRequest":{"count":1},"@n8n/n8n-nodes-langchain.agent":{"count":2},"n8n-nodes-base.extractFromFile":{"count":1},"@n8n/n8n-nodes-langchain.lmChatOllama":{"count":1},"@n8n/n8n-nodes-langchain.lmChatAnthropic":{"count":1},"@n8n/n8n-nodes-langchain.outputParserStructured":{"count":2}}},"status":"published","readyToDemo":null,"user":{"name":"ResilNext","username":"rnair1996","bio":"","verified":true,"links":[""],"avatar":"https://gravatar.com/avatar/c20bc6c3bcdf260fac3c28c556a8db661ee93670037a3ceb857e047851f6f438?r=pg&d=retro&size=200"},"nodes":[{"id":19,"icon":"file:httprequest.svg","name":"n8n-nodes-base.httpRequest","codex":{"data":{"alias":["API","Request","URL","Build","cURL"],"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/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/automatically-pulling-and-visualizing-data-with-n8n/","icon":"📈","label":"Automatically pulling and visualizing data with n8n"},{"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/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/running-n8n-on-ships-an-interview-with-maranics/","icon":"🛳","label":"Running n8n on ships: An interview with Maranics"},{"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/world-poetry-day-workflow/","icon":"📜","label":"Celebrating World Poetry Day with a daily poem in Telegram"},{"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/automate-designs-with-bannerbear-and-n8n/","icon":"🎨","label":"Automate Designs with Bannerbear and n8n"},{"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/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/how-to-use-the-http-request-node-the-swiss-army-knife-for-workflow-automation/","icon":"🧰","label":"How to use the HTTP Request Node - The Swiss Army Knife for Workflow Automation"},{"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-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/automations-for-activists/","icon":"✨","label":"How Common Knowledge use workflow automation for activism"},{"url":"https://n8n.io/blog/creating-scheduled-text-affirmations-with-n8n/","icon":"🤟","label":"Creating scheduled text affirmations with n8n"},{"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.httprequest/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"output\"]","defaults":{"name":"HTTP Request","color":"#0004F5"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00MCAyMEM0MCA4Ljk1MzE0IDMxLjA0NjkgMCAyMCAwQzguOTUzMTQgMCAwIDguOTUzMTQgMCAyMEMwIDMxLjA0NjkgOC45NTMxNCA0MCAyMCA0MEMzMS4wNDY5IDQwIDQwIDMxLjA0NjkgNDAgMjBaTTIwIDM2Ljk0NThDMTguODg1MiAzNi45NDU4IDE3LjEzNzggMzUuOTY3IDE1LjQ5OTggMzIuNjk4NUMxNC43OTY0IDMxLjI5MTggMTQuMTk2MSAyOS41NDMxIDEzLjc1MjYgMjcuNjg0N0gyNi4xODk4QzI1LjgwNDUgMjkuNTQwMyAyNS4yMDQ0IDMxLjI5MDEgMjQuNTAwMiAzMi42OTg1QzIyLjg2MjIgMzUuOTY3IDIxLjExNDggMzYuOTQ1OCAyMCAzNi45NDU4Wk0xMi45MDY0IDIwQzEyLjkwNjQgMjEuNjA5NyAxMy4wMDg3IDIzLjE2NCAxMy4yMDAzIDI0LjYzMDVIMjYuNzk5N0MyNi45OTEzIDIzLjE2NCAyNy4wOTM2IDIxLjYwOTcgMjcuMDkzNiAyMEMyNy4wOTM2IDE4LjM5MDMgMjYuOTkxMyAxNi44MzYgMjYuNzk5NyAxNS4zNjk1SDEzLjIwMDNDMTMuMDA4NyAxNi44MzYgMTIuOTA2NCAxOC4zOTAzIDEyLjkwNjQgMjBaTTIwIDMuMDU0MTlDMjEuMTE0OSAzLjA1NDE5IDIyLjg2MjIgNC4wMzA3OCAyNC41MDAxIDcuMzAwMzlDMjUuMjA2NiA4LjcxNDA4IDI1LjgwNzIgMTAuNDA2NyAyNi4xOTIgMTIuMzE1M0gxMy43NTAxQzE0LjE5MzMgMTAuNDA0NyAxNC43OTQyIDguNzEyNTQgMTUuNDk5OCA3LjMwMDY0QzE3LjEzNzcgNC4wMzA4MyAxOC44ODUxIDMuMDU0MTkgMjAgMy4wNTQxOVpNMzAuMTQ3OCAyMEMzMC4xNDc4IDE4LjQwOTkgMzAuMDU0MyAxNi44NjE3IDI5LjgyMjcgMTUuMzY5NUgzNi4zMDQyQzM2LjcyNTIgMTYuODQyIDM2Ljk0NTggMTguMzk2NCAzNi45NDU4IDIwQzM2Ljk0NTggMjEuNjAzNiAzNi43MjUyIDIzLjE1OCAzNi4zMDQyIDI0LjYzMDVIMjkuODIyN0MzMC4wNTQzIDIzLjEzODMgMzAuMTQ3OCAyMS41OTAxIDMwLjE0NzggMjBaTTI2LjI3NjcgNC4yNTUxMkMyNy42MzY1IDYuMzYwMTkgMjguNzExIDkuMTMyIDI5LjM3NzQgMTIuMzE1M0gzNS4xMDQ2QzMzLjI1MTEgOC42NjggMzAuMTA3IDUuNzgzNDYgMjYuMjc2NyA0LjI1NTEyWk0xMC42MjI2IDEyLjMxNTNINC44OTI5M0M2Ljc1MTQ3IDguNjY3ODQgOS44OTM1MSA1Ljc4MzQxIDEzLjcyMzIgNC4yNTUxM0MxMi4zNjM1IDYuMzYwMjEgMTEuMjg5IDkuMTMyMDEgMTAuNjIyNiAxMi4zMTUzWk0zLjA1NDE5IDIwQzMuMDU0MTkgMjEuNjAzIDMuMjc3NDMgMjMuMTU3NSAzLjY5NDg0IDI0LjYzMDVIMTAuMTIxN0M5Ljk0NjE5IDIzLjE0MiA5Ljg1MjIyIDIxLjU5NDMgOS44NTIyMiAyMEM5Ljg1MjIyIDE4LjQwNTcgOS45NDYxOSAxNi44NTggMTAuMTIxNyAxNS4zNjk1SDMuNjk0ODRDMy4yNzc0MyAxNi44NDI1IDMuMDU0MTkgMTguMzk3IDMuMDU0MTkgMjBaTTI2LjI3NjYgMzUuNzQyN0MyNy42MzY1IDMzLjYzOTMgMjguNzExIDMwLjg2OCAyOS4zNzc0IDI3LjY4NDdIMzUuMTA0NkMzMy4yNTEgMzEuMzMyMiAzMC4xMDY4IDM0LjIxNzkgMjYuMjc2NiAzNS43NDI3Wk0xMy43MjM0IDM1Ljc0MjdDOS44OTM2OSAzNC4yMTc5IDYuNzUxNTUgMzEuMzMyNCA0Ljg5MjkzIDI3LjY4NDdIMTAuNjIyNkMxMS4yODkgMzAuODY4IDEyLjM2MzUgMzMuNjM5MyAxMy43MjM0IDM1Ljc0MjdaIiBmaWxsPSIjM0E0MkU5Ii8+Cjwvc3ZnPgo="},"displayName":"HTTP Request","typeVersion":4,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]},{"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":24,"icon":"file:merge.svg","name":"n8n-nodes-base.merge","codex":{"data":{"alias":["Join","Concatenate","Wait"],"resources":{"generic":[{"url":"https://n8n.io/blog/how-to-sync-data-between-two-systems/","icon":"🏬","label":"How to synchronize data between two systems (one-way vs. two-way sync"},{"url":"https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with n8n"},{"url":"https://n8n.io/blog/migrating-community-metrics-to-orbit-using-n8n/","icon":"📈","label":"Migrating Community Metrics to Orbit using 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"},{"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/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.merge/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Merge"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTc3XzUxOCkiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTAgNDhDMCAyMS40OTAzIDIxLjQ5MDMgMCA0OCAwSDExMkMxMzguNTEgMCAxNjAgMjEuNDkwMyAxNjAgNDhWNTZIMTk2LjI1MkMyNDAuNDM1IDU2IDI3Ni4yNTIgOTEuODE3MiAyNzYuMjUyIDEzNlYxOTJDMjc2LjI1MiAyMTQuMDkxIDI5NC4xNjEgMjMyIDMxNi4yNTIgMjMySDM1MlYyMjRDMzUyIDE5Ny40OSAzNzMuNDkgMTc2IDQwMCAxNzZINDY0QzQ5MC41MSAxNzYgNTEyIDE5Ny40OSA1MTIgMjI0VjI4OEM1MTIgMzE0LjUxIDQ5MC41MSAzMzYgNDY0IDMzNkg0MDBDMzczLjQ5IDMzNiAzNTIgMzE0LjUxIDM1MiAyODhWMjgwSDMxNi4yNTJDMjk0LjE2MSAyODAgMjc2LjI1MiAyOTcuOTA5IDI3Ni4yNTIgMzIwVjM3NkMyNzYuMjUyIDQyMC4xODMgMjQwLjQzNSA0NTYgMTk2LjI1MiA0NTZIMTYwVjQ2NEMxNjAgNDkwLjUxIDEzOC41MSA1MTIgMTEyIDUxMkg0OEMyMS40OTAzIDUxMiAwIDQ5MC41MSAwIDQ2NFY0MDBDMCAzNzMuNDkgMjEuNDkwMyAzNTIgNDggMzUySDExMkMxMzguNTEgMzUyIDE2MCAzNzMuNDkgMTYwIDQwMFY0MDhIMTk2LjI1MkMyMTMuOTI1IDQwOCAyMjguMjUyIDM5My42NzMgMjI4LjI1MiAzNzZWMzIwQzIyOC4yNTIgMjk0Ljc4NCAyMzguODU5IDI3Mi4wNDQgMjU1Ljg1MyAyNTZDMjM4Ljg1OSAyMzkuOTU2IDIyOC4yNTIgMjE3LjIxNiAyMjguMjUyIDE5MlYxMzZDMjI4LjI1MiAxMTguMzI3IDIxMy45MjUgMTA0IDE5Ni4yNTIgMTA0SDE2MFYxMTJDMTYwIDEzOC41MSAxMzguNTEgMTYwIDExMiAxNjBINDhDMjEuNDkwMyAxNjAgMCAxMzguNTEgMCAxMTJWNDhaTTEwNCA0OEMxMDguNDE4IDQ4IDExMiA1MS41ODE3IDExMiA1NlYxMDRDMTEyIDEwOC40MTggMTA4LjQxOCAxMTIgMTA0IDExMkg1NkM1MS41ODE3IDExMiA0OCAxMDguNDE4IDQ4IDEwNFY1NkM0OCA1MS41ODE3IDUxLjU4MTcgNDggNTYgNDhIMTA0Wk00NTYgMjI0QzQ2MC40MTggMjI0IDQ2NCAyMjcuNTgyIDQ2NCAyMzJWMjgwQzQ2NCAyODQuNDE4IDQ2MC40MTggMjg4IDQ1NiAyODhINDA4QzQwMy41ODIgMjg4IDQwMCAyODQuNDE4IDQwMCAyODBWMjMyQzQwMCAyMjcuNTgyIDQwMy41ODIgMjI0IDQwOCAyMjRINDU2Wk0xMTIgNDA4QzExMiA0MDMuNTgyIDEwOC40MTggNDAwIDEwNCA0MDBINTZDNTEuNTgxNyA0MDAgNDggNDAzLjU4MiA0OCA0MDhWNDU2QzQ4IDQ2MC40MTggNTEuNTgxNyA0NjQgNTYgNDY0SDEwNEMxMDguNDE4IDQ2NCAxMTIgNDYwLjQxOCAxMTIgNDU2VjQwOFoiIGZpbGw9IiM1NEI4QzkiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTc3XzUxOCI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Merge","typeVersion":3,"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"}]},{"id":1119,"icon":"fa:robot","name":"@n8n/n8n-nodes-langchain.agent","codex":{"data":{"alias":["LangChain","Chat","Conversational","Plan and Execute","ReAct","Tools"],"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Agents","Root Nodes"]}}},"group":"[\"transform\"]","defaults":{"name":"AI Agent","color":"#404040"},"iconData":{"icon":"robot","type":"icon"},"displayName":"AI Agent","typeVersion":3,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1145,"icon":"file:anthropic.svg","name":"@n8n/n8n-nodes-langchain.lmChatAnthropic","codex":{"data":{"alias":["claude","sonnet","opus"],"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatanthropic/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Language Models","Root Nodes"],"Language Models":["Chat Models (Recommended)"]}}},"group":"[\"transform\"]","defaults":{"name":"Anthropic Chat Model"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NiIgaGVpZ2h0PSIzMiIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzdEN0Q4NyIgZD0iTTMyLjczIDBoLTYuOTQ1TDM4LjQ1IDMyaDYuOTQ1ek0xMi42NjUgMCAwIDMyaDcuMDgybDIuNTktNi43MmgxMy4yNWwyLjU5IDYuNzJoNy4wODJMMTkuOTI5IDB6bS0uNzAyIDE5LjMzNyA0LjMzNC0xMS4yNDYgNC4zMzQgMTEuMjQ2eiIvPjwvc3ZnPg=="},"displayName":"Anthropic Chat Model","typeVersion":1,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1151,"icon":"file:ollama.svg","name":"@n8n/n8n-nodes-langchain.lmChatOllama","codex":{"data":{"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatollama/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Language Models","Root Nodes"],"Language Models":["Chat Models (Recommended)"]}}},"group":"[\"transform\"]","defaults":{"name":"Ollama Chat Model"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNDEuMzMzIiBoZWlnaHQ9IjM0MS4zMzMiIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDE4MSAyNTYiPjxnIGZpbGw9IiM3RDdEODciPjxwYXRoIGQ9Ik0zNy43IDE5LjVjLTUuMiAxLjgtOC4zIDQuOS0xMS43IDExLjYtNC41IDguOS02LjIgMTkuMi01LjggMzUuNWwuMyAxNC4yLTUuOCA2LjFjLTE0LjggMTUuNS0xOC41IDM4LjctOS4yIDU3LjRsMy40IDYuOS0yIDQuNGMtMy40IDguMi01IDE2LjQtNSAyNi4zIDAgMTAuOCAxLjggMTkgNS44IDI2LjJsMi42IDQuOC0yLjEgNC45Yy0xLjIgMi43LTIuNiA3LjEtMy4yIDkuOC0xLjQgNi4yLTEuNSAyMi4xLS4xIDI1LjcgMSAyLjYgMS40IDIuNyA3LjYgMi43IDcuMyAwIDcgLjQgNS4zLTguNi0xLjUtOC4yLjItMTguOCA0LjItMjYuNiAzLjctNyAzLjgtMTAuNC41LTE0LjgtNC43LTYuNC02LjgtMTMuNi02LjktMjQtLjEtMTAuMyAxLjQtMTYgNi42LTI2LjEgMy4xLTYuMSAyLjktOC43LTEtMTIuMi0xLjEtMS0zLjEtNC4yLTQuMy03LTEuOS00LjItMi40LTYuOS0yLjMtMTQuMiAwLTExLjQgMi41LTE4LjMgOS41LTI2IDctNy42IDE0LjItMTEgMjMuOS0xMS4yIDQuMSAwIDcuOC0uMiA4LjItLjIuNC0uMSAxLjctMi4yIDIuOS00LjcgMy01LjkgOS42LTExLjkgMTYuNy0xNS4yIDQuOS0yLjMgNy0yLjcgMTQuNy0yLjcgNy45IDAgOS43LjQgMTQuOSAyLjkgNi44IDMuMyAxMy4zIDkuNCAxNS45IDE0LjggMSAyIDIuMyA0LjEgMyA0LjUuNi40IDQuNi44IDguNy44IDYuNy4xIDguMy41IDE0IDMuNiAxMi4zIDYuOCAxOS4zIDE4LjcgMTkuMyAzMy40LjEgNi43LS40IDktMi43IDE0LjItMS42IDMuNS0zLjUgNi44LTQuMyA3LjUtMy40IDIuOC0zLjUgNS44LS41IDExLjcgNS4yIDEwLjEgNi43IDE1LjggNi42IDI2LjEtLjEgMTAuNC0yLjIgMTcuNi02LjkgMjQtMy4zIDQuNC0zLjIgNy44LjUgMTQuOCA0IDcuOCA1LjcgMTguNCA0LjIgMjYuNi0xLjcgOS0yIDguNiA1LjMgOC42IDYuMiAwIDYuNi0uMSA3LjYtMi43IDEuNC0zLjYgMS4zLTE5LjUtLjEtMjUuNy0uNi0yLjctMi03LjEtMy4yLTkuOGwtMi4xLTQuOSAyLjYtNC44YzcuNi0xMy45IDcuOS0zNS45LjYtNTIuOGwtMi00LjcgMi41LTQuNmM5LjktMTguMyA2LjQtNDMuOS04LjEtNTkuMWwtNS44LTYuMS4zLTE0LjJjLjQtMTYuNC0xLjMtMjYuNi01LjgtMzUuNy02LjQtMTIuNi0xNy4yLTE1LjktMjYuMy03LjktNS40IDQuNy05LjIgMTMuOC0xMi4zIDI5LjgtLjMgMS40LTEgMi4yLTEuNyAxLjgtMTguMi04LTI5LjctOC41LTQ0LjMtMi4xTDY1IDU0LjlsLS40LTIuMkM2MSAzNC4yIDU2LjEgMjQuMiA0OSAyMC41Yy00LjMtMi4xLTcuNC0yLjQtMTEuMy0xbTcuNyAxNi44YzQuMiA3LjEgOC4xIDMwLjEgNS43IDMzLjYtLjUuOC0zLjEgMS42LTUuOCAxLjgtMi42LjItNi4yLjgtOCAxLjNsLTMuMS44LS43LTQuOWMtLjgtNS45LjItMTcuMiAyLjItMjQuOEMzNy4xIDM4LjQgNDAuNSAzMiA0MiAzMmMuNSAwIDIgMS45IDMuNCA0LjNtOTYuNS0xYzQgNi41IDYuOSAyMy45IDUuNiAzMy42bC0uNyA0LjktMy4xLS44Yy0xLjgtLjUtNS40LTEuMS04LTEuMy0yLjctLjItNS4zLTEtNS44LTEuOC0xLjItMS43LS4zLTE0LjEgMS43LTIyLjkgMS41LTYuNCA1LjctMTUgNy40LTE1IC40IDAgMS44IDEuNSAyLjkgMy4zIi8+PHBhdGggZD0iTTc3LjggMTE5LjljLTcuMyAyLjQtMTEuNiA1LjEtMTYuNSAxMC40LTUuNSA2LTcuNiAxMi03LjEgMjAuMS41IDcuNiAzLjUgMTIuOSAxMC42IDE4LjMgNi4yIDQuNyAxMi43IDYuMyAyNS43IDYuMyAxNy4yIDAgMjUuOC0zLjYgMzIuOS0xMy44IDQuMi01LjkgNC44LTE1LjUgMS42LTIzLTIuOS02LjgtMTEuMS0xNC4zLTE4LjgtMTcuMy04LTMuMS0yMC43LTMuNi0yOC40LTFtMjUuNyAxMGMxNi4xIDcuMSAxOS40IDIzLjIgNi42IDMxLjgtNC45IDMuMy05LjQgNC4zLTE5LjYgNC4zcy0xNC43LTEtMTkuNi00LjNjLTE3LjgtMTItMy4yLTM1LjYgMjEuMS0zNC4zIDMuOS4yIDguNiAxLjIgMTEuNSAyLjUiLz48cGF0aCBkPSJNODMuOCAxNDAuMWMtMi41IDEuNC0yLjIgNC40LjcgNi43IDIgMS42IDIuNCAyLjYgMS45IDQuOS0uNyAzLjYgMS41IDUuOCA1LjEgNC45IDIuMS0uNSAyLjUtMS4yIDIuNS00LjYgMC0yLjkuNS00LjIgMi01IDIuNy0xLjUgMi43LTYuNiAwLTcuNS0xLS4zLTIuOC0uMS00IC41LTEuNC43LTIuNi44LTMuOSAwLTIuMy0xLjItMi4yLTEuMi00LjMuMW0tNDQuMS0xOC45Yy0uOS43LTIuMyAzLTMuMiA1LTIuMSA1LjMtLjEgMTAuMyA0LjcgMTEuNiA0LjMgMS4xIDYgLjYgOS4yLTIuNyA0LTQuMSA0LjMtOC4xIDEuMS0xMS45LTIuMS0yLjUtMy40LTMuMi02LjQtMy4yLTIgMC00LjUuNi01LjQgMS4ybTg5LjggMmMtMy4yIDMuOC0yLjkgNy44IDEuMSAxMS45IDMuMiAzLjMgNC45IDMuOCA5LjIgMi43IDQuOS0xLjMgNi44LTYuMiA0LjYtMTEuOC0xLjktNC43LTMuOC02LTguNy02LTIuNyAwLTQuMS43LTYuMiAzLjIiLz48L2c+PC9zdmc+"},"displayName":"Ollama Chat Model","typeVersion":1,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1179,"icon":"fa:code","name":"@n8n/n8n-nodes-langchain.outputParserStructured","codex":{"data":{"alias":["json","zod"],"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.outputparserstructured/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Output Parsers"]}}},"group":"[\"transform\"]","defaults":{"name":"Structured Output Parser"},"iconData":{"icon":"code","type":"icon"},"displayName":"Structured Output Parser","typeVersion":1,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1235,"icon":"file:extractFromFile.svg","name":"n8n-nodes-base.extractFromFile","codex":{"data":{"alias":["CSV","Spreadsheet","Excel","xls","xlsx","ods","tabular","decode","decoding","Move Binary Data","Binary","File","PDF","JSON","HTML","ICS","iCal","txt","Text","RTF","XML","64","Base64","Convert"],"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.extractfromfile/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Files","Data Transformation"]}}},"group":"[\"input\"]","defaults":{"name":"Extract from File"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuOTM3NSAyQzAuNDE5NzMzIDIgMCAyLjQxOTczIDAgMi45Mzc1VjM3LjMyMjFDMCAzNy44Mzk5IDAuNDE5NzMzIDM4LjI1OTYgMC45Mzc1IDM4LjI1OTZIMjYuMjE1NEMyNi43MzMyIDM4LjI1OTYgMjcuMTUyOSAzNy44Mzk5IDI3LjE1MjkgMzcuMzIyMUwyNy4xNTI5IDMwLjY3MTlMMTYuNzk2OSAzMC42NzE5QzE0Ljg5ODQgMzAuNjcxOSAxMy4zNTk0IDI5LjEzMjkgMTMuMzU5NCAyNy4yMzQ0VjI1LjM1OTRDMTMuMzU5NCAyMy40NjA5IDE0Ljg5ODQgMjEuOTIxOSAxNi43OTY5IDIxLjkyMTlIMjcuMTUyOUwyNy4xNTI5IDE1Ljc4MjFIMTQuMzA4M0MxMy43OTA2IDE1Ljc4MjEgMTMuMzcwOCAxNS4zNjI0IDEzLjM3MDggMTQuODQ0NlYySDAuOTM3NVoiIGZpbGw9IiMzNTNGNkUiLz4KPHBhdGggZD0iTTE2LjAyNzEgMkMxNS45NDA4IDIgMTUuODcwOCAyLjA2OTk2IDE1Ljg3MDggMi4xNTYyNVYxMi44MTM0QzE1Ljg3MDggMTMuMDcyMyAxNi4wODA3IDEzLjI4MjEgMTYuMzM5NiAxMy4yODIxSDI2Ljk5NjdDMjcuMDgzIDEzLjI4MjEgMjcuMTUyOSAxMy4yMTIyIDI3LjE1MjkgMTMuMTI1OUwyNy4xNTI5IDEyLjYxNzFDMjcuMTUyOSAxMi4zNjg4IDI3LjA1NDUgMTIuMTMwNyAyNi44NzkxIDExLjk1NUwxNy4yMjI1IDIuMjc1MzhDMTcuMDQ2NiAyLjA5OTA4IDE2LjgwNzkgMiAxNi41NTg4IDJIMTYuMDI3MVoiIGZpbGw9IiMzNTNGNkUiLz4KPHBhdGggZD0iTTI5Ljc2NDIgMzQuNjUwM0MyOS4wMzQgMzMuOTE2IDI5LjAzNzQgMzIuNzI4OCAyOS43NzE2IDMxLjk5ODZMMzMuNjE5NyAyOC4xNzE5TDE2Ljc5NjkgMjguMTcxOUMxNi4yNzkxIDI4LjE3MTkgMTUuODU5NCAyNy43NTIxIDE1Ljg1OTQgMjcuMjM0NFYyNS4zNTk0QzE1Ljg1OTQgMjQuODQxNiAxNi4yNzkxIDI0LjQyMTkgMTYuNzk2OSAyNC40MjE5TDMzLjU0MTIgMjQuNDIxOUwyOS43NzE2IDIwLjY3MzNDMjkuMDM3NCAxOS45NDMxIDI5LjAzNCAxOC43NTU5IDI5Ljc2NDIgMTguMDIxNkMzMC40OTQ0IDE3LjI4NzQgMzEuNjgxNiAxNy4yODQgMzIuNDE1OSAxOC4wMTQyTDM5LjQ0NzEgMjUuMDA2NEMzOS44MDEgMjUuMzU4MyA0MCAyNS44MzY4IDQwIDI2LjMzNTlDNDAgMjYuODM1IDM5LjgwMSAyNy4zMTM1IDM5LjQ0NzEgMjcuNjY1NUwzMi40MTU5IDM0LjY1NzZDMzEuNjgxNiAzNS4zODc4IDMwLjQ5NDQgMzUuMzg0NSAyOS43NjQyIDM0LjY1MDNaIiBmaWxsPSIjMzUzRjZFIi8+Cjwvc3ZnPgo="},"displayName":"Extract from File","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]}],"categories":[{"id":35,"name":"Document Extraction"},{"id":49,"name":"AI Summarization"}],"image":[]}}