{"workflow":{"id":13544,"name":"Archive HR and legal documents with UploadToURL, Google Drive and Airtable","views":582,"recentViews":2,"totalViews":582,"createdAt":"2026-02-20T10:52:57.915Z","description":"Eliminate the manual chaos of HR and legal document management. This workflow automates the transition from a raw document upload to a structured, audit-ready archive by combining **UploadToURL** for instant CDN hosting, **Google Drive** for long-term storage, and **Airtable** for status tracking and database management.\n\n## 🎯 What This Workflow Does\n\nTransforms loose document scans into a structured corporate filing system:\n\n1. **📝 Captures Legal Assets** - Receives signed contracts or IDs via mobile scan (binary) or remote URL.\n2. **🛡️ Duplicate Prevention** - Checks Airtable first to ensure a contract isn't already filed for that specific Employee ID.\n3. **☁️ Instant CDN Hosting** - **UploadToURL** hosts the document to provide a high-speed link for immediate HR review.\n4. **📁 Smart Folder Logic** - Automatically navigates or creates a structured Google Drive path: `HR/Contracts/{Year}/{Department}/{EmployeeName}/`.\n5. **🗃️ Database Synchronization** - Updates (or creates) an Airtable record to tick \"Contract Received,\" logging both the Drive URL and the CDN backup.\n6. **📧 Automated Confirmation** - Sends a professional HTML email to HR and the employee with access links and filing metadata.\n\n## ✨ Key Features\n\n- **UploadToURL Integration**: Provides a redundant, accessible CDN link stored alongside your primary Drive storage for total data reliability.\n- **Auto-Nomenclature**: Renames files using a strict audit-ready format: `{EmployeeID}_{LastName}_{Type}_{Date}.pdf`.\n- **Intelligent Folder Creation**: Never manually create a folder again; the workflow builds the entire hierarchy on the fly.\n- **Audit Trail Generation**: Captures \"Filed By,\" \"Filed At,\" and unique \"Upload IDs\" for every document.\n- **Conflict Handling**: Built-in `409 Conflict` logic prevents accidental overwrites or double-filing of critical legal papers.\n\n## 💼 Perfect For\n\n- **HR Teams**: Managing onboarding documents and employment contracts at scale.\n- **Legal Departments**: Archiving NDAs, vendor agreements, and compliance certifications.\n- **Small Businesses**: Moving away from \"loose files in folders\" to a searchable, automated database.\n- **Remote Teams**: Enabling employees to \"upload and forget\" their paperwork via a simple link.\n\n## 🔧 What You'll Need\n\n### Required Integrations\n- **[UploadToURL](https://uploadtourl.com)** - To host documents and provide public CDN backup links.\n- **n8n Community Node** - `n8n-nodes-uploadtourl` must be installed.\n- **Google Drive** - OAuth2 credentials for secure document storage.\n- **Airtable** - Personal Access Token to manage your employee/document database.\n- **Gmail / SMTP** - To send automated filing confirmations.\n\n### Configuration Variables\n- `GDRIVE_ROOT_FOLDER_ID`: The ID of your main HR folder in Google Drive.\n- `AIRTABLE_BASE_ID`: Your specific Airtable base for HR/Legal tracking.\n\n## 🚀 Quick Start\n\n1. **Import Template** - Copy the JSON and import it into your n8n workspace.\n2. **Install Node** - Ensure the **UploadToURL** community node is active.\n3. **Set Credentials** - Link your UploadToURL, Google Drive, Airtable, and Gmail accounts.\n4. **Define Variables** - Set your Root Folder ID and Airtable Base details in n8n variables.\n5. **Test the Pipeline** - Send a test `POST` with a sample PDF to the Webhook URL.\n6. **Activate** - Enable the workflow to begin hands-free archiving.\n\n## 🎨 Customization Options\n\n- **Expiration Alerts**: Add a node to calculate 1-year expiry dates and set an automated reminder in Slack.\n- **OCR Processing**: Integrate an OCR step to read the content of scans and verify names automatically.\n- **Watermarking**: Add a \"Confidential\" or \"Draft\" watermark to documents before they are uploaded to the CDN.\n- **Multi-Base Routing**: Route documents to different Airtable bases depending on the \"Department\" field.\n\n## 📈 Expected Results\n\n- **100% Consistency** in file naming and folder structures across the entire organization.\n- **Zero manual data entry**—employee records and checkboxes update automatically.\n- **Audit-ready in minutes**: Every file has a timestamped trail and redundant storage links.\n- **Instant Accessibility**: HR can view documents via the CDN link before Drive permissions even propagate.\n\n## 🏆 Use Cases\n\n### High-Growth Onboarding\nA startup hiring 20 people a month can automate all contract filings, ensuring the \"Contract Received\" flag is always accurate for payroll.\n\n### Compliance Audits\nWhen auditors ask for specific contracts, use the Airtable \"Structured Filename\" column to find and share the relevant Drive or CDN links in seconds.\n\n### Field Service Scans\nTechnicians in the field can upload signed site reports via a mobile app; the workflow handles the filing and notifies the office immediately.\n\n## 💡 Pro Tips\n\n- **Folder IDs**: You can find your `GDRIVE_ROOT_FOLDER_ID` by looking at the last string in the URL when you are inside that folder in your browser.\n- **Structured JSON**: Use the returned `auditTrail` object to build a log of all uploads in a separate \"Master Audit\" spreadsheet.\n- **Employee IDs**: If no ID is provided, the workflow generates a temporary one using a timestamp to ensure the archive never breaks.\n\n---\n\n**Ready to secure your document pipeline?** Import this template and connect **UploadToURL** to build a world-class archiving system in under 20 minutes.\n\n**Need help with Airtable field mapping?** The workflow includes detailed sticky notes explaining the exact field names required for the automation to run.","workflow":{"meta":{"instanceId":"277842713620d9f5554de3b1518b865a152c8c4db680008bd8aec536fc18b4a8","templateCredsSetupCompleted":true},"nodes":[{"id":"2b43c48f-48fd-449d-89d8-4350be2d3f4b","name":"📋 Overview","type":"n8n-nodes-base.stickyNote","position":[-384,-1248],"parameters":{"width":640,"height":1600,"content":"# 🗂️ Legal & Compliance Document Archiving\n\n**The problem this solves:**\nHR managers receive signed contracts via email, WhatsApp, or phone scans — then manually rename files, drag them into the right Drive folder, and tick a checkbox in their HR system. Files get lost, folders stay inconsistent, and audit trails are weak. This workflow automates the entire chain.\n\n---\n\n## ⚙️ How it works\n1. **Webhook** receives a document upload (binary scan or remote URL) + employee metadata\n2. **Validator** sanitises all inputs — normalises employee name, generates a structured filename with date stamp, resolves the correct Drive folder path\n3. **Upload to URL** instantly hosts the document and returns a clean public CDN link\n4. **Google Drive** uploads the file into a structured folder: `HR / Contracts / {Year} / {EmployeeName}/`  — creates the folder if it doesn't exist\n5. **Airtable** looks up the employee record, ticks `Contract Received`, logs the Drive URL, file name, and timestamp\n6. **Duplicate Check** flags if a contract for this employee already exists in Airtable\n7. **Notifier** sends a confirmation email to HR + the employee\n8. **Webhook Response** returns the full archiving summary\n\n---\n\n## 🔐 Required Credentials\n| Credential | Node |\n|---|---|\n| `UploadToURL API` | Upload to URL nodes |\n| `Google Drive OAuth2` | Drive folder + file upload |\n| `Airtable API` | Record lookup + update |\n| `Gmail / SMTP` | Confirmation email |\n\n---\n\n## 🔧 Setup Checklist\n- [ ] Install **Upload to URL** community node via npm\n- [ ] Set `UploadToURL API` credentials\n- [ ] Connect `Google Drive OAuth2` credentials\n- [ ] Set n8n variable `GDRIVE_ROOT_FOLDER_ID` to your HR root folder ID in Drive\n- [ ] Connect `Airtable API` token\n- [ ] Set n8n variable `AIRTABLE_BASE_ID` and `AIRTABLE_TABLE_NAME`\n- [ ] Connect `Gmail` or `SMTP` credentials for confirmation emails\n- [ ] Activate workflow and copy the webhook URL\n\n---\n\n## 📬 Example Webhook Payload\n```json\n{\n  \"fileUrl\": \"https://cdn.example.com/contract-signed.pdf\",\n  \"filename\": \"contract-signed.pdf\",\n  \"employeeName\": \"Sarah Johnson\",\n  \"employeeId\": \"EMP-0042\",\n  \"employeeEmail\": \"sarah.johnson@company.com\",\n  \"contractType\": \"Full-Time Employment\",\n  \"department\": \"Engineering\",\n  \"effectiveDate\": \"2025-03-01\",\n  \"notifyEmployee\": true\n}\n```\n\n> 💡 **Tip:** Send binary PDF via `multipart/form-data` with field name `file` to skip the `fileUrl` requirement."},"typeVersion":1},{"id":"56ea1858-57e2-40f4-8d80-de36f8fdd700","name":"Entry & Duplicate Check","type":"n8n-nodes-base.stickyNote","position":[608,-128],"parameters":{"color":7,"width":500,"height":502,"content":"## 🚪 Entry, Validation & Duplicate Check\n**Nodes:** Webhook → Validate & Enrich → Airtable Duplicate Check → IF Duplicate?\n\n- Accepts `POST` with employee metadata + either `fileUrl` or binary PDF/image\n- Normalises employee name (title-case, strips special chars), generates a structured filename: `{EmployeeID}_{LastName}_{ContractType}_{YYYY-MM-DD}.pdf`\n- Builds the full Drive folder path: `HR/Contracts/{Year}/{Department}/{EmployeeName}/`\n- **Duplicate check runs first** — searches Airtable for an existing record with `Contract Received = true` for this employee before uploading anything, saving API quota and preventing double-filing\n- IF branch halts the workflow and returns a `409 Conflict` if a contract already exists"},"typeVersion":1},{"id":"7adcde7a-ad34-4f2f-b26c-3e6deed5d9b6","name":"Upload Chain","type":"n8n-nodes-base.stickyNote","position":[1504,-208],"parameters":{"color":7,"width":500,"height":780,"content":"## ☁️ Upload to URL → Google Drive\n**Nodes:** Has Remote URL? → Upload to URL (×2) → Extract Doc URL → Get/Create Drive Folder → Upload to Drive\n\n- Native **Upload to URL** node hosts the file first — this gives us a stable CDN URL to store in Airtable regardless of Drive sharing settings\n- `Get/Create Drive Folder` checks if the employee's subfolder already exists under the year/department path; creates it if not — no manual folder management needed\n- Drive upload uses the structured filename and sets `mimeType` correctly for PDF vs image scans\n- Both the CDN URL (UploadToURL) and the Drive file ID are passed downstream for full redundancy"},"typeVersion":1},{"id":"c4495c99-6e3b-4753-a4ec-b8498d447661","name":"Airtable Update","type":"n8n-nodes-base.stickyNote","position":[3936,-192],"parameters":{"color":7,"width":500,"height":770,"content":"## 🗃️ Airtable Update\n**Nodes:** Airtable - Find Employee → Airtable - Update Record\n\n- `Find Employee` searches by `Employee ID` field first, falls back to name match\n- `Update Record` ticks `Contract Received` checkbox, writes `Contract URL` (Drive link), `CDN Backup URL` (UploadToURL link), `Contract Type`, `Effective Date`, `Filed By`, and `Filed At` timestamp\n- If no Airtable record is found, a **new record is created** automatically so no employee needs to be pre-entered\n- Both Drive URL and the raw UploadToURL CDN link are stored — providing a redundant access path for auditors"},"typeVersion":1},{"id":"fd814fd6-732a-407d-896f-c5953038a326","name":"Notification & Response","type":"n8n-nodes-base.stickyNote","position":[4480,-160],"parameters":{"color":7,"width":500,"height":728,"content":"## 📧 Notification & Response\n**Nodes:** Send Confirmation Email → Build Final Response → Respond to Webhook\n\n- Sends a confirmation email to the HR manager (always) and optionally to the employee if `notifyEmployee: true`\n- Email includes: Drive folder link, CDN backup URL, structured filename, contract type, effective date\n- `Build Final Response` normalises the full archiving summary: Drive file ID, folder path, Airtable record ID, both URLs, and a `auditTrail` object\n- Returns `201 Created` with the complete record — ready to pipe into a broader HRIS or compliance dashboard"},"typeVersion":1},{"id":"01cd1834-06a3-4431-bcac-56a665891e3a","name":"Error & Conflict Handling","type":"n8n-nodes-base.stickyNote","position":[1184,656],"parameters":{"color":7,"width":460,"height":415,"content":"## ⚠️ Error & Conflict Handling\n**Nodes:** Duplicate Response (409) → Error Handler → Error Response (400)\n\n- `409 Conflict` is returned immediately if a contract already exists for the employee — prevents accidental overwrites during re-submissions\n- General `Error Handler` catches all other upstream failures (Drive API errors, Airtable timeouts, upload failures) and returns a structured `400` with the error message\n- Connect any node's **error output** to the Error Handler node"},"typeVersion":1},{"id":"5891f4a4-2d75-4783-af17-f312874287ed","name":"Webhook - Receive Contract","type":"n8n-nodes-base.webhook","position":[688,240],"webhookId":"ff159c22-4f86-4413-bd25-794c155d7595","parameters":{"path":"hr-contract-archive","options":{"allowedOrigins":"*"},"httpMethod":"POST","responseMode":"responseNode"},"typeVersion":2},{"id":"05264ff6-76ae-4def-aba1-e88cf91e62c8","name":"Validate & Enrich Payload","type":"n8n-nodes-base.code","position":[912,240],"parameters":{"jsCode":"const body = $input.first().json.body || $input.first().json;\n\n// ── Required field guards ─────────────────────────────────────\nif (!body.employeeName || body.employeeName.trim() === '') {\n  throw new Error('Missing required field: employeeName');\n}\nif (!body.fileUrl && !body.filename) {\n  throw new Error('Provide either fileUrl (remote document) or filename (binary upload).');\n}\n\n// ── Name normalisation (Title Case, strip special chars) ──────\nconst normaliseName = (raw) => {\n  return raw\n    .trim()\n    .replace(/[^a-zA-Z\\s\\-']/g, '')\n    .replace(/\\s+/g, ' ')\n    .split(' ')\n    .map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n    .join(' ');\n};\nconst employeeName = normaliseName(body.employeeName);\nconst nameParts = employeeName.split(' ');\nconst lastName = nameParts[nameParts.length - 1];\nconst firstName = nameParts[0];\n\n// ── Employee ID ────────────────────────────────────────────────\nconst employeeId = (body.employeeId || '').toUpperCase().replace(/[^A-Z0-9\\-]/g, '') || `EMP-${Date.now()}`;\n\n// ── Contract type slug ────────────────────────────────────────\nconst contractType = body.contractType || 'Employment Contract';\nconst contractTypeSlug = contractType.replace(/\\s+/g, '-').replace(/[^a-zA-Z0-9\\-]/g, '').toUpperCase();\n\n// ── Date handling ─────────────────────────────────────────────\nconst effectiveDate = body.effectiveDate || new Date().toISOString().split('T')[0];\nconst filedAt = new Date().toISOString();\nconst yearFolder = effectiveDate.split('-')[0];\n\n// ── Filename — structured for audit trail ─────────────────────\nconst originalFilename = body.filename || body.fileUrl?.split('?')[0].split('/').pop() || 'document.pdf';\nconst ext = originalFilename.split('.').pop()?.toLowerCase() || 'pdf';\nconst allowedExts = ['pdf', 'jpg', 'jpeg', 'png', 'docx', 'tiff'];\nif (!allowedExts.includes(ext)) {\n  throw new Error(`File type .${ext} not allowed. Accepted: ${allowedExts.join(', ')}`);\n}\nconst structuredFilename = `${employeeId}_${lastName.toUpperCase()}_${contractTypeSlug}_${effectiveDate}.${ext}`;\n\n// ── MIME type map ─────────────────────────────────────────────\nconst mimeMap = {\n  pdf: 'application/pdf',\n  jpg: 'image/jpeg', jpeg: 'image/jpeg',\n  png: 'image/png',\n  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n  tiff: 'image/tiff'\n};\nconst mimeType = mimeMap[ext] || 'application/octet-stream';\n\n// ── Drive folder path ─────────────────────────────────────────\nconst department = body.department || 'General';\nconst driveFolderPath = `HR/Contracts/${yearFolder}/${department}/${employeeName}`;\n\nreturn [{\n  json: {\n    // Source\n    fileUrl: body.fileUrl || null,\n    originalFilename,\n    structuredFilename,\n    mimeType,\n    ext,\n    // Employee\n    employeeName,\n    firstName,\n    lastName,\n    employeeId,\n    employeeEmail: body.employeeEmail || '',\n    department,\n    // Contract\n    contractType,\n    contractTypeSlug,\n    effectiveDate,\n    // Drive\n    driveFolderPath,\n    yearFolder,\n    rootFolderId: $vars.GDRIVE_ROOT_FOLDER_ID || 'root',\n    // Flags\n    notifyEmployee: body.notifyEmployee !== false,\n    filedBy: body.filedBy || 'HR System',\n    filedAt\n  }\n}];"},"typeVersion":2},{"id":"aa8b3b42-5bc3-4a02-ba8f-5e2d85642f3c","name":"Airtable - Duplicate Check","type":"n8n-nodes-base.airtable","notes":"Searches for existing contract record before uploading. Prevents duplicate filings and saves Drive quota.","position":[1120,240],"parameters":{"base":{"__rl":true,"mode":"list","value":""},"table":{"__rl":true,"mode":"list","value":""},"options":{"fields":["Employee ID","Employee Name","Contract Received","Contract URL","Filed At"]},"operation":"search","filterByFormula":"=AND({Employee ID} = '{{ $json.employeeId }}', {Contract Received} = TRUE())"},"credentials":{"airtableTokenApi":{"id":"3t89Q5x8gm0hM0Tx","name":"Airtable Personal Access Token account"}},"typeVersion":2.1},{"id":"51a5a374-b4d9-45ab-8166-55dea3242ee4","name":"IF Duplicate Exists?","type":"n8n-nodes-base.if","position":[1344,240],"parameters":{"options":{},"conditions":{"options":{"caseSensitive":false,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"cond-duplicate","operator":{"type":"number","operation":"gt"},"leftValue":"={{ $json.records?.length ?? 0 }}","rightValue":0}]}},"typeVersion":2},{"id":"ec542ad4-017f-4e4a-a5c5-093374be5b1f","name":"Respond - 409 Duplicate","type":"n8n-nodes-base.respondToWebhook","position":[1552,128],"parameters":{"options":{"responseCode":409,"responseHeaders":{"entries":[{"name":"Content-Type","value":"application/json"}]}},"respondWith":"json","responseBody":"={\n  \"success\": false,\n  \"conflict\": true,\n  \"message\": \"A contract for employee {{ $('Validate & Enrich Payload').first().json.employeeName }} ({{ $('Validate & Enrich Payload').first().json.employeeId }}) is already filed. Existing record: {{ $json.records[0].fields['Contract URL'] }}\",\n  \"existingContractUrl\": \"{{ $json.records[0].fields['Contract URL'] }}\",\n  \"filedAt\": \"{{ $json.records[0].fields['Filed At'] }}\"\n}"},"typeVersion":1.1},{"id":"adbf5a1e-f466-412e-92a5-f55ded178cf8","name":"Has Remote URL?","type":"n8n-nodes-base.if","position":[1552,352],"parameters":{"options":{},"conditions":{"options":{"caseSensitive":false,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"cond-fileurl","operator":{"type":"string","operation":"notEmpty"},"leftValue":"={{ $('Validate & Enrich Payload').first().json.fileUrl }}","rightValue":""}]}},"typeVersion":2},{"id":"2c1a9f2b-46a4-4491-8149-e8ff23b21881","name":"Upload to URL - Remote","type":"n8n-nodes-uploadtourl.uploadToUrl","position":[1760,224],"parameters":{"operation":"uploadFile"},"credentials":{"uploadToUrlApi":{"id":"aTtpEWKPdBd8vRfH","name":"Upload to URL account 3"}},"typeVersion":1},{"id":"7fbca76a-eda4-48b8-9c44-400214202fe4","name":"Upload to URL - Binary","type":"n8n-nodes-uploadtourl.uploadToUrl","position":[1760,464],"parameters":{"operation":"uploadFile"},"credentials":{"uploadToUrlApi":{"id":"aTtpEWKPdBd8vRfH","name":"Upload to URL account 3"}},"typeVersion":1},{"id":"334da8a8-b8b9-4c45-9a33-ab93f64a6ced","name":"Extract CDN URL","type":"n8n-nodes-base.code","position":[1984,352],"parameters":{"jsCode":"const uploadResp = $input.first().json;\nconst meta = $('Validate & Enrich Payload').first().json;\n\nconst cdnUrl =\n  uploadResp.url ||\n  uploadResp.link ||\n  uploadResp.data?.url ||\n  uploadResp.file?.url ||\n  uploadResp.shortUrl;\n\nif (!cdnUrl) {\n  throw new Error('Upload to URL returned no public URL. Response: ' + JSON.stringify(uploadResp));\n}\n\nreturn [{\n  json: {\n    ...meta,\n    cdnUrl: cdnUrl.replace(/^http:\\/\\//, 'https://'),\n    uploadId: uploadResp.id || uploadResp.data?.id || null,\n    fileSizeBytes: uploadResp.size || uploadResp.data?.size || null\n  }\n}];"},"typeVersion":2},{"id":"e82aac5b-6551-4415-9e87-288205dd1e68","name":"Drive - Find Employee Folder","type":"n8n-nodes-base.googleDrive","notes":"Searches for an existing employee subfolder. Result passed to the Create Folder or Use Existing branch.","position":[2208,240],"parameters":{"operation":"search"},"credentials":{"googleDriveOAuth2Api":{"id":"znjhGsCbPhwU2QLi","name":"PDFMunk - Jitesh"}},"typeVersion":3},{"id":"0ca63735-0c28-4ae3-a54c-dd0fe1dba37d","name":"Resolve Folder ID","type":"n8n-nodes-base.code","position":[2432,240],"parameters":{"jsCode":"// Decide whether to create a new folder or use the existing one\nconst searchResult = $input.first().json;\nconst meta = $('Extract CDN URL').first().json;\n\n// Google Drive search returns items array\nconst existingFolder = searchResult.files?.[0] || searchResult.items?.[0] || null;\nconst folderId = existingFolder?.id || null;\n\nreturn [{\n  json: {\n    ...meta,\n    existingFolderId: folderId,\n    needsNewFolder: !folderId\n  }\n}];"},"typeVersion":2},{"id":"61329861-d0c7-415b-99b4-4b7a1cca5b41","name":"Needs New Folder?","type":"n8n-nodes-base.if","position":[2640,240],"parameters":{"options":{},"conditions":{"options":{"caseSensitive":false,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"cond-newfolder","operator":{"type":"boolean","operation":"true"},"leftValue":"={{ $json.needsNewFolder }}","rightValue":true}]}},"typeVersion":2},{"id":"f82d1330-66de-4517-ac66-925df674384e","name":"Drive - Create Employee Folder","type":"n8n-nodes-base.googleDrive","notes":"Creates the employee subfolder under HR/Contracts/{Year}/{Department}/. Only runs if folder doesn't already exist.","position":[2864,128],"parameters":{"operation":"createFolder"},"credentials":{"googleDriveOAuth2Api":{"id":"znjhGsCbPhwU2QLi","name":"PDFMunk - Jitesh"}},"typeVersion":3},{"id":"cae0e67c-2fd0-4c8a-a3b8-0ddc5a455d7f","name":"Merge Folder ID","type":"n8n-nodes-base.code","position":[3088,240],"parameters":{"jsCode":"// Merge the folder ID from either path (new or existing)\nconst input = $input.first().json;\nconst meta = $('Resolve Folder ID').first().json;\n\n// If we just created a folder, the response has the new folder's id\nconst targetFolderId =\n  input.id ||               // newly created folder\n  meta.existingFolderId;    // pre-existing folder\n\nif (!targetFolderId) {\n  throw new Error('Could not resolve a Google Drive folder ID for upload.');\n}\n\nreturn [{\n  json: {\n    ...meta,\n    targetFolderId\n  }\n}];"},"typeVersion":2},{"id":"cf175356-ab80-4d3e-a24e-5ca30310f6c2","name":"Drive - Upload Document","type":"n8n-nodes-base.googleDrive","notes":"Uploads the document to the resolved employee folder using the structured filename. Sets correct MIME type for PDF vs image.","position":[3312,240],"parameters":{"name":"={{ $json.structuredFilename }}","driveId":{"__rl":true,"mode":"list","value":"MyDrive"},"options":{"ocrLanguage":""},"folderId":{"__rl":true,"mode":"id","value":"={{ $json.targetFolderId }}"}},"credentials":{"googleDriveOAuth2Api":{"id":"znjhGsCbPhwU2QLi","name":"PDFMunk - Jitesh"}},"typeVersion":3},{"id":"ce49884a-6f07-41a5-b1ff-4ff323160002","name":"Airtable - Find Employee Record","type":"n8n-nodes-base.airtable","position":[3520,240],"parameters":{"base":{"__rl":true,"mode":"list","value":""},"table":{"__rl":true,"mode":"list","value":""},"options":{"fields":["Employee ID","Employee Name","Department","Contract Received"]},"operation":"search","filterByFormula":"={Employee ID} = '{{ $('Merge Folder ID').first().json.employeeId }}'"},"credentials":{"airtableTokenApi":{"id":"3t89Q5x8gm0hM0Tx","name":"Airtable Personal Access Token account"}},"typeVersion":2.1},{"id":"9cca6163-dc9d-46ca-9531-fdfe6fc031fe","name":"Prepare Airtable Update","type":"n8n-nodes-base.code","position":[3744,240],"parameters":{"jsCode":"const airtableResp = $input.first().json;\nconst meta = $('Merge Folder ID').first().json;\nconst driveResp = $('Drive - Upload Document').first().json;\n\n// Build Drive shareable URL from file ID\nconst driveFileId = driveResp.id;\nconst driveUrl = driveFileId\n  ? `https://drive.google.com/file/d/${driveFileId}/view`\n  : null;\n\nconst existingRecord = airtableResp.records?.[0] || null;\n\nreturn [{\n  json: {\n    ...meta,\n    driveFileId,\n    driveUrl,\n    airtableRecordId: existingRecord?.id || null,\n    airtableRecordExists: !!existingRecord\n  }\n}];"},"typeVersion":2},{"id":"90abc179-346a-4a82-97e7-6c2bc7c9fdbc","name":"Airtable Record Exists?","type":"n8n-nodes-base.if","position":[3968,240],"parameters":{"options":{},"conditions":{"options":{"caseSensitive":false,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"cond-record-exists","operator":{"type":"boolean","operation":"true"},"leftValue":"={{ $json.airtableRecordExists }}","rightValue":true}]}},"typeVersion":2},{"id":"57d9299a-20e1-4075-b2d2-2d31f3102ca7","name":"Airtable - Update Existing Record","type":"n8n-nodes-base.airtable","notes":"Updates the existing employee record: ticks Contract Received, writes Drive URL, CDN backup URL, filename, effective date, and filing metadata.","position":[4192,128],"parameters":{"base":{"__rl":true,"mode":"list","value":""},"table":{"__rl":true,"mode":"list","value":""},"columns":{"value":{"Filed At":"={{ $json.filedAt }}","Filed By":"={{ $json.filedBy }}","Contract URL":"={{ $json.driveUrl }}","Contract Type":"={{ $json.contractType }}","CDN Backup URL":"={{ $json.cdnUrl }}","Effective Date":"={{ $json.effectiveDate }}","Contract Received":true,"Drive Folder Path":"={{ $json.driveFolderPath }}","Structured Filename":"={{ $json.structuredFilename }}"},"mappingMode":"defineBelow"},"options":{},"operation":"update"},"credentials":{"airtableTokenApi":{"id":"3t89Q5x8gm0hM0Tx","name":"Airtable Personal Access Token account"}},"typeVersion":2.1},{"id":"30b1753c-763c-4b50-9905-2756f6e85bba","name":"Airtable - Create New Record","type":"n8n-nodes-base.airtable","notes":"Creates a brand new Airtable record if the employee wasn't pre-entered. No manual Airtable setup needed before first use.","position":[4192,368],"parameters":{"base":{"__rl":true,"mode":"list","value":""},"table":{"__rl":true,"mode":"list","value":""},"columns":{"value":{"Filed At":"={{ $json.filedAt }}","Filed By":"={{ $json.filedBy }}","Department":"={{ $json.department }}","Employee ID":"={{ $json.employeeId }}","Contract URL":"={{ $json.driveUrl }}","Contract Type":"={{ $json.contractType }}","Employee Name":"={{ $json.employeeName }}","CDN Backup URL":"={{ $json.cdnUrl }}","Effective Date":"={{ $json.effectiveDate }}","Contract Received":true,"Drive Folder Path":"={{ $json.driveFolderPath }}","Structured Filename":"={{ $json.structuredFilename }}"},"mappingMode":"defineBelow"},"options":{},"operation":"create"},"credentials":{"airtableTokenApi":{"id":"3t89Q5x8gm0hM0Tx","name":"Airtable Personal Access Token account"}},"typeVersion":2.1},{"id":"c92fc87d-1dc2-423e-971e-3b3d6b548759","name":"Merge Airtable Result","type":"n8n-nodes-base.code","position":[4400,240],"parameters":{"jsCode":"// Normalise output from both Airtable branches\nconst airtableResp = $input.first().json;\nconst meta = $('Prepare Airtable Update').first().json;\n\nconst airtableRecordId = airtableResp.id || meta.airtableRecordId;\n\nreturn [{\n  json: {\n    ...meta,\n    airtableRecordId,\n    airtableUpdated: true\n  }\n}];"},"typeVersion":2},{"id":"c69bd238-b672-4de2-80e7-64548b2f1fba","name":"Send Confirmation Email","type":"n8n-nodes-base.gmail","notes":"Sends a formatted HTML confirmation to HR (always) and optionally to the employee. Includes Drive link, CDN backup, structured filename, and filing metadata.","position":[4624,240],"webhookId":"a95eb67c-d90a-44eb-b407-0dc4ee6c2e61","parameters":{"operation":"sendEmail"},"credentials":{"gmailOAuth2":{"id":"r1sEKiELINYOSRri","name":"jitesh0dugar@gmail.com"}},"typeVersion":2.1},{"id":"44c9e268-f8f9-4e76-93c1-f3e92324145f","name":"Build Final Response","type":"n8n-nodes-base.code","position":[4848,240],"parameters":{"jsCode":"const emailResp = $input.first().json;\nconst data = $('Merge Airtable Result').first().json;\n\nreturn [{\n  json: {\n    success: true,\n    message: `Contract for ${data.employeeName} successfully archived.`,\n    // Core identifiers\n    employeeId: data.employeeId,\n    employeeName: data.employeeName,\n    department: data.department,\n    // Document\n    structuredFilename: data.structuredFilename,\n    contractType: data.contractType,\n    effectiveDate: data.effectiveDate,\n    // Storage\n    driveFileId: data.driveFileId,\n    driveUrl: data.driveUrl,\n    driveFolderPath: data.driveFolderPath,\n    cdnBackupUrl: data.cdnUrl,\n    // Airtable\n    airtableRecordId: data.airtableRecordId,\n    // Audit trail\n    auditTrail: {\n      filedBy: data.filedBy,\n      filedAt: data.filedAt,\n      uploadId: data.uploadId,\n      fileSizeBytes: data.fileSizeBytes\n    }\n  }\n}];"},"typeVersion":2},{"id":"42c588d7-d455-4357-9fc1-9d16ac39a101","name":"Respond to Webhook","type":"n8n-nodes-base.respondToWebhook","position":[5072,240],"parameters":{"options":{"responseCode":201,"responseHeaders":{"entries":[{"name":"Content-Type","value":"application/json"}]}},"respondWith":"json","responseBody":"={{ $json }}"},"typeVersion":1.1},{"id":"5de2d9b8-930f-4837-8d83-34c75eabf316","name":"Error Handler","type":"n8n-nodes-base.code","position":[1248,928],"parameters":{"jsCode":"const err = $input.first();\nconst msg = err.json?.message || err.error?.message || err.json?.error || 'Unexpected error in document archiving workflow';\nconsole.error('[HR Archive] Error:', msg);\nreturn [{ json: { success: false, error: msg, timestamp: new Date().toISOString() } }];"},"typeVersion":2,"alwaysOutputData":true},{"id":"6dddfd8d-2de7-4a97-8806-e8a16c5e262b","name":"Respond with Error","type":"n8n-nodes-base.respondToWebhook","position":[1456,928],"parameters":{"options":{"responseCode":400,"responseHeaders":{"entries":[{"name":"Content-Type","value":"application/json"}]}},"respondWith":"json","responseBody":"={{ $json }}"},"typeVersion":1.1}],"pinData":{},"connections":{"Error Handler":{"main":[[{"node":"Respond with Error","type":"main","index":0}]]},"Extract CDN URL":{"main":[[{"node":"Drive - Find Employee Folder","type":"main","index":0}]]},"Has Remote URL?":{"main":[[{"node":"Upload to URL - Remote","type":"main","index":0}],[{"node":"Upload to URL - Binary","type":"main","index":0}]]},"Merge Folder ID":{"main":[[{"node":"Drive - Upload Document","type":"main","index":0}]]},"Needs New Folder?":{"main":[[{"node":"Drive - Create Employee Folder","type":"main","index":0}],[{"node":"Merge Folder ID","type":"main","index":0}]]},"Resolve Folder ID":{"main":[[{"node":"Needs New Folder?","type":"main","index":0}]]},"Build Final Response":{"main":[[{"node":"Respond to Webhook","type":"main","index":0}]]},"IF Duplicate Exists?":{"main":[[{"node":"Respond - 409 Duplicate","type":"main","index":0}],[{"node":"Has Remote URL?","type":"main","index":0}]]},"Merge Airtable Result":{"main":[[{"node":"Send Confirmation Email","type":"main","index":0}]]},"Upload to URL - Binary":{"main":[[{"node":"Extract CDN URL","type":"main","index":0}]]},"Upload to URL - Remote":{"main":[[{"node":"Extract CDN URL","type":"main","index":0}]]},"Airtable Record Exists?":{"main":[[{"node":"Airtable - Update Existing Record","type":"main","index":0}],[{"node":"Airtable - Create New Record","type":"main","index":0}]]},"Drive - Upload Document":{"main":[[{"node":"Airtable - Find Employee Record","type":"main","index":0}]]},"Prepare Airtable Update":{"main":[[{"node":"Airtable Record Exists?","type":"main","index":0}]]},"Send Confirmation Email":{"main":[[{"node":"Build Final Response","type":"main","index":0}]]},"Validate & Enrich Payload":{"main":[[{"node":"Airtable - Duplicate Check","type":"main","index":0}]]},"Airtable - Duplicate Check":{"main":[[{"node":"IF Duplicate Exists?","type":"main","index":0}]]},"Webhook - Receive Contract":{"main":[[{"node":"Validate & Enrich Payload","type":"main","index":0}]]},"Airtable - Create New Record":{"main":[[{"node":"Merge Airtable Result","type":"main","index":0}]]},"Drive - Find Employee Folder":{"main":[[{"node":"Resolve Folder ID","type":"main","index":0}]]},"Drive - Create Employee Folder":{"main":[[{"node":"Merge Folder ID","type":"main","index":0}]]},"Airtable - Find Employee Record":{"main":[[{"node":"Prepare Airtable Update","type":"main","index":0}]]},"Airtable - Update Existing Record":{"main":[[{"node":"Merge Airtable Result","type":"main","index":0}]]}}},"lastUpdatedBy":1,"workflowInfo":{"nodeCount":32,"nodeTypes":{"n8n-nodes-base.if":{"count":4},"n8n-nodes-base.code":{"count":8},"n8n-nodes-base.gmail":{"count":1},"n8n-nodes-base.webhook":{"count":1},"n8n-nodes-base.airtable":{"count":4},"n8n-nodes-base.stickyNote":{"count":6},"n8n-nodes-base.googleDrive":{"count":3},"n8n-nodes-base.respondToWebhook":{"count":3},"n8n-nodes-uploadtourl.uploadToUrl":{"count":2}}},"status":"published","readyToDemo":null,"user":{"name":"Jitesh Dugar","username":"jiteshdugar","bio":"AI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.","verified":true,"links":["https://www.linkedin.com/in/jiteshdugar"],"avatar":"https://gravatar.com/avatar/edaa3abb99806b0586dced559d0a5417f24a507e7c4464a63960f0638a4b1b90?r=pg&d=retro&size=200"},"nodes":[{"id":2,"icon":"file:airtable.svg","name":"n8n-nodes-base.airtable","codex":{"data":{"resources":{"generic":[{"url":"https://n8n.io/blog/2021-goals-level-up-your-vocabulary-with-vonage-and-n8n/","icon":"🎯","label":"2021 Goals: Level Up Your Vocabulary With Vonage and n8n"},{"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/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/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/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"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/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/learn-to-build-powerful-api-endpoints-using-webhooks/","icon":"🧰","label":"Learn to Build Powerful API Endpoints Using Webhooks"},{"url":"https://n8n.io/blog/sending-sms-the-low-code-way-with-airtable-twilio-programmable-sms-and-n8n/","icon":"📱","label":"Sending SMS the Low-Code Way with Airtable, Twilio Programmable SMS, and n8n"},{"url":"https://n8n.io/blog/automating-conference-organization-processes-with-n8n/","icon":"🙋‍♀️","label":"Automating Conference Organization Processes with n8n"},{"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/app-nodes/n8n-nodes-base.airtable/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/airtable/"}]},"categories":["Data & Storage"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\"]","defaults":{"name":"Airtable"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMDAgMTcwIj48cGF0aCBmaWxsPSIjZmNiNDAwIiBkPSJNODkgNC44IDE2LjIgMzQuOWMtNC4xIDEuNy00IDcuNC4xIDkuMWw3My4yIDI5YzYuNCAyLjYgMTMuNiAyLjYgMjAgMGw3My4yLTI5YzQuMS0xLjYgNC4xLTcuNC4xLTkuMWwtNzMtMzAuMUMxMDMuMiAyIDk1LjcgMiA4OSA0LjgiLz48cGF0aCBmaWxsPSIjMThiZmZmIiBkPSJNMTA1LjkgODguOXY3Mi41YzAgMy40IDMuNSA1LjggNi43IDQuNWw4MS42LTMxLjdjMS45LS43IDMuMS0yLjUgMy4xLTQuNVY1Ny4yYzAtMy40LTMuNS01LjgtNi43LTQuNUwxMDkgODQuM2MtMS45LjgtMy4xIDIuNi0zLjEgNC42Ii8+PHBhdGggZmlsbD0iI2Y4MmI2MCIgZD0ibTg2LjkgOTIuNi0yNC4yIDExLjctMi41IDEuMkw5LjEgMTMwYy0zLjIgMS42LTcuNC0uOC03LjQtNC40VjU3LjVjMC0xLjMuNy0yLjQgMS42LTMuM3EuNi0uNiAxLjItLjljMS4yLS43IDMtLjkgNC40LS4zbDc3LjUgMzAuN2M0IDEuNSA0LjMgNy4xLjUgOC45Ii8+PHBhdGggZmlsbD0iI2JhMWU0NSIgZD0ibTg2LjkgOTIuNi0yNC4yIDExLjctNTkuNC01MHEuNi0uNiAxLjItLjljMS4yLS43IDMtLjkgNC40LS4zbDc3LjUgMzAuN2M0IDEuNCA0LjMgNyAuNSA4LjgiLz48L3N2Zz4="},"displayName":"Airtable","typeVersion":2,"nodeCategories":[{"id":3,"name":"Data & Storage"}]},{"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":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":58,"icon":"file:googleDrive.svg","name":"n8n-nodes-base.googleDrive","codex":{"data":{"resources":{"generic":[{"url":"https://n8n.io/blog/your-business-doesnt-need-you-to-operate/","icon":" 🖥️","label":"Hey founders! Your business doesn't need you to operate"},{"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/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googledrive/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"}]},"categories":["Data & Storage"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\"]","defaults":{"name":"Google Drive"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiB2aWV3Qm94PSIwIDAgODEgNzMiPjx1c2UgeGxpbms6aHJlZj0iI2EiIHg9Ii41IiB5PSIuNSIvPjxzeW1ib2wgaWQ9ImEiIG92ZXJmbG93PSJ2aXNpYmxlIj48ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0ibm9uZSI+PHBhdGggZmlsbD0iIzAwNjZkYSIgZD0ibTYuMDQ4IDYxLjI2IDMuNTI4IDYuMDk0Yy43MzMgMS4yODMgMS43ODcgMi4yOTEgMy4wMjQgMy4wMjRsMTIuNi0yMS44MUgwYTguMyA4LjMgMCAwIDAgMS4xIDQuMTI0eiIvPjxwYXRoIGZpbGw9IiMwMGFjNDciIGQ9Ik00MCAyMi45MSAyNy40IDEuMWMtMS4yMzcuNzMzLTIuMjkxIDEuNzQxLTMuMDI0IDMuMDI0TDEuMSA0NC40NDVBOC4zIDguMyAwIDAgMCAwIDQ4LjU2OGgyNS4yeiIvPjxwYXRoIGZpbGw9IiNlYTQzMzUiIGQ9Ik02Ny40IDcwLjM3OGMxLjIzNy0uNzMzIDIuMjkxLTEuNzQxIDMuMDI0LTMuMDI0bDEuNDY2LTIuNTIgNy4wMS0xMi4xNDJhOC4zIDguMyAwIDAgMCAxLjEtNC4xMjRINTQuNzk4bDUuMzYzIDEwLjUzOHoiLz48cGF0aCBmaWxsPSIjMDA4MzJkIiBkPSJNNDAgMjIuOTEgNTIuNiAxLjFDNTEuMzYzLjM2NyA0OS45NDMgMCA0OC40NzcgMEgzMS41MjRjLTEuNDY2IDAtMi44ODcuNDEyLTQuMTI0IDEuMXoiLz48cGF0aCBmaWxsPSIjMjY4NGZjIiBkPSJNNTQuNzk5IDQ4LjU2OEgyNS4ybC0xMi42IDIxLjgxYzEuMjM3LjczMyAyLjY1NyAxLjEgNC4xMjQgMS4xaDQ2LjU1MmMxLjQ2NiAwIDIuODg3LS40MTIgNC4xMjQtMS4xeiIvPjxwYXRoIGZpbGw9IiNmZmJhMDAiIGQ9Ik02Ny4yNjIgMjQuMjg0IDU1LjYyNCA0LjEyNEM1NC44OTEgMi44NDEgNTMuODM3IDEuODMzIDUyLjYgMS4xTDQwIDIyLjkxbDE0LjggMjUuNjU5aDI1LjE1NWE4LjMgOC4zIDAgMCAwLTEuMS00LjEyNHoiLz48L2c+PC9zeW1ib2w+PC9zdmc+"},"displayName":"Google Drive","typeVersion":3,"nodeCategories":[{"id":3,"name":"Data & Storage"}]},{"id":356,"icon":"file:gmail.svg","name":"n8n-nodes-base.gmail","codex":{"data":{"alias":["email","human","form","wait","hitl","approval"],"resources":{"generic":[{"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/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with 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-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/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/your-business-doesnt-need-you-to-operate/","icon":" 🖥️","label":"Hey founders! Your business doesn't need you to operate"},{"url":"https://n8n.io/blog/using-automation-to-boost-productivity-in-the-workplace/","icon":"💪","label":"Using Automation to Boost Productivity in the Workplace"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gmail/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"}]},"categories":["Communication","HITL"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"HITL":["Human in the Loop"]}}},"group":"[\"transform\"]","defaults":{"name":"Gmail"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTYiIGhlaWdodD0iMTkzIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZmlsbD0iIzQyODVGNCIgZD0iTTU4LjE4MiAxOTIuMDVWOTMuMTRMMjcuNTA3IDY1LjA3NyAwIDQ5LjUwNHYxMjUuMDkxYzAgOS42NTggNy44MjUgMTcuNDU1IDE3LjQ1NSAxNy40NTV6Ii8+PHBhdGggZmlsbD0iIzM0QTg1MyIgZD0iTTE5Ny44MTggMTkyLjA1aDQwLjcyN2M5LjY1OSAwIDE3LjQ1NS03LjgyNiAxNy40NTUtMTcuNDU1VjQ5LjUwNWwtMzEuMTU2IDE3LjgzNy0yNy4wMjYgMjUuNzk4eiIvPjxwYXRoIGZpbGw9IiNFQTQzMzUiIGQ9Im01OC4xODIgOTMuMTQtNC4xNzQtMzguNjQ3IDQuMTc0LTM2Ljk4OUwxMjggNjkuODY4bDY5LjgxOC01Mi4zNjQgNC42NyAzNC45OTItNC42NyA0MC42NDRMMTI4IDE0NS41MDR6Ii8+PHBhdGggZmlsbD0iI0ZCQkMwNCIgZD0iTTE5Ny44MTggMTcuNTA0VjkzLjE0TDI1NiA0OS41MDRWMjYuMjMxYzAtMjEuNTg1LTI0LjY0LTMzLjg5LTQxLjg5LTIwLjk0NXoiLz48cGF0aCBmaWxsPSIjQzUyMjFGIiBkPSJtMCA0OS41MDQgMjYuNzU5IDIwLjA3TDU4LjE4MiA5My4xNFYxNy41MDRMNDEuODkgNS4yODZDMjQuNjEtNy42NiAwIDQuNjQ2IDAgMjYuMjN6Ii8+PC9zdmc+"},"displayName":"Gmail","typeVersion":2,"nodeCategories":[{"id":6,"name":"Communication"},{"id":28,"name":"HITL"}]},{"id":535,"icon":"file:webhook.svg","name":"n8n-nodes-base.respondToWebhook","codex":{"data":{"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.respondtowebhook/"}]},"categories":["Core Nodes","Utility"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"transform\"]","defaults":{"name":"Respond to Webhook"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCI+PHBhdGggZmlsbD0iIzM3NDc0ZiIgZD0iTTM1IDM3Yy0yLjIgMC00LTEuOC00LTRzMS44LTQgNC00IDQgMS44IDQgNC0xLjggNC00IDQiLz48cGF0aCBmaWxsPSIjMzc0NzRmIiBkPSJNMzUgNDNjLTMgMC01LjktMS40LTcuOC0zLjdsMy4xLTIuNWMxLjEgMS40IDIuOSAyLjMgNC43IDIuMyAzLjMgMCA2LTIuNyA2LTZzLTIuNy02LTYtNmMtMSAwLTIgLjMtMi45LjdsLTEuNyAxTDIzLjMgMTZsMy41LTEuOSA1LjMgOS40YzEtLjMgMi0uNSAzLS41IDUuNSAwIDEwIDQuNSAxMCAxMFM0MC41IDQzIDM1IDQzIi8+PHBhdGggZmlsbD0iIzM3NDc0ZiIgZD0iTTE0IDQzQzguNSA0MyA0IDM4LjUgNCAzM2MwLTQuNiAzLjEtOC41IDcuNS05LjdsMSAzLjlDOS45IDI3LjkgOCAzMC4zIDggMzNjMCAzLjMgMi43IDYgNiA2czYtMi43IDYtNnYtMmgxNXY0SDIzLjhjLS45IDQuNi01IDgtOS44IDgiLz48cGF0aCBmaWxsPSIjZTkxZTYzIiBkPSJNMTQgMzdjLTIuMiAwLTQtMS44LTQtNHMxLjgtNCA0LTQgNCAxLjggNCA0LTEuOCA0LTQgNCIvPjxwYXRoIGZpbGw9IiMzNzQ3NGYiIGQ9Ik0yNSAxOWMtMi4yIDAtNC0xLjgtNC00czEuOC00IDQtNCA0IDEuOCA0IDQtMS44IDQtNCA0Ii8+PHBhdGggZmlsbD0iI2U5MWU2MyIgZD0ibTE1LjcgMzQtMy40LTIgNS45LTkuN2MtMi0xLjktMy4yLTQuNS0zLjItNy4zIDAtNS41IDQuNS0xMCAxMC0xMHMxMCA0LjUgMTAgMTBjMCAuOS0uMSAxLjctLjMgMi41bC0zLjktMWMuMS0uNS4yLTEgLjItMS41IDAtMy4zLTIuNy02LTYtNnMtNiAyLjctNiA2YzAgMi4xIDEuMSA0IDIuOSA1LjFsMS43IDF6Ii8+PC9zdmc+"},"displayName":"Respond to Webhook","typeVersion":2,"nodeCategories":[{"id":7,"name":"Utility"},{"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":35,"name":"Document Extraction"}],"image":[]}}