Two-way property repair management system with Google Sheets & Drive
Pull contacts, verify each address with BillionVerify, and continue to Google Sheets — only deliverable addresses get through.
Why verify before the send
Sending to invalid, risky, catch-all, or disposable addresses spikes your bounce rate and erodes sender reputation. A verification gate before the Google Sheets step removes that risk automatically — only deliverable addresses continue, the rest are flagged.
The workflow
BillionVerify — verification sits right before the send.
Node by node
- 1New repair form submittedTrigger· n8n
Starts the workflow — on a schedule, a webhook, or manually while you test.
- 2REPLACE w/ N8N FORM trigger.Trigger· n8n
Starts the workflow — on a schedule, a webhook, or manually while you test.
- 3Isolate new entrySource· n8n
Provides or transforms the contact data flowing through the workflow.
- 4IfLogic· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 5Get row(s) in sheetSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 6Format DataSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 7Separate Photo FilesSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 8New detailsSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 9Existing DetailsSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 10Verify Email (BillionVerify) 2Verify· billionverify
The BillionVerify node verifies the address — status (valid / invalid / risky / catch-all / role / disposable), is_deliverable, and a confidence score — before anything is sent.
- 11Add UUID #Source· n8n
Provides or transforms the contact data flowing through the workflow.
- 12Photo UploadingSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 13Merge DataSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 14IF deliverable 2Logic· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 15Combine Photo URLsSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 16Upload Repair PhotoSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 17Update w/ RepairSource· n8n
Provides or transforms the contact data flowing through the workflow.
- 18Report Alert + InfoSend· n8n
Sends only to verified, deliverable addresses. Swap in your own provider node if you send elsewhere.
- 19Verify Email (BillionVerify)Verify· billionverify
The BillionVerify node verifies the address — status (valid / invalid / risky / catch-all / role / disposable), is_deliverable, and a confidence score — before anything is sent.
- 20IF deliverableLogic· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 21Send a messageSend· n8n
Sends only to verified, deliverable addresses. Swap in your own provider node if you send elsewhere.
Workflow JSON
Copy or download this workflow, then import it in n8n (Workflows → Import from File / Paste). Install the BillionVerify community node first, then add your API key credential.
{
"name": "Two-way property repair management system with Google Sheets & Drive + BillionVerify",
"nodes": [
{
"id": "11681c1a-101b-4571-a356-50953964986f",
"name": "Get row(s) in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-240,
-384
],
"parameters": {
"options": {
"returnFirstMatch": "={{ true }}"
},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json['UUID:'] }}",
"lookupColumn": "Unique Unit ID"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1646368885,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit#gid=1646368885",
"cachedResultName": "Form Responses 7"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit?usp=drivesdk",
"cachedResultName": "Repair Request Log"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "credential-id",
"name": "googleSheetsOAuth2Api Credential"
}
},
"typeVersion": 4.7
},
{
"id": "77c2411e-5798-412a-8973-0008236ba01a",
"name": "Upload Repair Photo",
"type": "n8n-nodes-base.googleDrive",
"position": [
-240,
48
],
"parameters": {
"name": "=Repair Photo-{{ $('On form submission').item.json['UUID:'] }}-{{ $('On form submission').item.json.nameDate }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive",
"cachedResultUrl": "https://drive.google.com/drive/my-drive",
"cachedResultName": "My Drive"
},
"options": {
"simplifyOutput": false
},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1YoLmXkOmch_GRUmFd4UxUKzbYFlXSxC0",
"cachedResultUrl": "https://drive.google.com/drive/folders/1YoLmXkOmch_GRUmFd4UxUKzbYFlXSxC0",
"cachedResultName": "Pictures of Repairs"
},
"inputDataFieldName": "=data"
},
"typeVersion": 3
},
{
"id": "b9cb0d25-7952-4f45-b4eb-0543fc77d1cc",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1392,
-64
],
"parameters": {
"width": 352,
"height": 208,
"content": "## Repair Updates Submitted\n\n-PRODUCTION URL must be in \"Repair Request\" email at end of Workflow 1. \n-Repair categories/questions set as FIELD NAMES in this node as.\n"
},
"typeVersion": 1
},
{
"id": "47975fa7-8e24-41d9-a025-e8ec03310ddd",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-304,
272
],
"parameters": {
"color": 4,
"content": "## Google Drive\n\n### -Add Drive Credential\n### -Select folder for photo storage\n\n"
},
"typeVersion": 1
},
{
"id": "0bd21377-576f-42af-a354-2d98f97e96b7",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-304,
-592
],
"parameters": {
"color": 4,
"content": "## Sheets:\n\n### -Google Sheets Credential\n### -Use UUID to collect row info\n\n"
},
"typeVersion": 1
},
{
"id": "00b9d433-c56f-486d-9c6b-91ca0e32bbf4",
"name": "New details",
"type": "n8n-nodes-base.set",
"position": [
-16,
-208
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1bf4ffbd-5db2-47e7-bc0a-6e2b07574776",
"name": "UUID",
"type": "string",
"value": "={{ $('On form submission').first().json['UUID:'] }}"
},
{
"id": "359c4abd-676f-4678-be20-cfaddf6d37c4",
"name": "Action-new",
"type": "string",
"value": "={{ $('On form submission').first().json.Action }}"
},
{
"id": "dbe7bd55-c3cd-41a1-9f54-727647427f86",
"name": "nameDate-new",
"type": "string",
"value": "={{ $('On form submission').first().json.nameDate }}"
},
{
"id": "3bd6bb3c-13a1-4fb1-b56f-cdc53697d593",
"name": "repairPhotos-new",
"type": "string",
"value": "={{ $json.photosCombined || \"\"}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a644df42-331a-4fef-88a0-cda9821f16c4",
"name": "Send a message",
"type": "n8n-nodes-base.gmail",
"position": [
656,
-304
],
"webhookId": "724cea8a-3d0e-41e3-947e-fe92b4bd5b49",
"parameters": {
"message": "=<a href=[ADD LINK TO SPREADSHEET]><h3>Vew Repair Log</h3></a>\n\n<strong>UUID:</strong> {{ $json['Unique Unit ID'] }}<br>\n<strong>Action:</strong> {{ $('Merge Data').item.json['Action-new']}}<br>\n<strong>Completed by:</strong> {{ $('Merge Data').item.json['nameDate-new'] }}<br>",
"options": {},
"subject": "=Repair update submitted\n"
},
"typeVersion": 2.1
},
{
"id": "c913659d-a113-4175-9aa3-7de57e880f69",
"name": "Photo Uploading",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-480,
-48
],
"parameters": {
"options": {
"reset": false
}
},
"typeVersion": 3
},
{
"id": "8c2da542-c8df-458f-ae8d-1da2ad0b31ae",
"name": "Combine Photo URLs",
"type": "n8n-nodes-base.code",
"position": [
-240,
-144
],
"parameters": {
"jsCode": "const delimiter = ', '; // change to '\\n' if you prefer newlines\n\n// Extract all webViewLinks from incoming items\nconst links = items\n .map(i => i.json?.webViewLink)\n .filter(Boolean);\n\n// Optional: de-duplicate links in case upstream created duplicates\nconst uniqueLinks = Array.from(new Set(links));\n\n// Create a single output item\nreturn [\n {\n json: {\n photosCombined: uniqueLinks.join(delimiter),\n // If you also need arrays downstream:\n photosArray: uniqueLinks\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "440dace7-d0a6-4fda-b859-1249f3fe6842",
"name": "Separate Photo Files",
"type": "n8n-nodes-base.code",
"position": [
-688,
-128
],
"parameters": {
"jsCode": "const output = [];\n\nfor (const [key, value] of Object.entries(items[0].binary || {})) {\n // Get original extension if available, fallback to mime type-derived\n const originalName = value.fileName || 'unknown';\n const extension = originalName.includes('.')\n ? originalName.split('.').pop()\n : (value.mimeType?.split('/')[1] || 'bin');\n const fileName = originalName.includes('.')\n ? originalName\n : `unknown.${extension}`;\n\n output.push({\n binary: {\n data: value\n },\n json: {\n originalKey: key,\n fileName: fileName,\n mimeType: value.mimeType || 'unknown'\n }\n });\n}\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "08ab3686-6014-4f3d-af09-e40f07e59bad",
"name": "Merge Data",
"type": "n8n-nodes-base.merge",
"position": [
208,
-304
],
"parameters": {
"mode": "combine",
"options": {},
"joinMode": "keepEverything",
"fieldsToMatchString": "UUID"
},
"typeVersion": 3.2,
"alwaysOutputData": true
},
{
"id": "8b0e5ea5-fa63-415a-8b2e-10c5f387a2a8",
"name": "Update w/ Repair",
"type": "n8n-nodes-base.googleSheets",
"position": [
432,
-304
],
"parameters": {
"columns": {
"value": {
"Action": "={{ $json.Action }}, {{ $json['Action-new'] }}",
"Name/Date": "={{ $json.nameDate }} ,{{ $json['nameDate-new'] }}",
"Repair Photos": "={{ $json.repairPhotos }}, {{ $json['repairPhotos-new'] }}",
"Unique Unit ID": "={{ $json.UUID }}"
},
"schema": [
{
"id": "Unique Unit ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Unique Unit ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timestamp",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Building Address",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Building Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Unit Number ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Unit Number ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Urgency",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Urgency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone Number:",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Phone Number:",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name on Messenger",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name on Messenger",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "In Person ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "In Person ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Best days/times to reach you ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Best days/times to reach you ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "What is this regarding?",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "What is this regarding?",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Please explain the situation.",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Please explain the situation.",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Pictures/Video of issue",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Pictures/Video of issue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Any feedback or suggestions are welcome:",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Any feedback or suggestions are welcome:",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Action",
"type": "string",
"display": true,
"required": false,
"displayName": "Action",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name/Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Name/Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Repair Photos",
"type": "string",
"display": true,
"required": false,
"displayName": "Repair Photos",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Unique Unit ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1646368885,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit#gid=1646368885",
"cachedResultName": "Form Responses 7"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE"
}
},
"typeVersion": 4.7,
"alwaysOutputData": true
},
{
"id": "1909881c-cc0b-48b2-b919-37b991b8ba7f",
"name": "Existing Details",
"type": "n8n-nodes-base.set",
"position": [
-16,
-368
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1bf4ffbd-5db2-47e7-bc0a-6e2b07574776",
"name": "UUID",
"type": "string",
"value": "={{ $json['Unique Unit ID'] }}"
},
{
"id": "359c4abd-676f-4678-be20-cfaddf6d37c4",
"name": "Action",
"type": "string",
"value": "={{ $json.Action }}"
},
{
"id": "dbe7bd55-c3cd-41a1-9f54-727647427f86",
"name": "nameDate",
"type": "string",
"value": "={{ $json['Name/Date'] }}"
},
{
"id": "3bd6bb3c-13a1-4fb1-b56f-cdc53697d593",
"name": "repairPhotos",
"type": "string",
"value": "={{ $json['Repair Photos'] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c43a5bb2-4914-49ab-8603-73a71897ce76",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
-1040,
-224
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2b7e9e14-1e29-44c5-a2b0-00918dcd0100",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.repairPhotos }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "0830f61e-d52a-41ce-a56b-011282ab855c",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-64,
-32
],
"parameters": {
"color": 4,
"width": 256,
"height": 288,
"content": "## Combine Photo URL(s)\n\n### -Combines URL(s) into single Key so they can be stored in 1 spreadsheet cell. \n\n-maintains organization of repair photos in row with original Repair Request\n\n"
},
"typeVersion": 1
},
{
"id": "90067297-75bf-493a-b26a-46fbaf3b5a11",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
320,
-656
],
"parameters": {
"color": 4,
"width": 368,
"height": 320,
"content": "## Sheets:\n\n### -Google Sheets Credential\n### -Use *TIMESTAMP* as *Column to Match On*\n\n### ‼️Field Names from the FORM SUBMITTED node (trigger), must align with Column headings in the spreadsheet. \n\nEX: Form question: \"repair status\"\nColumn title: \"repair status\"\n\n \n\n"
},
"typeVersion": 1
},
{
"id": "6e0a9646-b30d-4bee-8b36-9bf970462310",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
-144
],
"parameters": {
"color": 4,
"height": 208,
"content": "## Optional Email:\n\n### -Email Credential\n### -Ideal for: \n-Developer to monitor initial project\n-Manager to send updates to Tenant.\n\n"
},
"typeVersion": 1
},
{
"id": "03ac1bd2-e54a-46ce-82d8-709968e9f0b1",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2064,
-512
],
"parameters": {
"width": 640,
"height": 624,
"content": "# Workflow 2:\n\n## **Behind the Scenes:**\n[building manager] Submits information in \"repair update\" form.\n\n\n## How it Works:\n### Top Nodes\n- Uses **UUID** to collect existing info from spreadsheet row. \n### Middle Nodes (False from IF node):\n- if photos submitted, uploads them to gmail folder and passes URL(s) to workflow. Loop because each much be processed separately, and coding blocks to manage naming conventions. \n### Middle (False from IF Node): \n- If no photos, pass on other new info. \n\n### Merge Data Node (new + existing Details)\n- All Data (existing and newly added) collected in **Merge Data** node, then added to spreadsheet. \n- This allows for multiple repair updates to be collected in the same row as the Original Repair Request. \n"
},
"typeVersion": 1
},
{
"id": "7e5035e9-056b-4740-8dbc-2a6601f91959",
"name": "New repair form submitted",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
-736,
-1376
],
"parameters": {
"event": "rowAdded",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1646368885,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit#gid=1646368885",
"cachedResultName": "Form Responses 7"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit?usp=drivesdk",
"cachedResultName": "Repair Request Log"
}
},
"typeVersion": 1
},
{
"id": "890d39b1-8601-4885-8b86-7b846f2be007",
"name": "Isolate new entry",
"type": "n8n-nodes-base.code",
"position": [
-512,
-1376
],
"parameters": {
"jsCode": "const last = items[items.length - 1];\nreturn [last];\n"
},
"typeVersion": 2
},
{
"id": "4486c5f3-adf2-4120-bd2e-9614282b61ab",
"name": "Report Alert + Info",
"type": "n8n-nodes-base.gmail",
"notes": "Message as text (instead of html): \n\nCopy Row ID then click Link to update:\n\nUUID(copy): {{ $json.uniqueUnitId }}\n\n[Update Repair](https://mattpd.app.n8n.cloud/form/302ad4c5-2d21-496c-9e31-d9322566b0f6)\n\n<a href=\"https://mattpd.app.n8n.cloud/form/302ad4c5-2d21-496c-9e31-d9322566b0f6\">Update Repair: {{ $json.uniqueUnitId }}</a>\n\nTEST form info:\nAddress: {{ $json.building }}\nUnit: {{ $json.unit }}\nUrgency: {{ $json.urgency }}\nContact Methods:\n--Email: {{ $json.email }}\n--Messenger: {{ $json.contactMessenger }}\n--Phone: {{ $json.phoneNumber }}\n--In Person: {{ $json.InPerson }}\n----Best Times: {{ $json.availability }}\nCategory: {{ $json.category }}\nExplanation: {{ $json.explanation }}\nPhotos/Video: {{ $json.photosVideos }} \nFeedback/Suggestions: {{ $json.feedbackSuggestions }}\n\n\n[Repair Request Log](https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit?gid=1451848569#gid=1451848569)\n",
"position": [
-48,
-1280
],
"webhookId": "44df98f5-7bd6-4ef9-aa8d-1dc43e7c2c9e",
"parameters": {
"message": "= <h3><p><strong>Copy UUID then click <u> <a href=\"[N8N PRODUCTION FORM LINK\">\n Update Repair</a></u> for repair update form:</strong></p></h3>\n <p>\n <strong>UUID:</strong>\n {{ $json.uniqueUnitId }}\n </p>\n<br>\n <p><h3><u><strong>Request Form Input:</strong></u><br></h3>\n\n <strong>Address:</strong> {{ $json.building }}<br>\n <strong>Unit:</strong> {{ $json.unit }}<br>\n <strong>Urgency:</strong> {{ $json.urgency }}<br>\n <strong>Category:</strong> {{ $json.category }}<br>\n <strong>Explanation:</strong> {{ $json.explanation }}<br>\n <strong>Photos/Video:</strong> {{ $json.photosVideos }}<br>\n <strong>Feedback/Suggestions:</strong> {{ $json.feedbackSuggestions }}\n </p>\n\n\n <p><strong>Contact Methods:</strong>\n <ul style=\"margin: 0 0 12px 18px; padding: 0;\">\n <li><strong>Email:</strong> {{ $json.email }}</li>\n <li><strong>Messenger:</strong> {{ $json.contactMessenger }}</li>\n <li><strong>Phone:</strong> {{ $json.phoneNumber }}</li>\n <li><strong>In Person:</strong> {{ $json.InPerson }}</li>\n <li><strong>Best Times:</strong> {{ $json.availability }}</li>\n </ul></p>\n\n <br>\n <p>\n <h4><a href=\"[ADD LINK TO SPREADSHEET URL]\">\n View Repair Request Log\n </a></h4>\n </p>\n </body>\n</html>\n",
"options": {
"bccList": "",
"appendAttribution": false
},
"subject": "=n8nTESt - Urgency: {{ $json.urgency }}. Service Request @ {{ $json.building }}, Unit{{ $json.unit }}"
},
"typeVersion": 2.1
},
{
"id": "0aa37071-4e50-4bef-a9ed-42430dd7ac69",
"name": "Format Data",
"type": "n8n-nodes-base.set",
"position": [
-304,
-1376
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "32d425d1-8709-4664-9f40-461db6265ed0",
"name": "=uniqueUnitId",
"type": "string",
"value": "={{ $json[\"Building Address\"].replace(/\\s+/g, '').toUpperCase() + '-' + String($json[\"Unit Number \"]).trim() }}"
},
{
"id": "92c16198-22df-4d88-861e-2ac711a979e3",
"name": "=timestamp",
"type": "string",
"value": "={{ $json.Timestamp }}"
},
{
"id": "5025808b-2fc2-4e50-8b0c-a0891ed366c8",
"name": "name",
"type": "string",
"value": "={{ $json.Name }}"
},
{
"id": "e9269d41-7914-4e19-9b1d-1c1f742986fb",
"name": "=building",
"type": "string",
"value": "={{ $json[\"Building Address\"] }}"
},
{
"id": "f6424b20-f420-45d1-8b07-4db653714233",
"name": "=unit",
"type": "string",
"value": "={{ $json[\"Unit Number \"] }}"
},
{
"id": "87e34134-fa0b-47c4-910b-820fe8139e20",
"name": "=urgency",
"type": "string",
"value": "={{ $json.Urgency }}"
},
{
"id": "3ece1551-0d0d-4099-8aa0-e8a9b18acfef",
"name": "=email",
"type": "string",
"value": "={{ $json.Email }}"
},
{
"id": "f65475d0-7cbc-456d-a6c3-d2ec2e05fdcc",
"name": "=phoneNumber",
"type": "string",
"value": "={{ $json[\"Phone Number\"] }}"
},
{
"id": "eb39de6b-bc15-400d-810d-f73610825642",
"name": "=contactMessenger",
"type": "string",
"value": "={{ $json[\"Name on Messenger\"] }}"
},
{
"id": "c2579c8a-d26b-42b1-b562-dfb5b2f7d88f",
"name": "=InPerson",
"type": "string",
"value": "={{ $json[\"In Person \"] }}"
},
{
"id": "2ff412d8-fe2c-4171-b9c0-e068c8ae3045",
"name": "=availability",
"type": "string",
"value": "={{ $json.Availability }}"
},
{
"id": "017c4e1c-db05-47f7-96ff-f1220ca8eb33",
"name": "=category",
"type": "string",
"value": "={{ $json['What is this regarding?'] }}"
},
{
"id": "aafae6b9-f01d-44f2-9f6c-c73cf03ac2eb",
"name": "=explanation",
"type": "string",
"value": "={{ $json[\"Please explain the situation.\"] }}"
},
{
"id": "93a4e87a-54b3-4358-8a55-c1451f3b54cb",
"name": "photosVideos",
"type": "string",
"value": "={{ $json[\"Pictures/Video of issue\"] }}"
},
{
"id": "63176c6a-5e72-4cd1-b955-ef1c6de68c6d",
"name": "feedbackSuggestions",
"type": "string",
"value": "={{ $json['Any feedback or suggestions are welcome:'] }}"
}
]
}
},
"executeOnce": false,
"typeVersion": 3.4
},
{
"id": "5860a874-e90b-4892-9329-b88733cc531e",
"name": "Add UUID #",
"type": "n8n-nodes-base.googleSheets",
"position": [
-48,
-1472
],
"parameters": {
"columns": {
"value": {
"Timestamp": "={{ $json.timestamp }}",
"Unique Unit ID": "={{ $json.uniqueUnitId }}"
},
"schema": [
{
"id": "Unique Unit ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Unique Unit ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timestamp",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Building Address",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Building Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Unit Number ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Unit Number ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Urgency",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Urgency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone Number:",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Phone Number:",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name on Messenger",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name on Messenger",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "In Person ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "In Person ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Best days/times to reach you ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Best days/times to reach you ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "What is this regarding?",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "What is this regarding?",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Please explain the situation.",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Please explain the situation.",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Pictures/Video of issue",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Pictures/Video of issue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Any feedback or suggestions are welcome:",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Any feedback or suggestions are welcome:",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Timestamp"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1646368885,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit#gid=1646368885",
"cachedResultName": "Form Responses 7"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ubRqvf5deapQMzSbh271fJkwBiMk1ihvOwAfr25bwEE/edit?usp=drivesdk",
"cachedResultName": "Repair Request Log"
}
},
"typeVersion": 4.7
},
{
"id": "48a2d86e-2999-41bd-8213-5d95abdec50a",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1680,
-1680
],
"parameters": {
"width": 672,
"height": 704,
"content": "# Workflow 1:\n\n## **Behind the Scenes:**\nTennant fills out Google form (\"Repair Request Form\") which auto-populates a new row in a spreadsheet. \n\n## How it Works:\n#### Trigger:\n- New ROW ADDED repair form submission via rowAdded.\n#### Code:\n- Extract the newly added entry for processing.\n#### **Format:** \n -Build display fields (address, unit, urgency, contacts) and a message body.\n#### **Add Unit ID:** \n -Generate a standardized Unit/UUID (e.g., BUILDING-UNIT) from form inputs.\n#### **Email:** \n -Send [building manager] a formatted email with repair details, contact methods, and ⚠️ **link to update the repair** ⚠️"
},
"typeVersion": 1
},
{
"id": "f32e7012-2938-404e-9455-e5d8de27138a",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-832,
-1536
],
"parameters": {
"color": 4,
"height": 112,
"content": "## Sheets:\n\n### -Google Sheets Credential"
},
"typeVersion": 1
},
{
"id": "59fc4759-d2e4-4447-8704-e920038cd99e",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-144,
-1120
],
"parameters": {
"color": 4,
"width": 320,
"height": 256,
"content": "## Alert Email:\n\n### -Email Credential\n### -Format Data to share essential info for [building manager]\n⚠️ ### -Include Link to N8N form ⚠️\n\n"
},
"typeVersion": 1
},
{
"id": "c274f39b-37cc-47ae-b950-e817c29091b7",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
-1696
],
"parameters": {
"color": 4,
"height": 192,
"content": "## Sheets:\n\n### -Google Sheets Credential\n### -Add UUID to row\n### -Use TIMESTAMP as \"Column to match on\"\n\n"
},
"typeVersion": 1
},
{
"id": "6dd22693-98d3-40da-896d-a83ab93a696c",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1344,
-432
],
"parameters": {
"color": 3,
"width": 256,
"height": 320,
"content": "## REPLACE THIS TRIGGER WITH \nN8N FORM = Repair Update Form\n\n"
},
"typeVersion": 1
},
{
"id": "89bf8720-71bc-43a1-8043-825314f482d5",
"name": "REPLACE w/ N8N FORM trigger.",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1280,
-288
],
"parameters": {},
"typeVersion": 1
},
{
"id": "0b45ec23-9f20-4399-b3aa-d07c3106397d",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
-2256
],
"parameters": {
"width": 1088,
"height": 400,
"content": "# This template automates tenant repair requests and updates via Google Forms and Google Sheets. Two workflows handle new submissions and manager updates, ensuring all repair data stays in a single, organized row."
},
"typeVersion": 1
},
{
"id": "95962c56-130d-40f5-b580-e085335917e5",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
432,
-1680
],
"parameters": {
"width": 704,
"height": 688,
"content": "# Setting Up Workflow 1:\n\n## **Behind the Scenes:**\n- Create Google form (\"Repair Request Form\")\n- Create Google Sheet to collect responses. (In \"Form Responses\" you can create a linked Google Sheet.)\n\n## Nodes:\n#### Trigger:\n- Add Google Sheets credential. \n- Select document, sheet, poll time. \n#### **Format Data:** \n- Build display fields that apply to your Spreadsheet columns (address, unit, urgency, contacts, etc) and a message body.\n- add input expressions for \"address\"+\"unit\" to create \"UUID\"\n#### **Add Unit ID:** \n- Add Sheets credential\n#### **Report Alert + Info:** \n- Add Gmail/email credential\n- format information summary sent to building manager.\n- ⚠️ **link to update the repair** ⚠️ --link found in **N8N Form Trigger** in Workflow 2. "
},
"typeVersion": 1
},
{
"id": "33193daf-e81b-486e-8913-a388bec977ed",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
-496
],
"parameters": {
"width": 672,
"height": 976,
"content": "# Setting Up Workflow 2:\n\n## **Behind the Scenes:**\n- Select categories(questions) for repair information to submit\n- **One as Image/File**\n\n### ⚠️Replace MANUAL TRIGGER with N8N FORM trigger ⚠️\n‼️**The Link to the N8N FORM trigger must be pasted to the EMAIL node at end of Workflow 1.**\n\n## Top Nodes: \n### Get Rows:\n- Add Sheets Credential\n- Use **UUID** to collect existing info from spreadsheet row. \n### Existing Details:\n- set required data fields\n## Bottom Nodes:\n### Code Nodes:\n- Update file names if necessary (use AI: copy code and update with new file name) \n### Upload Repair Photo:\n- Add Drive Credential\n- set folder to store photos\n\n## End Nodes:\n### Merge: \n- organize data as necessary for columns\n### Sheets node:\n- Add Credential\n- select file and sheet.\n- Map java expressions to column\n- Must have spreadsheet columns that exactly match all field names **including repair updates**.\n### Email Node:\n- Optional: to alert tenant or other about a repair update. \n\n"
},
"typeVersion": 1
},
{
"parameters": {
"operation": "verify",
"email": "={{ $json.email || $json.Email }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
296,
-304
],
"name": "Verify Email (BillionVerify)",
"credentials": {
"billionVerifyApi": {
"id": "",
"name": "BillionVerify account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "is-deliverable",
"leftValue": "={{ $json.is_deliverable }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
]
}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
476,
-304
],
"name": "IF deliverable"
},
{
"parameters": {
"operation": "verify",
"email": "={{ $json.email || $json.Email }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
-408,
-1280
],
"name": "Verify Email (BillionVerify) 2",
"credentials": {
"billionVerifyApi": {
"id": "",
"name": "BillionVerify account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "is-deliverable",
"leftValue": "={{ $json.is_deliverable }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
]
}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-228,
-1280
],
"name": "IF deliverable 2"
}
],
"connections": {
"If": {
"main": [
[
{
"node": "Separate Photo Files",
"type": "main",
"index": 0
}
],
[
{
"node": "New details",
"type": "main",
"index": 0
}
]
]
},
"Merge Data": {
"main": [
[
{
"node": "Update w/ Repair",
"type": "main",
"index": 0
}
]
]
},
"Format Data": {
"main": [
[
{
"node": "Verify Email (BillionVerify) 2",
"type": "main",
"index": 0
},
{
"node": "Add UUID #",
"type": "main",
"index": 0
}
]
]
},
"New details": {
"main": [
[
{
"node": "Merge Data",
"type": "main",
"index": 1
}
]
]
},
"Photo Uploading": {
"main": [
[
{
"node": "Combine Photo URLs",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload Repair Photo",
"type": "main",
"index": 0
}
]
]
},
"Existing Details": {
"main": [
[
{
"node": "Merge Data",
"type": "main",
"index": 0
}
]
]
},
"Update w/ Repair": {
"main": [
[
{
"node": "Verify Email (BillionVerify)",
"type": "main",
"index": 0
}
]
]
},
"Isolate new entry": {
"main": [
[
{
"node": "Format Data",
"type": "main",
"index": 0
}
]
]
},
"Combine Photo URLs": {
"main": [
[
{
"node": "New details",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet": {
"main": [
[
{
"node": "Existing Details",
"type": "main",
"index": 0
}
]
]
},
"Upload Repair Photo": {
"main": [
[
{
"node": "Photo Uploading",
"type": "main",
"index": 0
}
]
]
},
"Separate Photo Files": {
"main": [
[
{
"node": "Photo Uploading",
"type": "main",
"index": 0
}
]
]
},
"New repair form submitted": {
"main": [
[
{
"node": "Isolate new entry",
"type": "main",
"index": 0
}
]
]
},
"REPLACE w/ N8N FORM trigger.": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
},
{
"node": "Get row(s) in sheet",
"type": "main",
"index": 0
}
]
]
},
"Verify Email (BillionVerify)": {
"main": [
[
{
"node": "IF deliverable",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
],
[]
]
},
"Verify Email (BillionVerify) 2": {
"main": [
[
{
"node": "IF deliverable 2",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable 2": {
"main": [
[
{
"node": "Report Alert + Info",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1"
}
}When to use this
- Cleaning a list before a Google Sheets send or sync.
- Protecting Google Sheets deliverability and sender reputation.
- Keeping bounce rates low so your sending is never throttled.
FAQ
Why verify before sending in Google Sheets?
Verifying first keeps your bounce rate low, which protects your sender reputation and your results.
How do I import this workflow?
Download the JSON, then in n8n go to Workflows → Import from File (or paste it). Install the BillionVerify community node and add your API key credential.
What happens to risky or catch-all addresses?
They are routed to the false branch and excluded from the send. You decide whether to retry, review, or drop them.
Add verification to your workflow
Create a free account, grab your API key, and stop bounces before they happen.
Get started free