{
  "name": "FilePost — Archive documents with Google Drive and Airtable",
  "nodes": [
    {
      "parameters": {
        "content": "## Searchable document archive\n\nReceives a document URL and business metadata, downloads the file once, then sends the same binary to two destinations:\n\n- **FilePost** creates a stable review URL.\n- **Google Drive** stores the internal archive copy.\n- **Airtable** records both links and the audit metadata.\n\n### Setup\n1. Install the verified `n8n-nodes-filepost` community node.\n2. Connect FilePost, Google Drive, and Airtable credentials.\n3. Choose the Drive folder, Airtable base, and table in their nodes.\n4. POST JSON containing `file_url`, `employee_id`, `employee_name`, and `document_type` to the webhook.",
        "height": 520,
        "width": 600,
        "color": 7
      },
      "id": "1cc4ab9a-5238-4bbc-890e-a0d472c40f0a",
      "name": "How this workflow works",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-760, -380]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "filepost-document-archive",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "fe64ed7c-008d-4572-a109-e2cc879b5dd6",
      "name": "Receive Document",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [-720, 80],
      "webhookId": "filepost-document-archive-template"
    },
    {
      "parameters": {
        "jsCode": "const body = $input.first().json.body || $input.first().json;\nconst required = ['file_url', 'employee_id', 'employee_name', 'document_type'];\nconst missing = required.filter((key) => !String(body[key] || '').trim());\nif (missing.length) throw new Error(`Missing required fields: ${missing.join(', ')}`);\n\nconst sourceUrl = new URL(body.file_url);\nif (!['http:', 'https:'].includes(sourceUrl.protocol)) throw new Error('file_url must use http or https');\n\nconst clean = (value, fallback) => String(value || fallback).trim().replace(/[\\r\\n]+/g, ' ').slice(0, 180);\nconst employeeId = clean(body.employee_id, '').toUpperCase().replace(/[^A-Z0-9_-]/g, '');\nconst employeeName = clean(body.employee_name, 'Unknown employee');\nconst documentType = clean(body.document_type, 'Document');\nconst originalName = clean(body.filename || sourceUrl.pathname.split('/').pop(), 'document.bin');\nconst extension = (originalName.includes('.') ? originalName.split('.').pop() : 'bin').toLowerCase().replace(/[^a-z0-9]/g, '') || 'bin';\nconst date = new Date().toISOString().slice(0, 10);\nconst archiveName = `${employeeId}_${documentType.replace(/[^a-z0-9]+/gi, '-').replace(/^-|-$/g, '')}_${date}.${extension}`;\n\nreturn [{ json: {\n  fileUrl: sourceUrl.toString(),\n  employeeId,\n  employeeName,\n  employeeEmail: clean(body.employee_email, ''),\n  department: clean(body.department, 'General'),\n  documentType,\n  archiveName,\n  filedBy: clean(body.filed_by, 'n8n'),\n  filedAt: new Date().toISOString()\n} }];"
      },
      "id": "f7f089bf-38d7-4fb1-992e-83381901a363",
      "name": "Validate and Name Document",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [-480, 80]
    },
    {
      "parameters": {
        "url": "={{ $json.fileUrl }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file",
              "outputPropertyName": "data"
            }
          }
        }
      },
      "id": "bfa10665-9bda-4cff-802f-0e1c7a885949",
      "name": "Download Source Document",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [-240, 80]
    },
    {
      "parameters": {
        "operation": "upload",
        "binaryPropertyName": "data",
        "expiresIn": "",
        "filenameMode": "download"
      },
      "id": "73ea8efe-a83a-447f-b6ab-16d5ee4bf122",
      "name": "Create Stable Review URL",
      "type": "n8n-nodes-filepost.filePost",
      "typeVersion": 1,
      "position": [20, -40]
    },
    {
      "parameters": {
        "name": "={{ $('Validate and Name Document').first().json.archiveName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "MyDrive"
        },
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root"
        },
        "options": {}
      },
      "id": "81e7768e-3f85-4484-b56f-d94cec65aa57",
      "name": "Archive in Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [20, 200]
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "id": "f08dbec2-cfe8-4735-a0e0-cf28a8394620",
      "name": "Join Storage Results",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [280, 80]
    },
    {
      "parameters": {
        "operation": "create",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Employee ID": "={{ $('Validate and Name Document').first().json.employeeId }}",
            "Employee Name": "={{ $('Validate and Name Document').first().json.employeeName }}",
            "Department": "={{ $('Validate and Name Document').first().json.department }}",
            "Document Type": "={{ $('Validate and Name Document').first().json.documentType }}",
            "Archive Name": "={{ $('Validate and Name Document').first().json.archiveName }}",
            "FilePost URL": "={{ $('Create Stable Review URL').first().json.url }}",
            "FilePost File ID": "={{ $('Create Stable Review URL').first().json.file_id }}",
            "Drive File ID": "={{ $('Archive in Google Drive').first().json.id }}",
            "Filed By": "={{ $('Validate and Name Document').first().json.filedBy }}",
            "Filed At": "={{ $('Validate and Name Document').first().json.filedAt }}"
          }
        },
        "options": {}
      },
      "id": "736f2ff0-bef5-4bd7-902f-111e93b56858",
      "name": "Create Airtable Archive Record",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.1,
      "position": [520, 80]
    },
    {
      "parameters": {
        "jsCode": "const meta = $('Validate and Name Document').first().json;\nconst hosted = $('Create Stable Review URL').first().json;\nconst drive = $('Archive in Google Drive').first().json;\nconst airtable = $input.first().json;\nreturn [{ json: {\n  success: true,\n  employee_id: meta.employeeId,\n  document_type: meta.documentType,\n  archive_name: meta.archiveName,\n  filepost_url: hosted.url,\n  filepost_file_id: hosted.file_id,\n  drive_file_id: drive.id || null,\n  airtable_record_id: airtable.id || null,\n  filed_at: meta.filedAt\n} }];"
      },
      "id": "f5c0b92f-815c-4196-94e5-c4ff60ba7f71",
      "name": "Build Archive Result",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [760, 80]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ $json }}",
        "options": {
          "responseCode": 201
        }
      },
      "id": "9e8465b4-199b-4a5d-9bdc-9c2224ca8c10",
      "name": "Return Archive Result",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [1000, 80]
    }
  ],
  "connections": {
    "Receive Document": {
      "main": [[{"node": "Validate and Name Document", "type": "main", "index": 0}]]
    },
    "Validate and Name Document": {
      "main": [[{"node": "Download Source Document", "type": "main", "index": 0}]]
    },
    "Download Source Document": {
      "main": [[
        {"node": "Create Stable Review URL", "type": "main", "index": 0},
        {"node": "Archive in Google Drive", "type": "main", "index": 0}
      ]]
    },
    "Create Stable Review URL": {
      "main": [[{"node": "Join Storage Results", "type": "main", "index": 0}]]
    },
    "Archive in Google Drive": {
      "main": [[{"node": "Join Storage Results", "type": "main", "index": 1}]]
    },
    "Join Storage Results": {
      "main": [[{"node": "Create Airtable Archive Record", "type": "main", "index": 0}]]
    },
    "Create Airtable Archive Record": {
      "main": [[{"node": "Build Archive Result", "type": "main", "index": 0}]]
    },
    "Build Archive Result": {
      "main": [[{"node": "Return Archive Result", "type": "main", "index": 0}]]
    }
  },
  "active": false,
  "settings": {"executionOrder": "v1"},
  "versionId": "840d1490-d823-436a-afd0-729f7d3c4617",
  "meta": {"templateCredsSetupCompleted": false},
  "tags": []
}
