This workflow corresponds to n8n.io template #13071 — we link there as the canonical source.
This workflow follows the Airtable → 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": "omGegE9vPd6v03RM",
"name": "Invoice Generation System",
"tags": [],
"nodes": [
{
"id": "18b67cf7-0177-424a-b834-3dd143d177a8",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
112,
-384
],
"parameters": {
"path": "your-webhook-path",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "536218fd-ccb3-465d-9e98-ad4171e464dc",
"name": "Create a record1",
"type": "n8n-nodes-base.airtable",
"position": [
112,
48
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "YOUR_AIRTABLE_BASE_ID",
"cachedResultName": "Your Airtable Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "YOUR_INVOICE_TABLE_ID",
"cachedResultName": "Factura"
},
"columns": {
"value": {
"Date": "={{ $('Webhook').first().json.body.date }}",
"Client": "={{ $('Webhook').first().json.body.clientId }}",
"Service": "={{ $('Formatting Data').first().json.id }}",
"Invoice #": "={{ $('Generate Invoice #').item.json.nextInvoiceNumber }}"
},
"schema": [
{
"id": "Invoice #",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Invoice #",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Client",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Service",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Service",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total_Taxable_Base",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "Total_Taxable_Base",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total VAT",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "Total VAT",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Retention",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "Total Retention",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "Total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Invoice",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Invoice",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total_Taxable_Base (from Servicio)",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "Total_Taxable_Base (from Servicio)",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total (from Servicio)",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "Total (from Servicio)",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Service Description",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Service Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total VAT (from Servicio)",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "Total VAT (from Servicio)",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Retention (from Servicio)",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "Total Retention (from Servicio)",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"typecast": true
},
"operation": "create"
},
"typeVersion": 2.1
},
{
"id": "fc3fc580-c2ae-4eaa-9434-18bab1dd1642",
"name": "Add Service to DB",
"type": "n8n-nodes-base.airtable",
"position": [
560,
-384
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "YOUR_AIRTABLE_BASE_ID",
"cachedResultName": "Your Airtable Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "YOUR_SERVICE_TABLE_ID",
"cachedResultName": "Servicio"
},
"columns": {
"value": {
"VAT": "={{ $json.vat }}",
"Units": "={{ $json.units }}",
"Value": "={{ $json.price }}",
"Retention": "={{ $json.retention }}",
"Description": "={{ $json.description }}"
},
"schema": [
{
"id": "Description",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Value",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Value",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Units",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Units",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "VAT",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "VAT",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Retention",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Retention",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "Total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Factura",
"type": "array",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Factura",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "create"
},
"typeVersion": 2.1
},
{
"id": "3e0cc576-d6e4-49ef-ae96-1e72451a0e45",
"name": "Split Services",
"type": "n8n-nodes-base.splitOut",
"position": [
336,
-384
],
"parameters": {
"options": {},
"fieldToSplitOut": "body.services"
},
"typeVersion": 1
},
{
"id": "e1c5aa9f-2687-493f-b719-8250f73ded7a",
"name": "Formatting Data",
"type": "n8n-nodes-base.code",
"position": [
784,
-384
],
"parameters": {
"jsCode": "// n8n Code Node - Transform Airtable data to array format with formatting\n\nconst items = $input.all();\n\nconst ids = [];\nconst values = [];\n\nfor (const item of items) {\n const data = item.json;\n ids.push(data.id);\n\n const fields = data.fields;\n\n const formattedValue = fields.Value.toFixed(2) + '\u20ac';\n const formattedUnits = fields.Units;\n const formattedVAT = fields.VAT + '%';\n const formattedRetention = fields.Retention === 0 ? '0%' : '-' + fields.Retention + '%';\n const formattedTotal = fields.Total.toFixed(2) + '\u20ac';\n\n const valueArray = [\n fields.Description,\n formattedValue,\n formattedUnits,\n formattedVAT,\n formattedRetention,\n formattedTotal\n ];\n\n values.push(valueArray);\n}\n\nreturn {\n json: {\n id: ids,\n values: {\n values: values\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "fd0eb607-53b0-4c2c-b4e5-a9a9a9be49fd",
"name": "Get Previous Invoices",
"type": "n8n-nodes-base.airtable",
"position": [
1008,
-384
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "YOUR_AIRTABLE_BASE_ID",
"cachedResultName": "Your Airtable Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "YOUR_INVOICE_TABLE_ID",
"cachedResultName": "Factura"
},
"options": {},
"operation": "search"
},
"typeVersion": 2.1,
"alwaysOutputData": true
},
{
"id": "061b0353-3969-4111-b3bc-63deb1be87e1",
"name": "Generate Invoice #",
"type": "n8n-nodes-base.code",
"position": [
112,
-176
],
"parameters": {
"jsCode": "// n8n Code Node - Invoice Number Generator (JavaScript)\n\nconst currentYear = new Date().getFullYear();\nconst invoices = $input.all();\n\nlet maxNumber = 0;\n\nfor (const invoice of invoices) {\n const invoiceNum = invoice.json['Invoice #'];\n\n if (invoiceNum) {\n const parts = invoiceNum.split('-');\n\n if (parts.length === 2) {\n const year = parseInt(parts[0]);\n const number = parseInt(parts[1]);\n\n if (year === currentYear && !isNaN(number)) {\n maxNumber = Math.max(maxNumber, number);\n }\n }\n }\n}\n\nconst nextNumber = maxNumber + 1;\nconst paddedNumber = nextNumber.toString().padStart(4, '0');\nconst nextInvoiceNumber = `${currentYear}-${paddedNumber}`;\n\nreturn {\n json: {\n nextInvoiceNumber: nextInvoiceNumber,\n year: currentYear,\n sequenceNumber: nextNumber,\n lastInvoiceNumber: maxNumber > 0 ? `${currentYear}-${maxNumber.toString().padStart(4, '0')}` : 'None'\n }\n};"
},
"typeVersion": 2
},
{
"id": "81ac9e60-1449-4dff-b09a-c8e5e91e1d1c",
"name": "Copy Invoice Template",
"type": "n8n-nodes-base.googleDrive",
"position": [
336,
-176
],
"parameters": {
"name": "={{ $json.nextInvoiceNumber }}_Factura",
"fileId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEETS_TEMPLATE_FILE_ID"
},
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive",
"cachedResultName": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_DRIVE_OUTPUT_FOLDER_ID"
},
"operation": "copy",
"sameFolder": false
},
"typeVersion": 3
},
{
"id": "b5f35fce-d2c9-461e-a581-8b3250748d99",
"name": "Add Services to Invoice",
"type": "n8n-nodes-base.httpRequest",
"position": [
560,
-176
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $json.id }}/values/A19:append",
"method": "POST",
"options": {},
"jsonBody": "={{ $('Formatting Data').first().json.values }}",
"sendBody": true,
"sendQuery": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "valueInputOption",
"value": "USER_ENTERED"
},
{
"name": "insertDataOption",
"value": "INSERT_ROWS"
}
]
},
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "7aeabe32-d087-424a-a12e-89162500ea68",
"name": "Get Client Info",
"type": "n8n-nodes-base.airtable",
"position": [
784,
-176
],
"parameters": {
"id": "={{ $('Webhook').first().json.body.clientId }}",
"base": {
"__rl": true,
"mode": "list",
"value": "YOUR_AIRTABLE_BASE_ID",
"cachedResultName": "Your Airtable Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "YOUR_CLIENT_TABLE_ID",
"cachedResultName": "Client"
},
"options": {}
},
"typeVersion": 2.1
},
{
"id": "4f80ca1f-631e-4cfc-8a12-c433d1b8996c",
"name": "Add Client Info",
"type": "n8n-nodes-base.httpRequest",
"position": [
1008,
-176
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $('Add Services to Invoice').item.json.spreadsheetId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"requests\": [\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"invoice_date\",\n \"replacement\": \"{{ $('Webhook').first().json.body.date }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"invoice_number\",\n \"replacement\": \"{{ $('Generate Invoice #').item.json.nextInvoiceNumber }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"billingName\",\n \"replacement\": \"{{ $json.Name }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"billingId\",\n \"replacement\": \"{{ $json.ID }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"billingAddress\",\n \"replacement\": \"{{ $json.Address }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"billingCity\",\n \"replacement\": \"{{ $json.City }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"billingCountry\",\n \"replacement\": \"{{ $json.Country }}\",\n \"matchEntireCell\": true\n }\n }\n\n ]\n} ",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "c5aa8cf1-76f9-4f3d-8083-58da584563d4",
"name": "Create a record1 (template)",
"type": "n8n-nodes-base.airtable",
"position": [
112,
48
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "YOUR_AIRTABLE_BASE_ID",
"cachedResultName": "Your Airtable Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "YOUR_INVOICE_TABLE_ID",
"cachedResultName": "Factura"
},
"columns": {
"value": {
"Date": "={{ $('Webhook').first().json.body.date }}",
"Client": "={{ $('Webhook').first().json.body.clientId }}",
"Service": "={{ $('Formatting Data').first().json.id }}",
"Invoice #": "={{ $('Generate Invoice #').item.json.nextInvoiceNumber }}"
},
"schema": [
{
"id": "Invoice #",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Invoice #",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Client",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Service",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Service",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Invoice",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Invoice",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"typecast": true
},
"operation": "create"
},
"typeVersion": 2.1
},
{
"id": "687a7047-3202-4992-a20f-f4e268e31f2e",
"name": "Add Invoice Summary Info",
"type": "n8n-nodes-base.httpRequest",
"position": [
336,
48
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $('Add Services to Invoice').item.json.spreadsheetId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"requests\": [\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"total_taxable_base\",\n \"replacement\": \"{{ Number($json.fields.Total_Taxable_Base).toFixed(2) + '\u20ac' }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"total_vat\",\n \"replacement\": \"{{ Number($json.fields['Total VAT']).toFixed(2) + '\u20ac' }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"total_retention\",\n \"replacement\": \"{{'-'+ Number($json.fields['Total Retention']).toFixed(2) + '\u20ac' }}\",\n \"matchEntireCell\": true\n }\n },\n {\n \"findReplace\": {\n \"sheetId\": \"0\",\n \"find\": \"total_total\",\n \"replacement\": \"{{ Number($json.fields.Total).toFixed(2) + '\u20ac' }}\",\n \"matchEntireCell\": true\n }\n }\n\n ]\n} ",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "26ba7f66-02c0-4160-8766-fde3e9af4ad6",
"name": "Share file",
"type": "n8n-nodes-base.googleDrive",
"position": [
560,
48
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.spreadsheetId }}"
},
"options": {},
"operation": "share",
"permissionsUi": {
"permissionsValues": {
"role": "reader",
"type": "anyone"
}
}
},
"typeVersion": 3
},
{
"id": "d4f2a694-b239-48ed-a1b6-6da33e66c30e",
"name": "Update record",
"type": "n8n-nodes-base.airtable",
"position": [
784,
48
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "YOUR_AIRTABLE_BASE_ID",
"cachedResultName": "Your Airtable Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "YOUR_INVOICE_TABLE_ID",
"cachedResultName": "Factura"
},
"columns": {
"value": {
"id": "={{ $('Create a record1').item.json.id }}",
"Invoice": "=[{\"url\":\"https://docs.google.com/spreadsheets/d/{{ $('Add Invoice Summary Info').item.json.spreadsheetId }}/export?format=pdf\"}]"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "id",
"defaultMatch": true
},
{
"id": "Invoice",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Invoice",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update"
},
"typeVersion": 2.1
},
{
"id": "c55694e2-5220-4cfd-aceb-36ae2ca08d39",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-912,
-368
],
"parameters": {
"width": 928,
"height": 720,
"content": "# Automated Invoice Generator (Airtable + Google Sheets)\n\nThis workflow completely automates the invoicing process by turning raw JSON data into a formatted PDF and syncing it with your CRM. It specifically handles **multiple line items**, ensuring detailed breakdowns on your invoices.\n\n### How it works\n1. **Webhook Trigger:** Receives a payload containing a Client ID and a list of Services (items).\n2. **Line Item Processing:** Splits the list of services and creates individual records in your Airtable \"Services\" table.\n3. **Template Generation:** Duplicates a master Google Sheet template, fills in the client details and dynamic service rows, and calculates totals.\n4. **CRM Sync:** Creates a master \"Invoice\" record in Airtable, generates a shareable PDF link from Drive, and attaches the file back to the Airtable record.\n\n### Setup steps\n1. **Airtable:** Create 3 tables (Clients, Invoices, Services) and link them.\nAirtable Template: [https://airtable.com/appUL5P7KN2Kqsgsf/shr5vCMwg2o4Z5wZI](https://airtable.com/appUL5P7KN2Kqsgsf/shr5vCMwg2o4Z5wZI)\n2. **Google Drive:** Create a Google Sheet template with placeholders (e.g., `{{clientName}}`).\nGoogle Sheets Template: [https://docs.google.com/spreadsheets/d/1XF9vcbsgYqDDgQwBn4RNtnzCkBjbk3jmKU7MBgIXtbo/edit?usp=sharing](https://docs.google.com/spreadsheets/d/1XF9vcbsgYqDDgQwBn4RNtnzCkBjbk3jmKU7MBgIXtbo/edit?usp=sharing)\n3. **Credentials:** Connect your Google Drive and Airtable credentials in the respective nodes.\n4. **Webhook:** Ensure your frontend sends a JSON body with `clientId` and an array of `services`.\n\n### \ud83d\udc4b Need help building this? Want to automate & scale your business?\nI help businesses automate their \"boring work\" so they can focus on sales.\n- https://www.linkedin.com/in/sergiomedinah/\n- https://sergio-medina.com/"
},
"typeVersion": 1
},
{
"id": "b0179c1c-51af-48b7-b6c7-af62cae8e6f1",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
-400
],
"parameters": {
"color": 7,
"width": 528,
"content": "## Process Line Items\nIterates through the incoming list of services, logging each one into the Airtable \"Services\" table and preparing the data for the invoice."
},
"typeVersion": 1
},
{
"id": "2636e5e0-c08b-4501-842d-35a4026c0806",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
-208
],
"parameters": {
"color": 7,
"width": 528,
"content": "## Fill Template\nCalculates the new invoice number, duplicates the Google Sheet template, and maps the service rows and client details into the file."
},
"typeVersion": 1
},
{
"id": "1c027410-a3d7-4641-842d-cc25be66df3a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
-16
],
"parameters": {
"color": 7,
"width": 528,
"content": "## Finalize & Sync\nCreates the master Invoice record in Airtable, generates a public PDF link from Google Drive, and attaches the final document to the CRM record."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "95422eca-c691-4c4c-b08e-850e118a3b15",
"connections": {
"Webhook": {
"main": [
[
{
"node": "Split Services",
"type": "main",
"index": 0
}
]
]
},
"Share file": {
"main": [
[
{
"node": "Update record",
"type": "main",
"index": 0
}
]
]
},
"Split Services": {
"main": [
[
{
"node": "Add Service to DB",
"type": "main",
"index": 0
}
]
]
},
"Add Client Info": {
"main": [
[
{
"node": "Create a record1 (template)",
"type": "main",
"index": 0
}
]
]
},
"Formatting Data": {
"main": [
[
{
"node": "Get Previous Invoices",
"type": "main",
"index": 0
}
]
]
},
"Get Client Info": {
"main": [
[
{
"node": "Add Client Info",
"type": "main",
"index": 0
}
]
]
},
"Add Service to DB": {
"main": [
[
{
"node": "Formatting Data",
"type": "main",
"index": 0
}
]
]
},
"Generate Invoice #": {
"main": [
[
{
"node": "Copy Invoice Template",
"type": "main",
"index": 0
}
]
]
},
"Copy Invoice Template": {
"main": [
[
{
"node": "Add Services to Invoice",
"type": "main",
"index": 0
}
]
]
},
"Get Previous Invoices": {
"main": [
[
{
"node": "Generate Invoice #",
"type": "main",
"index": 0
}
]
]
},
"Add Services to Invoice": {
"main": [
[
{
"node": "Get Client Info",
"type": "main",
"index": 0
}
]
]
},
"Add Invoice Summary Info": {
"main": [
[
{
"node": "Share file",
"type": "main",
"index": 0
}
]
]
},
"Create a record1 (template)": {
"main": [
[
{
"node": "Add Invoice Summary Info",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Stop manually copy-pasting client data into Word templates. This workflow automates the entire invoicing process, handling complex line items, VAT calculations, PDF generation, and CRM syncing in under 20 seconds.
Source: https://n8n.io/workflows/13071/ — 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 workflow automatically saves Zoom meeting recordings to Google Drive and logs all important details into Airtable for easy tracking. Perfect for teams that want a searchable meeting archive. Zoom
This premium n8n workflow harnesses the power of DataForSEO's API combined with Airtable's relational database capabilities to transform your keyword research process, providing deeper insights for co
This workflow automates the entire lifecycle of a service-based client, combining four distinct business flows into a single view: Intake Leads: Receives a webhook from your form builder, validates th
It intelligently syncs confirmed sales orders from your Airtable base to QuickBooks, automatically creating new customers if they don't exist before generating a perfectly matched invoice. It then log