This workflow corresponds to n8n.io template #7271 — we link there as the canonical source.
This workflow follows the Form Trigger → Gmail 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": "oxgrJNmYucFmtqbU",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Reimbursement Claims",
"tags": [],
"nodes": [
{
"id": "62704744-327d-4ba6-9c50-27aabe2fbca5",
"name": "On form submission",
"type": "n8n-nodes-base.formTrigger",
"position": [
-1060,
-920
],
"parameters": {
"options": {
"buttonLabel": "Submit",
"appendAttribution": false,
"respondWithOptions": {
"values": {
"formSubmittedText": "=Thank you !\nYou will receive an email shortly about your reimbursement request from Finance Department.\n"
}
}
},
"formTitle": "Reimbursement Form",
"formFields": {
"values": [
{
"fieldLabel": "Emp Name",
"placeholder": "Employee Name",
"requiredField": true
},
{
"fieldLabel": "Emp ID",
"placeholder": "Employee ID",
"requiredField": true
},
{
"fieldType": "email",
"fieldLabel": "Email",
"placeholder": "Email Address",
"requiredField": true
},
{
"fieldType": "number",
"fieldLabel": "Claim Amount",
"placeholder": "INR 0.00",
"requiredField": true
},
{
"fieldType": "dropdown",
"fieldLabel": "Nature of Bill",
"fieldOptions": {
"values": [
{
"option": "Food"
},
{
"option": "Travel"
},
{
"option": "Accomodation"
},
{
"option": "Others"
}
]
},
"requiredField": true
},
{
"fieldType": "file",
"fieldLabel": "Upload Bills",
"requiredField": true,
"acceptFileTypes": ".jpg, .png, .pdf"
}
]
},
"responseMode": "lastNode",
"formDescription": "Reimbursement Form"
},
"typeVersion": 2.2
},
{
"id": "03b7edb5-2f55-48a4-9fbb-9c230f45df70",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
-420,
-940
],
"parameters": {
"mode": "chooseBranch",
"useDataOfInput": 2
},
"typeVersion": 3.2
},
{
"id": "6393835a-0680-482d-86eb-fd9703a562ff",
"name": "if Bill Exists",
"type": "n8n-nodes-base.if",
"position": [
-660,
-1080
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b07ac5ff-eb0d-4d85-b15f-60eba9384546",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.name }}",
"rightValue": "={{ $('On form submission').item.json['Upload Bills'][0].filename }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "548f0d70-643c-4ef5-861a-5ad584a40321",
"name": "Download Existing Bill",
"type": "n8n-nodes-base.googleDrive",
"position": [
-280,
-1100
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "download"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "0127a1b4-5a2e-42a6-b2bc-7476dd7bf817",
"name": "Mail Invalid Claim",
"type": "n8n-nodes-base.gmail",
"position": [
720,
-1180
],
"parameters": {
"sendTo": "={{ $('On form submission').item.json.Email }}",
"message": "=Dear {{ $json.receiptContent.empName }},\n\nIt was identified that the claims requested does not match the total bill from the uploaded receipts . \n\nAmount Claimed: $ {{ $json.receiptContent.amountClaimed }}/-\nTotal Bill: $ {{ $json.receiptContent.totalBill }}/-\nUploaded Recipt: {{ $json.receiptContent.uploadedFile }}\nBill Type: {{ $json.receiptContent.billType }}\n\nPlease review and resubmit the request.\n\n*Claims are Subject to Approvals*\n\nRegards,\nFinance Depeartment\n\n",
"options": {
"ccList": "user@example.com",
"appendAttribution": false
},
"subject": "=New Reimbursement Request - INR {{ $('On form submission').item.json['Claim Amount'] }} /-",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "13253bbd-890a-49b2-a89e-821575f298dc",
"name": "Mail Valid Claim",
"type": "n8n-nodes-base.gmail",
"position": [
880,
-980
],
"parameters": {
"sendTo": "={{ $('On form submission').item.json.Email }}",
"message": "=Dear {{ $json['Employee Name'] }},\n\nThank you for your email. \n\nRequest ID: {{ $json.RequestID }}\n\nYou reimbursement rquest as below is being reviewed.\n\nAmount Claimed: ${{ $('Validate False Claims').item.json.receiptContent.amountClaimed }}/-\nTotal Bill: ${{ $json['Total Billed Amount'] }}/-\nUploaded Recipt: {{ $json['Recieipt Link'] }}\nBill Type: {{ $json['Receipt Type'] }}\n\n*Claims are subject to approvals*\n\nRegards,\nFinance Depeartment\n",
"options": {
"ccList": "user@example.com",
"appendAttribution": false
},
"subject": "=New Reimbursement Request - INR {{ $('On form submission').item.json['Claim Amount'] }} /- | {{ $json.RequestID }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "ca855f2a-c40e-4dec-845c-8b7b0d81b330",
"name": "MergeInputs",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
100,
-1100
],
"parameters": {
"text": "=Create a JSON as below and just return structed JSON in strings. \n\n{\n empID: {{ $('On form submission').item.json['Emp ID'] }},\n empName: {{ $('On form submission').item.json['Emp Name'] }},\n empEmail: {{ $('On form submission').item.json.Email }},\n billType: {{ $('On form submission').item.json['Nature of Bill'] }},\n amountClaimed: {{ $('On form submission').item.json['Claim Amount'] || 0.00}},\n totalBill: Extract the total amount from the binary,\n uploadedFile: {{ $json.webViewLink }}\n\n## NOTE\n - Do not append ```json\\n in the output",
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"resource": "image",
"inputType": "base64",
"operation": "analyze"
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "de6eb222-2e33-4277-8cfb-45042e6902e3",
"name": "Validate False Claims",
"type": "n8n-nodes-base.code",
"position": [
260,
-1100
],
"parameters": {
"jsCode": "var jsonObj = JSON.parse($input.first().json.content)\n\nif (jsonObj.amountClaimed != jsonObj.totalBill) {\n return {isFalseClaim: true, receiptContent: jsonObj,requestID: generateRandomString()}\n} else return {isFalseClaim: false, receiptContent: jsonObj, requestID: generateRandomString()}\n\n\nfunction generateRandomString(length = 20) {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = jsonObj.empID+'_';\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n"
},
"typeVersion": 2
},
{
"id": "34b61b4d-a314-4d3d-9e9a-806c5a747ce4",
"name": "Upload_Bills",
"type": "n8n-nodes-base.googleDrive",
"position": [
-260,
-940
],
"parameters": {
"name": "={{ $json['Upload Bills'][0].filename }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1huBmHtSlSU2nV5xbRDDOaBY-CKIPmnjs",
"cachedResultUrl": "https://drive.google.com/drive/folders/1huBmHtSlSU2nV5xbRDDOaBY-CKIPmnjs",
"cachedResultName": "Reimburse Bills"
},
"inputDataFieldName": "=Upload_Bills"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "bf47788d-8326-4524-b0e4-58cfc453da72",
"name": "Download_Bills",
"type": "n8n-nodes-base.googleDrive",
"position": [
-100,
-940
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "download"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "b9ae6568-76dd-4605-8402-765a25e850ed",
"name": "Search_Bill",
"type": "n8n-nodes-base.googleDrive",
"onError": "continueRegularOutput",
"position": [
-840,
-1080
],
"parameters": {
"limit": 5,
"filter": {
"folderId": {
"__rl": true,
"mode": "list",
"value": "1huBmHtSlSU2nV5xbRDDOaBY-CKIPmnjs",
"cachedResultUrl": "https://drive.google.com/drive/folders/1huBmHtSlSU2nV5xbRDDOaBY-CKIPmnjs",
"cachedResultName": "Reimburse Bills"
}
},
"options": {
"fields": [
"id",
"name",
"webViewLink"
]
},
"resource": "fileFolder",
"queryString": "={{ $json['Upload Bills'][0].filename }}"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3,
"alwaysOutputData": true
},
{
"id": "b9a932ea-9404-453d-b45d-1ced96120d57",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
420,
-1100
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9d358347-9a20-425a-b6ef-4f03007c99fd",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.isFalseClaim }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "7182bbde-016f-4ff0-abb9-43dcf82f9bf2",
"name": "Add Request",
"type": "n8n-nodes-base.googleSheets",
"position": [
720,
-980
],
"parameters": {
"columns": {
"value": {
"Bill Date": "={{ $now }}",
"RequestID": "={{ $json.requestID }}",
"Employee ID": "={{ $('Validate False Claims').item.json.receiptContent.empID }}",
"Is_Approved": "No",
"Uploaded On": "={{ $now }}",
"Receipt Type": "={{ $('Validate False Claims').item.json.receiptContent.billType }}",
"Employee Name": "={{ $('Validate False Claims').item.json.receiptContent.empName }}",
"Recieipt Link": "={{ $('Validate False Claims').item.json.receiptContent.uploadedFile }}",
"Total Billed Amount": "={{ $('Validate False Claims').item.json.receiptContent.totalBill }}"
},
"schema": [
{
"id": "RequestID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "RequestID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Employee ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Employee ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Employee Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Employee Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Receipt Type",
"type": "string",
"display": true,
"required": false,
"displayName": "Receipt Type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Billed Amount",
"type": "string",
"display": true,
"required": false,
"displayName": "Total Billed Amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Bill Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Bill Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Uploaded On",
"type": "string",
"display": true,
"required": false,
"displayName": "Uploaded On",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Recieipt Link",
"type": "string",
"display": true,
"required": false,
"displayName": "Recieipt Link",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Is_Approved",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Is_Approved",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ttZJOK5L-_zFTSRUoOyNkJ9VL60mgd6HRTvaQWKvYAs/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ttZJOK5L-_zFTSRUoOyNkJ9VL60mgd6HRTvaQWKvYAs",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ttZJOK5L-_zFTSRUoOyNkJ9VL60mgd6HRTvaQWKvYAs/edit?usp=drivesdk",
"cachedResultName": "Receipts"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "64793a3d-e3d1-462a-8870-4af280f81423",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1300,
-1000
],
"parameters": {
"color": 4,
"width": 380,
"height": 220,
"content": "## Submit Form\nThis form will get all required information from the user and pass it to other nodes\n"
},
"typeVersion": 1
},
{
"id": "cb6b5988-9eb9-4686-9f5b-3a2ce92179d9",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
-1260
],
"parameters": {
"width": 360,
"height": 340,
"content": "## Validate User Uploaded Bills.\n\nValidate if the user uploaded bill already exists into the system.\n\nIf **Yes** then reuse and download for proccesing.\n**Else** -- Upload the bill and then use for processing. "
},
"typeVersion": 1
},
{
"id": "b1501bda-4ad4-45a0-9b95-322d307b3688",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-480,
-1180
],
"parameters": {
"color": 5,
"width": 520,
"height": 560,
"content": "## Uploads and Downloads\nIf **Bills Already Exist]** Download the file and send to next node for OCR.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nIf **Bills Does not Exists**\n- **Merge** - This node will get the user uploaded file [**binary**] and then uploads to **GDrive** from the next node. \n- The Same file get downloaded again and then passed to next node for OCR"
},
"typeVersion": 1
},
{
"id": "46d1de94-b727-450e-adc2-10e424f39291",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
60,
-1300
],
"parameters": {
"width": 500,
"height": 360,
"content": "## Extract, Validate\nThese nodes will \n- Extract the content from the bill\n- Validate if the claim made by the user is correct. Whether the amount claimed and the amount from the bill match.\n- If **false claim** the Notify user to resubmit.\n- If **correct claim** send for Finance Team for processing. "
},
"typeVersion": 1
},
{
"id": "45aa008a-5f9f-41ed-b7ba-0473edf9a597",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
680,
-1240
],
"parameters": {
"color": 3,
"width": 280,
"height": 220,
"content": "## Invalid Claim\n\n"
},
"typeVersion": 1
},
{
"id": "5391e33a-7b73-43d6-9a13-444ccf6840e8",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
680,
-1000
],
"parameters": {
"color": 4,
"width": 380,
"height": 300,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Valid Claim\n- Notify User with the request id.\n- Notify Finance Team to proceed with review."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "94c7c211-e7bf-45ec-b0c9-8f31bf7b7229",
"connections": {
"If": {
"main": [
[
{
"node": "Mail Invalid Claim",
"type": "main",
"index": 0
}
],
[
{
"node": "Add Request",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Upload_Bills",
"type": "main",
"index": 0
}
]
]
},
"Add Request": {
"main": [
[
{
"node": "Mail Valid Claim",
"type": "main",
"index": 0
}
]
]
},
"MergeInputs": {
"main": [
[
{
"node": "Validate False Claims",
"type": "main",
"index": 0
}
]
]
},
"Search_Bill": {
"main": [
[
{
"node": "if Bill Exists",
"type": "main",
"index": 0
}
]
]
},
"Upload_Bills": {
"main": [
[
{
"node": "Download_Bills",
"type": "main",
"index": 0
}
]
]
},
"Download_Bills": {
"main": [
[
{
"node": "MergeInputs",
"type": "main",
"index": 0
}
]
]
},
"if Bill Exists": {
"main": [
[
{
"node": "Download Existing Bill",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Mail Valid Claim": {
"main": [
[]
]
},
"On form submission": {
"main": [
[
{
"node": "Search_Bill",
"type": "main",
"index": 0
},
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Validate False Claims": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Download Existing Bill": {
"main": [
[
{
"node": "MergeInputs",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleDriveOAuth2ApigoogleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Reimbursements used to be a headache.
Source: https://n8n.io/workflows/7271/ — 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.
An n8n-based automation that generates client proposals from a form, lets you review everything in one place, and sends the proposal only when you approve it.
This workflow automates the process of creating high-quality articles using AI, organizing them in Google Drive, and tracking their progress in Google Sheets. It's perfect for marketers, bloggers, and
What it is An automated LinkedIn content system that takes a simple form (idea + optional file), generates LinkedIn posts with OpenAI, stores them in Notion, builds Google Slides carousels, and auto-p
Automatically analyze your full sports performance evolution using your Strava activities, enriched with AI insights and delivered directly to your email — all powered by your own n8n instance.
Overview