This workflow corresponds to n8n.io template #15866 — we link there as the canonical source.
This workflow follows the Gmail → Google Calendar recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "viYVhQayQDR3YROX",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Auto-classify documents with Gemini and organize in Google Drive",
"tags": [],
"nodes": [
{
"id": "94b8eab6-5674-449f-8b6d-06557117bdd9",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2912,
-192
],
"parameters": {
"width": 460,
"height": 612,
"content": "### How it works\nThis workflow picks up files from a Google Drive inbox folder and classifies each one using Gemini 2.5 Flash OCR. Based on the result, it renames the file, moves it to the matching folder, and logs everything to Google Sheets.\n\nIf a deadline is detected (payment due, contract renewal, etc.), it creates a Google Calendar event and sends a Gmail alert. Failed classifications are emailed for manual review and logged to a separate error sheet.\n\n### Setup steps\n1. Set your inbox folder ID in **Get inbox files**\n2. Add your Gemini API key as a Query Auth credential (parameter name: `key`)\n3. Set destination folder IDs for each document type in **Generate filename**\n4. Set your spreadsheet ID in **Log to spreadsheet** and **Log error to sheet**\n5. Set your calendar ID in **Add to calendar**\n6. Set your notification email in **Send deadline alert** and **Send error notification**\n\n### Customization\n- Edit the classification prompt in **Gemini OCR classification** to add document types\n- Adjust the confidence threshold (default 0.6) in **Parse AI response**\n- Modify the filename pattern in **Generate filename**"
},
"typeVersion": 1
},
{
"id": "3d45df51-4364-4838-b3cb-cf03edd95af0",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2416,
-192
],
"parameters": {
"color": "#F2EEEE",
"width": 876,
"height": 924,
"content": "## 1. Retrieve files\nPulls all files from a designated Google Drive inbox folder and processes them one at a time through a loop."
},
"typeVersion": 1
},
{
"id": "67f815c8-ca9a-4493-b460-d61db795ccd9",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1520,
-192
],
"parameters": {
"color": "#FDFCFC",
"width": 1108,
"height": 930,
"content": "## 2. Classify documents\nChecks file type (PDF or image), converts to Base64, and sends to Gemini 2.5 Flash for OCR classification. Unsupported formats go to error handling."
},
"typeVersion": 1
},
{
"id": "74b34dff-ff19-4e17-be85-8bc12c83d470",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
-192
],
"parameters": {
"color": "#FAFAFA",
"width": 772,
"height": 570,
"content": "## 3. Rename & organize\nBuilds a standardized filename, renames the file, and moves it to the matching folder in Google Drive."
},
"typeVersion": 1
},
{
"id": "08ce2461-82bd-4b9d-9736-848525c4851b",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
-192
],
"parameters": {
"color": "#F7F7F7",
"width": 896,
"height": 926,
"content": "## 4. Log & schedule deadlines\nAppends results to Google Sheets. If a deadline is found, creates a calendar event and sends an email alert via Gmail."
},
"typeVersion": 1
},
{
"id": "0a6271c4-ac9e-4d9f-b412-fd34d5d0a622",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
400
],
"parameters": {
"color": "#FEFBFB",
"width": 772,
"height": 336,
"content": "## Error handling\nSends a Gmail notification for failed classifications and logs the error to a separate sheet for manual review."
},
"typeVersion": 1
},
{
"id": "8f505d2f-dc73-4ca9-9c6a-1a0a379669b5",
"name": "Download file",
"type": "n8n-nodes-base.googleDrive",
"notes": "Downloads the file binary from Google Drive for processing",
"position": [
-1680,
32
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "download"
},
"typeVersion": 3
},
{
"id": "58ab20ba-a840-433f-b2eb-81c1823dd4a3",
"name": "Check file type",
"type": "n8n-nodes-base.switch",
"notes": "Routes PDF and image files to classification; other formats go to error handling",
"position": [
-1456,
16
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "PDF",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "6e6ccb5c-4635-4a74-9baf-db965f31083c",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $binary.data.mimeType }}",
"rightValue": "=application/pdf"
}
]
},
"renameOutput": true
},
{
"outputKey": "Image",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "2959442d-d2d6-4661-86c5-31b4c9bfda75",
"operator": {
"type": "string",
"operation": "startsWith"
},
"leftValue": "={{ $binary.data.mimeType }}",
"rightValue": "=image/"
}
]
},
"renameOutput": true
}
]
},
"options": {
"fallbackOutput": "extra"
},
"looseTypeValidation": true
},
"typeVersion": 3.4
},
{
"id": "c86a634d-2bfc-428f-a3b0-103360744c17",
"name": "Convert to Base64",
"type": "n8n-nodes-base.code",
"notes": "Encodes file binary to Base64 for the Gemini API request",
"position": [
-1232,
0
],
"parameters": {
"jsCode": "const items = $input.all();\nconst results = [];\n\nfor (let i = 0; i < items.length; i++) {\n const item = items[i];\n const binaryData = item.binary?.data;\n if (!binaryData) {\n results.push({\n json: {\n error: true,\n message: 'No binary data found',\n originalFileName: item.json.name || 'unknown'\n }\n });\n continue;\n }\n\n const binaryBuffer = await this.helpers.getBinaryDataBuffer(i, 'data');\n const base64 = binaryBuffer.toString('base64');\n\n const mimeType = binaryData.mimeType || 'application/octet-stream';\n const fileName = item.json.name || binaryData.fileName || 'unknown';\n\n results.push({\n json: {\n base64Data: base64,\n mimeType: mimeType,\n originalFileName: fileName,\n fileId: item.json.id || '',\n error: false\n }\n });\n}\n\nreturn results;"
},
"typeVersion": 2
},
{
"id": "0f008dcb-b807-487b-992b-5863c8837d5f",
"name": "Gemini OCR classification",
"type": "n8n-nodes-base.httpRequest",
"notes": "Sends the Base64-encoded file to Gemini 2.5 Flash for OCR and document classification",
"position": [
-1008,
0
],
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
"method": "POST",
"options": {},
"jsonBody": "={\n \"contents\": [\n {\n \"parts\": [\n {\n \"inline_data\": {\n \"mime_type\": \"{{ $json.mimeType }}\",\n \"data\": \"{{ $json.base64Data }}\"\n }\n },\n {\n \"text\": \"You are a document classification expert. Analyze this document and respond ONLY in the following JSON format.\\n\\n{\\n \\\"document_type\\\": \\\"invoice|estimate|contract|receipt|application|inquiry|delivery_note|purchase_order|other\\\",\\n \\\"confidence\\\": 0.0~1.0,\\n \\\"company_name\\\": \\\"Company name\\\",\\n \\\"document_date\\\": \\\"YYYY-MM-DD\\\",\\n \\\"amount\\\": \\\"Amount (numbers only)\\\",\\n \\\"deadline\\\": \\\"Deadline date YYYY-MM-DD (null if none)\\\",\\n \\\"deadline_type\\\": \\\"payment_due|contract_renewal|submission_due|response_due|null\\\",\\n \\\"summary\\\": \\\"Brief summary of the document (max 50 chars)\\\",\\n \\\"extracted_items\\\": [\\n {\\\"key\\\": \\\"Field name\\\", \\\"value\\\": \\\"Value\\\"}\\n ]\\n}\\n\\nNotes:\\n- Use null for unreadable fields\\n- Do not output any text other than JSON\\n- Amounts should be numbers only without commas\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"temperature\": 0.1,\n \"responseMimeType\": \"application/json\"\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "ed0a37f0-6df3-4b46-b503-2bec8ac49de8",
"name": "Parse AI response",
"type": "n8n-nodes-base.code",
"notes": "Parses the Gemini JSON response and validates confidence >= 0.6",
"position": [
-784,
0
],
"parameters": {
"jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n try {\n const response = item.json;\n let content = '';\n\n if (response.candidates && response.candidates[0]) {\n content = response.candidates[0].content.parts[0].text;\n }\n\n let parsed;\n try {\n content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n parsed = JSON.parse(content);\n } catch (parseErr) {\n throw new Error('JSON parse failed: ' + parseErr.message);\n }\n\n const confidence = parsed.confidence || 0;\n const isValid = confidence >= 0.6 && parsed.document_type && parsed.document_type !== 'other';\n const prevData = $('Convert to Base64').first().json;\n\n results.push({\n json: {\n ...parsed,\n isValid: isValid,\n parseError: false,\n originalFileName: prevData.originalFileName || '',\n fileId: prevData.fileId || '',\n processedAt: new Date().toISOString()\n }\n });\n } catch (err) {\n const prevData = $('Convert to Base64').first().json;\n results.push({\n json: {\n isValid: false,\n parseError: true,\n errorMessage: err.message,\n originalFileName: prevData?.originalFileName || 'unknown',\n fileId: prevData?.fileId || '',\n processedAt: new Date().toISOString()\n }\n });\n }\n}\n\nreturn results;"
},
"typeVersion": 2
},
{
"id": "7abefe69-652b-4c45-a4dd-ab7ac7533158",
"name": "Classification check",
"type": "n8n-nodes-base.if",
"notes": "TRUE = valid classification \u2192 organize files. FALSE = failed \u2192 error handling",
"position": [
-560,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4b25baf0-0c14-4f86-b162-f14f6ab5a9b8",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.isValid }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "f9d72908-6947-48d8-bdb9-86230971cd25",
"name": "Rename file",
"type": "n8n-nodes-base.googleDrive",
"notes": "Renames the file in Google Drive with the standardized name",
"position": [
-64,
-16
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.fileId }}"
},
"options": {},
"operation": "update",
"newUpdatedFileName": "={{ $json.newFileName }}"
},
"typeVersion": 3
},
{
"id": "f04d2684-708f-4823-bf16-e3ba86333dfd",
"name": "Move to folder",
"type": "n8n-nodes-base.googleDrive",
"notes": "Moves the file to the document-type folder in Google Drive",
"position": [
160,
-16
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Generate filename').first().json.fileId }}"
},
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"folderId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Generate filename').first().json.targetFolderId }}"
},
"operation": "move"
},
"typeVersion": 3
},
{
"id": "3bd48727-a11d-475b-8324-0499454133c1",
"name": "Generate filename",
"type": "n8n-nodes-base.code",
"notes": "Builds filename (e.g. INV_20250101_CompanyName.pdf) and maps document type to folder ID",
"position": [
-288,
-16
],
"parameters": {
"jsCode": "const item = $input.first().json;\n\n// Document type prefix mapping\nconst typeMap = {\n 'invoice': 'INV',\n 'estimate': 'EST',\n 'contract': 'CON',\n 'receipt': 'REC',\n 'application': 'APP',\n 'inquiry': 'INQ',\n 'delivery_note': 'DLV',\n 'purchase_order': 'ORD',\n 'other': 'OTH'\n};\n\n// \u2605 Set your Google Drive folder IDs for each document type \u2605\nconst folderMap = {\n 'invoice': 'YOUR_INVOICE_FOLDER_ID',\n 'estimate': 'YOUR_ESTIMATE_FOLDER_ID',\n 'contract': 'YOUR_CONTRACT_FOLDER_ID',\n 'receipt': 'YOUR_RECEIPT_FOLDER_ID',\n 'application': 'YOUR_APPLICATION_FOLDER_ID',\n 'inquiry': 'YOUR_INQUIRY_FOLDER_ID',\n 'delivery_note': 'YOUR_DELIVERY_NOTE_FOLDER_ID',\n 'purchase_order': 'YOUR_PURCHASE_ORDER_FOLDER_ID',\n 'other': 'YOUR_OTHER_FOLDER_ID'\n};\n\nconst prefix = typeMap[item.document_type] || 'OTH';\nconst date = item.document_date || new Date().toISOString().slice(0, 10);\nconst company = (item.company_name || 'unknown').replace(/[\\\\\\/\\/:*?\"<>|]/g, '_').slice(0, 20);\nconst ext = item.originalFileName ? item.originalFileName.split('.').pop() : 'pdf';\nconst newFileName = prefix + '_' + date.replace(/-/g, '') + '_' + company + '.' + ext;\nconst targetFolderId = folderMap[item.document_type] || folderMap['other'];\n\nreturn [{\n json: {\n ...item,\n newFileName: newFileName,\n targetFolderId: targetFolderId,\n typePrefix: prefix\n }\n}];"
},
"typeVersion": 2
},
{
"id": "50a47708-9767-47f1-9bb5-50326880a95f",
"name": "Log to spreadsheet",
"type": "n8n-nodes-base.googleSheets",
"notes": "Appends the classification result to the main log sheet",
"position": [
448,
176
],
"parameters": {
"columns": {
"value": {
"amount": "={{ $('Generate filename').first().json.amount }}",
"status": "Processed",
"summary": "={{ $('Generate filename').first().json.summary }}",
"deadline": "={{ $('Generate filename').first().json.deadline }}",
"file_url": "=https://drive.google.com/file/d/{{ $('Generate filename').first().json.fileId }}/view",
"filename": "={{ $('Generate filename').first().json.newFileName }}",
"confidence": "={{ $('Generate filename').first().json.confidence }}",
"company_name": "={{ $('Generate filename').first().json.company_name }}",
"processed_at": "={{ $('Generate filename').first().json.processedAt }}",
"deadline_type": "={{ $('Generate filename').first().json.deadline_type }}",
"document_date": "={{ $('Generate filename').first().json.document_date }}",
"document_type": "={{ $('Generate filename').first().json.document_type }}",
"original_filename": "={{ $('Generate filename').first().json.originalFileName }}"
},
"schema": [
{
"id": "processed_at",
"type": "string",
"display": true,
"required": false,
"displayName": "processed_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "document_type",
"type": "string",
"display": true,
"required": false,
"displayName": "document_type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "company_name",
"type": "string",
"display": true,
"required": false,
"displayName": "company_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "document_date",
"type": "string",
"display": true,
"required": false,
"displayName": "document_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "amount",
"type": "string",
"display": true,
"required": false,
"displayName": "amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "deadline",
"type": "string",
"display": true,
"required": false,
"displayName": "deadline",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "deadline_type",
"type": "string",
"display": true,
"required": false,
"displayName": "deadline_type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "summary",
"type": "string",
"display": true,
"required": false,
"displayName": "summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "filename",
"type": "string",
"display": true,
"required": false,
"displayName": "filename",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "original_filename",
"type": "string",
"display": true,
"required": false,
"displayName": "original_filename",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "confidence",
"type": "string",
"display": true,
"required": false,
"displayName": "confidence",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "file_url",
"type": "string",
"display": true,
"required": false,
"displayName": "file_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_SPREADSHEET_ID"
}
},
"typeVersion": 4.7
},
{
"id": "be94e998-9b65-4dd4-a7c2-eaa1f86c1d76",
"name": "Has deadline?",
"type": "n8n-nodes-base.if",
"notes": "Checks if the document has a deadline date to schedule",
"position": [
640,
176
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2ffb57f8-a972-4a2d-8540-dd9bf7e25aec",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Generate filename').first().json.deadline }}",
"rightValue": ""
},
{
"id": "b3a17460-3167-478e-81f1-ecdf8516f52c",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $('Generate filename').first().json.deadline }}",
"rightValue": "null"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "91dc853d-0945-47ad-8324-d2644c4f1211",
"name": "Add to calendar",
"type": "n8n-nodes-base.googleCalendar",
"notes": "Creates an all-day calendar event on the deadline date",
"position": [
880,
80
],
"parameters": {
"end": "={{ $('Generate filename').first().json.deadline }}",
"start": "={{ $('Generate filename').first().json.deadline }}",
"calendar": {
"__rl": true,
"mode": "id",
"value": "YOUR_CALENDAR_ID"
},
"additionalFields": {
"allday": "yes",
"summary": "={{ $('Generate filename').first().json.deadline_type }}: {{ $('Generate filename').first().json.company_name }}",
"description": "==[Auto-registered]\\n\\nDocument type: {{ $('Generate filename').first().json.document_type }}\\nCompany: {{ $('Generate filename').first().json.company_name }}\\nAmount: {{ $('Generate filename').first().json.amount }}\\nSummary: {{ $('Generate filename').first().json.summary }}\\n\\nFile: https://drive.google.com/file/d/{{ $('Generate filename').first().json.fileId }}/view"
}
},
"typeVersion": 1.3
},
{
"id": "445fd82b-d3e1-4db8-9240-33cf7b0626a2",
"name": "Send deadline alert",
"type": "n8n-nodes-base.gmail",
"notes": "Sends an email notification about the upcoming deadline",
"position": [
1088,
80
],
"parameters": {
"sendTo": "user@example.com",
"message": "=<h3>Document deadline notification</h3><table border='1' cellpadding='8' cellspacing='0' style='border-collapse:collapse;'><tr><th style='background:#f0f0f0;'>Field</th><th>Details</th></tr><tr><td>Document type</td><td>{{ $('Generate filename').first().json.document_type }}</td></tr><tr><td>Company</td><td>{{ $('Generate filename').first().json.company_name }}</td></tr><tr><td>Deadline type</td><td>{{ $('Generate filename').first().json.deadline_type }}</td></tr><tr><td>Due date</td><td><strong>{{ $('Generate filename').first().json.deadline }}</strong></td></tr><tr><td>Amount</td><td>{{ $('Generate filename').first().json.amount }}</td></tr><tr><td>Summary</td><td>{{ $('Generate filename').first().json.summary }}</td></tr><tr><td>File</td><td><a href='https://drive.google.com/file/d/{{ $('Generate filename').first().json.fileId }}/view'>Open in Drive</a></td></tr></table><p style='color:#888;font-size:12px;'>This email was sent automatically by AI Document Organizer</p>",
"options": {},
"subject": "=[Deadline Alert] {{ $('Generate filename').first().json.deadline_type }} - {{ $('Generate filename').first().json.company_name }} ({{ $('Generate filename').first().json.deadline }})"
},
"typeVersion": 2.2
},
{
"id": "218ded88-96e2-441a-83e9-235bf096dd4d",
"name": "Send error notification",
"type": "n8n-nodes-base.gmail",
"notes": "Emails an alert when classification fails or confidence is too low",
"position": [
-64,
528
],
"parameters": {
"sendTo": "user@example.com",
"message": "=<h3>Automatic document classification failed</h3><p>The following file could not be classified automatically by AI. Please review it manually.</p><table border='1' cellpadding='8' cellspacing='0' style='border-collapse:collapse;'><tr><th style='background:#fff3cd;'>Field</th><th>Details</th></tr><tr><td>Filename</td><td>{{ $json.originalFileName }}</td></tr><tr><td>Error</td><td>{{ $json.errorMessage || 'Low confidence / unable to classify' }}</td></tr><tr><td>Confidence</td><td>{{ $json.confidence || 'N/A' }}</td></tr><tr><td>Processed at</td><td>{{ $json.processedAt }}</td></tr><tr><td>File</td><td><a href='https://drive.google.com/file/d/{{ $json.fileId }}/view'>Open in Drive</a></td></tr></table><p style='color:#888;font-size:12px;'>This email was sent automatically by AI Document Organizer</p>",
"options": {},
"subject": "=[Action Required] AI classification failed - {{ $json.originalFileName }}"
},
"typeVersion": 2.2
},
{
"id": "62933916-dcee-4d61-a040-0a818b10359b",
"name": "Log error to sheet",
"type": "n8n-nodes-base.googleSheets",
"notes": "Logs failed classifications to a separate error sheet for manual review",
"position": [
160,
528
],
"parameters": {
"columns": {
"value": {
"error": "={{ $json.errorMessage || 'Low confidence' }}",
"status": "Pending review",
"file_url": "=https://drive.google.com/file/d/{{ $json.fileId }}/view",
"filename": "={{ $json.originalFileName }}",
"processed_at": "={{ $json.processedAt }}"
},
"schema": [
{
"id": "processed_at",
"type": "string",
"display": true,
"required": false,
"displayName": "processed_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "filename",
"type": "string",
"display": true,
"required": false,
"displayName": "filename",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "error",
"type": "string",
"display": true,
"required": false,
"displayName": "error",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "file_url",
"type": "string",
"display": true,
"required": false,
"displayName": "file_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_SPREADSHEET_ID"
}
},
"typeVersion": 4.7
},
{
"id": "4960b27d-79b7-4130-b956-f82658f50243",
"name": "Handle unsupported format",
"type": "n8n-nodes-base.code",
"notes": "Creates an error object for file types that are not PDF or image",
"position": [
-304,
528
],
"parameters": {
"jsCode": "const item = $input.first();\n\nreturn [{\n json: {\n isValid: false,\n parseError: true,\n errorMessage: 'Unsupported file format (' + (item.json.mimeType || 'unknown') + '). Only PDF and image files are supported.',\n originalFileName: item.json.name || 'unknown',\n fileId: item.json.id || '',\n processedAt: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "8a31a825-1ea4-4619-ab09-8f29b55cab0e",
"name": "Done - no deadline",
"type": "n8n-nodes-base.noOp",
"notes": "End of flow for documents with no deadline",
"position": [
880,
272
],
"parameters": {},
"typeVersion": 1
},
{
"id": "9f492a60-3d6c-487c-8d0d-4b0230a5e2e4",
"name": "When clicking 'Execute workflow'",
"type": "n8n-nodes-base.manualTrigger",
"notes": "Run this workflow manually or replace with a Schedule Trigger for automation",
"position": [
-2352,
400
],
"parameters": {},
"typeVersion": 1
},
{
"id": "4a172b75-e050-46a9-9f2e-8423a3ea355c",
"name": "Get inbox files",
"type": "n8n-nodes-base.googleDrive",
"notes": "Fetches all files from the inbox folder \u2014 set YOUR_INBOX_FOLDER_ID to your folder",
"position": [
-2128,
400
],
"parameters": {
"filter": {},
"options": {},
"resource": "fileFolder",
"returnAll": true,
"queryString": "'YOUR_INBOX_FOLDER_ID' in parents and mimeType != 'application/vnd.google-apps.folder'",
"searchMethod": "query"
},
"typeVersion": 3
},
{
"id": "2830461a-76cd-44c5-9e9e-cc6bb67f7498",
"name": "Loop through files",
"type": "n8n-nodes-base.splitInBatches",
"notes": "Processes files one at a time to avoid API rate limits",
"position": [
-1904,
400
],
"parameters": {
"options": {}
},
"typeVersion": 3
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "37bb1105-f23b-44b8-bd17-5357f3a5b0d2",
"connections": {
"Rename file": {
"main": [
[
{
"node": "Move to folder",
"type": "main",
"index": 0
}
]
]
},
"Download file": {
"main": [
[
{
"node": "Check file type",
"type": "main",
"index": 0
}
]
]
},
"Has deadline?": {
"main": [
[
{
"node": "Add to calendar",
"type": "main",
"index": 0
}
],
[
{
"node": "Done - no deadline",
"type": "main",
"index": 0
}
]
]
},
"Move to folder": {
"main": [
[
{
"node": "Log to spreadsheet",
"type": "main",
"index": 0
}
]
]
},
"Add to calendar": {
"main": [
[
{
"node": "Send deadline alert",
"type": "main",
"index": 0
}
]
]
},
"Check file type": {
"main": [
[
{
"node": "Convert to Base64",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert to Base64",
"type": "main",
"index": 0
}
],
[
{
"node": "Handle unsupported format",
"type": "main",
"index": 0
}
]
]
},
"Get inbox files": {
"main": [
[
{
"node": "Loop through files",
"type": "main",
"index": 0
}
]
]
},
"Convert to Base64": {
"main": [
[
{
"node": "Gemini OCR classification",
"type": "main",
"index": 0
}
]
]
},
"Generate filename": {
"main": [
[
{
"node": "Rename file",
"type": "main",
"index": 0
}
]
]
},
"Parse AI response": {
"main": [
[
{
"node": "Classification check",
"type": "main",
"index": 0
}
]
]
},
"Log to spreadsheet": {
"main": [
[
{
"node": "Has deadline?",
"type": "main",
"index": 0
},
{
"node": "Loop through files",
"type": "main",
"index": 0
}
]
]
},
"Loop through files": {
"main": [
[],
[
{
"node": "Download file",
"type": "main",
"index": 0
}
]
]
},
"Classification check": {
"main": [
[
{
"node": "Generate filename",
"type": "main",
"index": 0
}
],
[
{
"node": "Send error notification",
"type": "main",
"index": 0
},
{
"node": "Loop through files",
"type": "main",
"index": 0
}
]
]
},
"Send error notification": {
"main": [
[
{
"node": "Log error to sheet",
"type": "main",
"index": 0
}
]
]
},
"Gemini OCR classification": {
"main": [
[
{
"node": "Parse AI response",
"type": "main",
"index": 0
}
]
]
},
"Handle unsupported format": {
"main": [
[
{
"node": "Send error notification",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Get inbox files",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Accountants and office managers who want to automatically classify and organize documents in Google Drive.
Source: https://n8n.io/workflows/15866/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Domain Outbound Machine is an n8n workflow designed to fully automate the domain sales process: lead generation, email extraction, personalized outreach, and automated email sending. It also stores ex
Transform your receipt management with this comprehensive n8n workflow that automatically processes receipts through Telegram, extracts transaction data using AI, and stores it across multiple platfor
This workflow is perfect for eCommerce teams, market researchers, and product analysts who want to track or extract product information from websites that restrict scraping tools. It’s also useful for
This workflow is for eCommerce researchers, affiliate marketers, and anyone who needs to compare product listings across sites like Amazon. It’s perfect for quickly identifying top product picks based
Secretary — Gmail Manager (gelsonmascarenhas@gmail.com). Uses gmailTrigger, httpRequest, googleCalendar, gmail. Event-driven trigger; 47 nodes.