This workflow corresponds to n8n.io template #14978 — we link there as the canonical source.
This workflow follows the Gmail Trigger → Google Drive 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": "",
"meta": {
"templateCredsSetupCompleted": false
},
"name": "Smart Mailroom Workflow powered by easybits",
"tags": [],
"nodes": [
{
"id": "ceccb0f1-f81f-4e04-9865-b0b8e1d6d912",
"name": "Extractor: Purchase Orders",
"type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
"position": [
1264,
224
],
"parameters": {},
"typeVersion": 2
},
{
"id": "236c284d-88ac-42d7-bb83-880796b11c8a",
"name": "Gmail Trigger",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
-144,
0
],
"parameters": {
"simple": false,
"filters": {},
"options": {
"downloadAttachments": true
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"typeVersion": 1.3
},
{
"id": "9456f8f9-d8e9-4f44-9f18-7a9c760c997f",
"name": "easybits: Classify Document",
"type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
"position": [
208,
0
],
"parameters": {},
"typeVersion": 2
},
{
"id": "85bbb969-0d38-4e17-a423-49e9740fbadb",
"name": "Route by Document Type",
"type": "n8n-nodes-base.switch",
"position": [
560,
-16
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "02cfff2d-74a3-45c7-b655-d5c1efa10047",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.document_class }}",
"rightValue": "Invoice"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ade45c05-8ed4-4cdf-98dd-b8d12734e191",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.document_class }}",
"rightValue": "Contracts"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "fef9adea-263b-424c-9be7-4d453dbafae3",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.document_class }}",
"rightValue": "Purchase Orders"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.4
},
{
"id": "7d28879f-8133-4d71-9570-df13ce423cd3",
"name": "Merge: Invoice Binary",
"type": "n8n-nodes-base.merge",
"position": [
912,
-240
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "85b5d486-60c1-4a61-84d2-915f30fe0423",
"name": "Merge: Contract Binary",
"type": "n8n-nodes-base.merge",
"position": [
912,
0
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "969b35c6-c5ea-4de0-9c69-905ba1eebb36",
"name": "Merge: Purchase Order Binary",
"type": "n8n-nodes-base.merge",
"position": [
912,
224
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "59e7334f-2d44-4bdd-9b88-661ecf480de3",
"name": "easybits: Extract Invoice",
"type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
"position": [
1264,
-240
],
"parameters": {},
"typeVersion": 2
},
{
"id": "1e853791-89d8-4dc3-af3b-77f4691e7457",
"name": "easybits: Extract Contract",
"type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
"position": [
1264,
0
],
"parameters": {},
"typeVersion": 2
},
{
"id": "815a5109-5696-4175-9b39-136ec2f694a2",
"name": "Merge: Invoice Data + File",
"type": "n8n-nodes-base.merge",
"position": [
1616,
-240
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "bcd1f111-90a6-466c-b575-e1c7acc292a6",
"name": "Merge: Contract Data + File",
"type": "n8n-nodes-base.merge",
"position": [
1616,
0
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "3bef4105-24ea-4fc3-95c8-9537aa769cc4",
"name": "Merge: Purchase Order Data + File",
"type": "n8n-nodes-base.merge",
"position": [
1616,
224
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "020e35dc-3e3c-46fa-beff-dff13ae8a2b6",
"name": "Upload Invoice to Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
1968,
-240
],
"parameters": {
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_FOLDER_ID",
"cachedResultUrl": "",
"cachedResultName": "YOUR_FOLDER_NAME"
},
"inputDataFieldName": "attachment_0"
},
"typeVersion": 3
},
{
"id": "2b37b79b-7241-4a51-bf1b-a18000a8612f",
"name": "Upload Contract to Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
1968,
0
],
"parameters": {
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
}
},
"typeVersion": 3
},
{
"id": "e6d5b804-9f5c-4254-8978-851a3941317b",
"name": "Upload Purchase Order to Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
1968,
224
],
"parameters": {
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
}
},
"typeVersion": 3
},
{
"id": "85daecdd-24d1-4e2b-818b-de5f4ea6389e",
"name": "Update Master Finance Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2320,
-240
],
"parameters": {
"columns": {
"value": {
"Invoice Number": "={{ $('Merge: Invoice Data + File').item.json.data.invoice_number }}",
"Final Amount (EUR)": "={{ $('Merge: Invoice Data + File').item.json.data.total_amount }}"
},
"schema": [
{
"id": "Invoice Number",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Invoice Number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Original Amount",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Original Amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Currency",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Exchange Rate",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Exchange Rate",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Final Amount (EUR)",
"type": "string",
"display": true,
"required": false,
"displayName": "Final Amount (EUR)",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Invoice Number"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SPREADSHEET_ID",
"cachedResultUrl": "",
"cachedResultName": "YOUR_SPREADSHEET_NAME"
}
},
"typeVersion": 4.7
},
{
"id": "2c3da541-18e2-4379-b2f1-8596d15d6636",
"name": "Slack: Notify Sales \u2013 New Contract",
"type": "n8n-nodes-base.slack",
"position": [
2320,
0
],
"parameters": {
"select": "channel",
"blocksUi": "=:page_facing_up: *New Contract Received*\n\n*Client:* {{ $('Merge: Contract Data + File').item.json.data.client_name }}\n*Type:* {{ $('Merge: Contract Data + File').item.json.data.contract_type }}\n*Value:* {{ $('Merge: Contract Data + File').item.json.data.contract_value }} {{ $('Merge: Contract Data + File').item.json.data.currency }}\n*Start Date:* {{ $('Merge: Contract Data + File').item.json.data.start_date }}\n*Notice Period:* {{ $('Merge: Contract Data + File').item.json.data.notice_period }}\n\n:file_folder: <{{ $('Upload Contract to Drive').item.json.webViewLink }}|View in Drive>",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_CHANNEL_ID",
"cachedResultName": "YOUR_CHANNEL_NAME"
},
"messageType": "block",
"otherOptions": {}
},
"typeVersion": 2.4
},
{
"id": "2a4d8c2f-90fc-48cc-97e1-bd9eee092b88",
"name": "Slack: Notify Team \u2013 Restock Update",
"type": "n8n-nodes-base.slack",
"position": [
2320,
224
],
"parameters": {
"select": "channel",
"blocksUi": "=:package: *New Purchase Order Filed*\n\n*Supplier:* {{ $('Merge: Purchase Order Data + File').item.json.data.supplier_name }}\n*PO Number:* {{ $('Merge: Purchase Order Data + File').item.json.data.po_number }}\n*Order Date:* {{ $('Merge: Purchase Order Data + File').item.json.data.order_date }}\n*Expected Delivery:* {{ $('Merge: Purchase Order Data + File').item.json.data.expected_delivery_date }}\n*Total:* {{ $('Merge: Purchase Order Data + File').item.json.data.total_amount }} {{ $('Merge: Purchase Order Data + File').item.json.data.currency }}\n\n:file_folder: <{{ $('Upload Purchase Order to Drive').item.json.webViewLink }}|View in Drive>",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_CHANNEL_ID",
"cachedResultName": "YOUR_CHANNEL_NAME"
},
"messageType": "block",
"otherOptions": {}
},
"typeVersion": 2.4
},
{
"id": "4f4b838e-f861-4d3a-bf88-43359618d52c",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-256,
-240
],
"parameters": {
"color": 7,
"width": 320,
"height": 432,
"content": "## \ud83d\udce7 Email Intake\nPolls Gmail every minute for new emails. Downloads attachments automatically. The binary file is branched to all merge nodes so the original document stays available throughout the workflow."
},
"typeVersion": 1
},
{
"id": "3eb38c43-2469-4e6a-a82a-bedeafd92efd",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
96,
-240
],
"parameters": {
"color": 7,
"width": 320,
"height": 432,
"content": "## \ud83c\udff7\ufe0f Document Classification\nSends the email attachment to **easybits Extractor** configured for classification. Returns a `document_class` field with one of three values: `Invoice`, `Contracts`, or `Purchase Orders`. The Switch node routes the item down the matching path."
},
"typeVersion": 1
},
{
"id": "88cd89d2-fc71-4a84-9628-b3ba7b99215b",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
448,
-240
],
"parameters": {
"color": 7,
"width": 320,
"height": 432,
"content": "## \ud83d\udd00 Route by Document Type\nReads the `document_class` returned by the classification step and routes the item to the matching path: **Invoice**, **Contract**, or **Purchase Order**. Each output connects to its own extraction and delivery pipeline."
},
"typeVersion": 1
},
{
"id": "5f85c781-64da-404c-96cc-d5dc19376aed",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
-464
],
"parameters": {
"color": 7,
"width": 320,
"height": 896,
"content": "## \ud83d\udd17 Merge: Restore Original File\nThe classification step strips the binary from the item. These Merge nodes reunite the original email attachment (from the Gmail Trigger) with the routed item so the Extractor receives both the document class and the actual file."
},
"typeVersion": 1
},
{
"id": "06654027-24a1-4348-9830-fbd1b5e2a1c0",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1152,
-464
],
"parameters": {
"color": 7,
"width": 320,
"height": 896,
"content": "## \ud83e\udd16 Document-Specific Extraction\nEach route has its own **easybits Extractor** pipeline configured for that document type. Invoices extract vendor, amount, due date. Contracts extract client, value, notice period. Purchase Orders extract supplier, items, delivery date."
},
"typeVersion": 1
},
{
"id": "a5221886-245e-45ca-ba5c-cf7104ee95d4",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1504,
-464
],
"parameters": {
"color": 7,
"width": 320,
"height": 896,
"content": "## \ud83d\udd17 Merge: Combine Extracted Data + File\nThe Extractor returns structured JSON but strips the binary again. These Merge nodes recombine the extracted data with the original file so the Google Drive upload node has both the file to store and the JSON to pass downstream."
},
"typeVersion": 1
},
{
"id": "abbe021c-c4e6-412f-aeda-3c8db5a2b6b8",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1856,
-464
],
"parameters": {
"color": 7,
"width": 320,
"height": 896,
"content": "## \u2601\ufe0f Upload to Google Drive\nStores the original document in a dedicated folder per type: **Invoices**, **Contracts**, or **Purchase Orders**. The Drive link is passed to the next node for reference in Sheets or Slack."
},
"typeVersion": 1
},
{
"id": "a58997cf-579c-4dbe-a45e-266959e4a897",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
2208,
-464
],
"parameters": {
"color": 7,
"width": 320,
"height": 896,
"content": "## \ud83d\udce4 Notify & Log\nEach route ends with a different action: **Invoices** are appended to the Master Finance Sheet. **Contracts** trigger a Slack message to Mike with key terms and a Drive link. **Purchase Orders** post a restock update to the team channel."
},
"typeVersion": 1
},
{
"id": "89143657-a827-49b0-8c65-44f303ced5ac",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1136,
-736
],
"parameters": {
"width": 848,
"height": 1520,
"content": "# \ud83d\udcec Smart Mailroom: Auto-Classify & Route Documents with easybits\n\n## What This Workflow Does\nReceive any business document via email. The attachment is automatically **classified** (Invoice, Contract, or Purchase Order) using easybits Extractor, then **routed** down the correct path where a second Extractor pulls out document-specific data. Each route stores the file in Google Drive and triggers the appropriate action \u2013 Invoices go to a finance spreadsheet, Contracts and Purchase Orders trigger Slack notifications.\n\n## How It Works\n1. **Receive** \u2013 Gmail polls for new emails with attachments every minute\n2. **Classify** \u2013 easybits Extractor identifies the document type and returns a class label\n3. **Route** \u2013 A Switch node sends the item down the matching path (Invoice / Contract / PO)\n4. **Merge Binary** \u2013 The original file is merged back into the routed item (classification strips the binary)\n5. **Extract** \u2013 A second easybits Extractor pulls fields specific to that document type\n6. **Merge Data + File** \u2013 Extracted JSON and original binary are combined for upload\n7. **Store & Notify** \u2013 The file is uploaded to Google Drive; Invoices update a spreadsheet, Contracts and POs trigger Slack alerts\n\n---\n\n## Setup Guide\n\n### 1. Create Your easybits Classification Pipeline\n1. Go to **extractor.easybits.tech** and create a new pipeline\n2. Add **one field** called `document_class`\n3. In the field prompt, describe your classification categories and how to identify each one\n4. The prompt should instruct the model to return exactly one category label \u2013 no explanations, no extra text\n5. Adjust the categories and identification criteria to match your specific document types\n6. Copy your **Pipeline ID** and your **API Key** and connect the credential in the document classification node\n\n> \ud83d\udca1 **Tip:** The classification prompt is the heart of this workflow. The more specific your category descriptions and decision rules are, the more accurate your results will be.\n\n### 2. Create Three Extraction Pipelines\nCreate one pipeline per document type on **extractor.easybits.tech**:\n- **Invoice pipeline** \u2013 fields: `invoice_number`, `total_amount`, `currency`, `due_date`, `vendor_name`\n- **Contract pipeline** \u2013 fields: `client_name`, `contract_type`, `contract_value`, `currency`, `start_date`, `notice_period`\n- **Purchase Order pipeline** \u2013 fields: `supplier_name`, `po_number`, `order_date`, `expected_delivery_date`, `total_amount`, `currency`\n\nConnect each pipeline's credentials to the matching Extractor node.\n\n### 3. Set Up Gmail\nConnect your Gmail account via OAuth2. Optionally filter by label to only process specific emails. Make sure **Download Attachments** is enabled in the node options.\n\n### 4. Set Up Google Drive\nCreate three folders in Google Drive: **Invoices**, **Contracts**, **Purchase Orders**. Select the correct folder in each Upload node. Set the **Input Binary Field** to `attachment_0` (or whichever field carries the PDF).\n\n### 5. Set Up Google Sheets\nCreate a spreadsheet (or use an existing Master Finance File). Make sure the column headers match the field mappings in the \"Update Master Finance Sheet\" node.\n\n### 6. Set Up Slack\nConnect your Slack workspace. Select the channel for contract notifications (e.g. `#contracts`) and the channel for PO updates (e.g. `#operations`). Adjust the message templates if your extracted field names differ.\n\n### 7. Activate & Test\nSet the workflow to active and send a test email with an invoice, contract, and purchase order attached to verify each route works end to end."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "",
"connections": {
"Gmail Trigger": {
"main": [
[
{
"node": "easybits: Classify Document",
"type": "main",
"index": 0
},
{
"node": "Merge: Invoice Binary",
"type": "main",
"index": 0
},
{
"node": "Merge: Invoice Data + File",
"type": "main",
"index": 0
},
{
"node": "Merge: Contract Binary",
"type": "main",
"index": 0
},
{
"node": "Merge: Purchase Order Binary",
"type": "main",
"index": 1
},
{
"node": "Merge: Contract Data + File",
"type": "main",
"index": 0
},
{
"node": "Merge: Purchase Order Data + File",
"type": "main",
"index": 1
}
]
]
},
"Merge: Invoice Binary": {
"main": [
[
{
"node": "easybits: Extract Invoice",
"type": "main",
"index": 0
}
]
]
},
"Merge: Contract Binary": {
"main": [
[
{
"node": "easybits: Extract Contract",
"type": "main",
"index": 0
}
]
]
},
"Route by Document Type": {
"main": [
[
{
"node": "Merge: Invoice Binary",
"type": "main",
"index": 1
}
],
[
{
"node": "Merge: Contract Binary",
"type": "main",
"index": 1
}
],
[
{
"node": "Merge: Purchase Order Binary",
"type": "main",
"index": 0
}
]
]
},
"Upload Invoice to Drive": {
"main": [
[
{
"node": "Update Master Finance Sheet",
"type": "main",
"index": 0
}
]
]
},
"Upload Contract to Drive": {
"main": [
[
{
"node": "Slack: Notify Sales \u2013 New Contract",
"type": "main",
"index": 0
}
]
]
},
"easybits: Extract Invoice": {
"main": [
[
{
"node": "Merge: Invoice Data + File",
"type": "main",
"index": 1
}
]
]
},
"Extractor: Purchase Orders": {
"main": [
[
{
"node": "Merge: Purchase Order Data + File",
"type": "main",
"index": 0
}
]
]
},
"Merge: Invoice Data + File": {
"main": [
[
{
"node": "Upload Invoice to Drive",
"type": "main",
"index": 0
}
]
]
},
"easybits: Extract Contract": {
"main": [
[
{
"node": "Merge: Contract Data + File",
"type": "main",
"index": 1
}
]
]
},
"Merge: Contract Data + File": {
"main": [
[
{
"node": "Upload Contract to Drive",
"type": "main",
"index": 0
}
]
]
},
"easybits: Classify Document": {
"main": [
[
{
"node": "Route by Document Type",
"type": "main",
"index": 0
}
]
]
},
"Merge: Purchase Order Binary": {
"main": [
[
{
"node": "Extractor: Purchase Orders",
"type": "main",
"index": 0
}
]
]
},
"Upload Purchase Order to Drive": {
"main": [
[
{
"node": "Slack: Notify Team \u2013 Restock Update",
"type": "main",
"index": 0
}
]
]
},
"Merge: Purchase Order Data + File": {
"main": [
[
{
"node": "Upload Purchase Order to Drive",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Receive any business document via email. The attachment is automatically classified (Invoice, Contract, or Purchase Order) using easybits Extractor, then routed down the correct path where a second Extractor pulls out document-specific data. Each route stores the file in Google…
Source: https://n8n.io/workflows/14978/ — 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.
This template is built to be customized for your specific needs. This template has the core logic and n8n node specific references sorted to work with dynamic file names throughout the workflow. Store
Automatically convert Gmail emails and Slack messages into Zendesk support tickets with intelligent priority detection, comprehensive Google Sheets tracking, and real-time team notifications. Streamli
This is an elite enterprise-grade solution for Talent Acquisition and HR Ops teams. It automates the high-volume task of resume screening by transforming unstructured PDF applications into structured
📘 Description
Watches your support inbox, classifies every incoming email by category, scores it for priority based on sentiment and urgency signals, and posts a clean summary to the matching Slack channel. Works e