This workflow corresponds to n8n.io template #9417 — we link there as the canonical source.
This workflow follows the Agent → 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": "PtWwGGJYMVyJGgoI",
"name": "JotForm Cashback (Template)",
"tags": [],
"nodes": [
{
"id": "fafc18fe-9ffe-42d1-aa6e-16d2c44b0bab",
"name": "JotForm Trigger",
"type": "n8n-nodes-base.jotFormTrigger",
"position": [
-2896,
480
],
"parameters": {
"form": "YOUR_FORM_ID"
},
"typeVersion": 1
},
{
"id": "53c0d83e-9711-4b81-b738-70919a4c764e",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
-1760,
768
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-lite"
},
"typeVersion": 1
},
{
"id": "6a8cba61-0195-44d7-a8e6-c6ab918918ab",
"name": "OCR.Space",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1856,
480
],
"parameters": {
"url": "https://api.ocr.space/parse/image",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "multipart-form-data",
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "base64Image",
"value": "=data:image/jpeg;base64,{{$json.imageBase64}}"
},
{
"name": "language",
"value": "ara"
},
{
"name": "OCREngine",
"value": "1"
},
{
"name": "filetype",
"value": "jpg"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "YOUR_OCR_SPACE_API_KEY"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "3794d88d-02db-4183-94f2-05d9cbcf8358",
"name": "Fetch All Receipts",
"type": "n8n-nodes-base.httpRequest",
"position": [
-2688,
480
],
"parameters": {
"url": "https://api.jotform.com/form/YOUR_FORM_ID/files",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "apiKey",
"value": "YOUR_JOTFORM_API_KEY_FOR_FILES"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "6cc27de0-4bcf-4fc6-8bfc-27044cfa482d",
"name": "Fetch Receipt File",
"type": "n8n-nodes-base.httpRequest",
"position": [
-2272,
480
],
"parameters": {
"url": "={{ $json.lastFile.url.replace('http://','https://') }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "a3580172-cbe7-41e3-9c8c-cf965050f75e",
"name": "Gets Last Receipt",
"type": "n8n-nodes-base.code",
"position": [
-2480,
480
],
"parameters": {
"jsCode": "// Access the array that contains all files\n// Adjust the path if necessary (e.g., $json.content or $json.files)\nconst files = $json.files || $json.content || [];\n\n// If it's a dictionary of answers, flatten all URLs\nlet allUrls = [];\nif (!Array.isArray(files)) {\n // if it\u2019s a Jotform structure like answers -> each -> answer:[urls]\n const answers = files.answers || files.data?.answers || {};\n for (const key of Object.keys(answers)) {\n const a = answers[key]?.answer;\n if (Array.isArray(a)) allUrls.push(...a);\n }\n} else {\n allUrls = files;\n}\n\n// Take the last file\nconst lastFile = allUrls[allUrls.length - 1] || null;\n\n// Return it as a single field\nreturn [{ json: { lastFile } }];\n"
},
"typeVersion": 2
},
{
"id": "12f9b49f-e973-4e2e-afa0-63b2488becc0",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-1424,
752
],
"parameters": {
"jsonSchemaExample": "{\n \"store_name\": \"\",\n \"purchase_date\": \"\",\n \"products\": [\n {\n \"product_name\": \"\",\n \"quantity\": 0,\n \"unit_price\": 0,\n \"total_price\": 0,\n \"cashback_amount\": 0\n }\n ],\n \"total_cashback\": 0\n}\n"
},
"typeVersion": 1.3
},
{
"id": "1aee2b39-2516-48ec-8b24-2565eb6974ce",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-1616,
480
],
"parameters": {
"text": "=You are an intelligent assistant for XQ Pharma.\n\nYou receive OCR text extracted from a customer's purchase receipt.\nThe text may include both Arabic and English, with missing spaces, symbols, or repeated lines.\n\n### STEP 1 \u2014 Clean and Organize\nClean and rewrite the OCR text in a clear, structured way:\n- Combine broken lines that belong to the same sentence or product.\n- Remove repeating symbols, dots, commas, or words.\n- Normalize Arabic (\u0627\u0643\u0633 \u0643\u064a\u0648) and English (XQ) text forms.\n- Try to create a simple, readable \u201creceipt\u201d view with one product per line.\n\n### STEP 2 \u2014 Identify XQ Pharma Products\n- Find all products that belong to XQ Pharma (look for \"XQ\", \"\u0627\u0643\u0633 \u0643\u064a\u0648\", or variants like \"\u0627\u0643\u0633 \u0643\").\n- Rebuild product lines if necessary (for example, join \u201c\u0643\u0631\u064a\u0645 \u0627\u0643\u0633\u201d + \u201c\u0643\u064a\u0648 \u0645\u0631\u0637\u0628\u201d = \u201c\u0643\u0631\u064a\u0645 \u0627\u0643\u0633 \u0643\u064a\u0648 \u0645\u0631\u0637\u0628\u201d).\n- For each product line, detect nearby numbers that look like prices.\n\n### STEP 3 \u2014 Extract Data\nExtract:\n- store_name\n- purchase_date\n- products \u2192 a list of all identified XQ Pharma items, each with:\n - product_name \n - quantity (default 1 if missing)\n - unit_price (try to find numbers following the product name)\n - total_price (quantity \u00d7 unit_price if not listed)\n - cashback_amount (10% of total_price)\n- total_cashback = sum of cashback_amount values\n\nIf any value is missing, infer it logically (for example, assume total_price = unit_price if only one quantity).\n\n### STEP 4 \u2014 Output\nReturn **only** a valid JSON in this exact structure (no text or notes before or after):\n\n{\n \"store_name\": \"\",\n \"purchase_date\": \"\",\n \"products\": [\n {\n \"product_name\": \"\",\n \"quantity\": ,\n \"unit_price\": ,\n \"total_price\": ,\n \"cashback_amount\": \n }\n ],\n \"total_cashback\": \n}\n\n### OCR Text Input:\n{{ $json.ParsedResults[0].ParsedText }}\n",
"options": {},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.2
},
{
"id": "29d1089d-f09b-4380-a9fd-20c79bb16b4e",
"name": "Customer Email",
"type": "n8n-nodes-base.gmail",
"position": [
-656,
224
],
"parameters": {
"sendTo": "={{ $('JotForm Trigger').item.json['E-mail'] }}",
"message": "=\ud83c\udf89 Congratulations! You\u2019ve earned a cashback reward \ud83c\udf81\n\n\ud83d\uddd3\ufe0f Purchase Date: {{ $('AI Agent').item.json.output.purchase_date }}\n\ud83c\udfec Store: {{ $('AI Agent').item.json.output.store_name }}\n\n\ud83e\uddf4 Products Purchased:\n{{ $node['AI Agent'].json[\"output\"][\"products\"].map(p => `\u2022 ${p.product_name} \u2014 Cashback: ${p.cashback_amount} EGP`).join('\\n') }}\n\n\ud83d\udcb0 Total Cashback Earned: {{ $('AI Agent').item.json.output.total_cashback }} EGP \ud83c\udf89\n\nYour cashback will be added to your wallet within 24 hours.\nThank you for your purchase \ud83d\udc99\n",
"options": {},
"subject": "Cashback",
"emailType": "text"
},
"typeVersion": 2.1
},
{
"id": "f4e533e6-db38-48aa-acb6-544b16a6a915",
"name": "Marketing Email",
"type": "n8n-nodes-base.gmail",
"position": [
-656,
496
],
"parameters": {
"sendTo": "=Marketing@yourcompany.com",
"message": "=\ud83d\udce2 Cashback Notification \u2013 New Reward Granted \ud83c\udf89\n\n\ud83d\uddd3\ufe0f Purchase Date: {{ $('AI Agent').item.json.output.purchase_date }}\n\ud83c\udfec Store: {{ $('AI Agent').item.json.output.store_name }}\n\n\ud83e\uddfe Products Purchased:\n{{ $node['AI Agent'].json[\"output\"][\"products\"].map(p => `\u2022 ${p.product_name} \u2014 Cashback: ${p.cashback_amount} EGP`).join('\\n') }}\n\nCustomer name : {{ $('JotForm Trigger').item.json['Full Name'].first }} {{ $('JotForm Trigger').item.json['Full Name'].last }}\nCustomer Email: {{ $('JotForm Trigger').item.json['E-mail'] }}\nCustomer Phone Number: {{ $('JotForm Trigger').item.json['Contact Number'].full }}\n\n\n\ud83d\udcb0 Total Cashback Issued: {{ $('AI Agent').item.json.output.total_cashback }} EGP\n\n\u2705 Status: Cashback confirmation message sent to customer.\nPlease ensure this transaction is logged in the campaign tracking sheet.\n",
"options": {},
"subject": "Cashback Notification - New Reward",
"emailType": "text"
},
"typeVersion": 2.1
},
{
"id": "e4f93b36-e5df-4e62-a7c1-2565459d49f8",
"name": "Add info to Database",
"type": "n8n-nodes-base.notion",
"position": [
-944,
384
],
"parameters": {
"options": {},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "YOUR_NOTION_DATABASE_ID",
"cachedResultUrl": "https://www.notion.so/YOUR_NOTION_DATABASE_ID",
"cachedResultName": "Cashback"
},
"propertiesUi": {
"propertyValues": [
{
"key": "Customer name|title",
"title": "={{ $('JotForm Trigger').item.json['Full Name'].first }} {{ $('JotForm Trigger').item.json['Full Name'].last }}"
},
{
"key": "Customer Email|email",
"emailValue": "={{ $('JotForm Trigger').item.json['E-mail'] }}"
},
{
"key": "Store Type|rich_text",
"textContent": "={{ $('JotForm Trigger').item.json['Purchase Channel'] }}"
},
{
"key": "Store Name|rich_text",
"textContent": "={{ $('JotForm Trigger').item.json['Store Name'] }}"
},
{
"key": "Cashback Amount|number",
"numberValue": "={{ $json.output.total_cashback }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e20517ed-2f08-4b8b-bf81-41cd7fb23eea",
"name": "Is There's cashback",
"type": "n8n-nodes-base.if",
"position": [
-1216,
480
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "329c2481-24e8-4871-8035-813bc48f82f2",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.output.total_cashback }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.2
},
{
"id": "36c305f5-efa7-4849-9f1e-1c384f8c4833",
"name": "Convert Image to base64",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-2064,
480
],
"parameters": {
"options": {},
"operation": "binaryToPropery",
"destinationKey": "imageBase64"
},
"typeVersion": 1
},
{
"id": "7199729e-da73-4c70-a0a2-6a67815a890b",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3008,
400
],
"parameters": {
"color": 3,
"width": 272,
"content": "Starts the workflow upon form submission; provides customer and initial purchase data."
},
"typeVersion": 1
},
{
"id": "b8601130-a266-4e72-af38-bd759db0457f",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2720,
400
],
"parameters": {
"color": 4,
"width": 176,
"content": "Requests the list of all uploaded receipt files from the JotForm API."
},
"typeVersion": 1
},
{
"id": "2db6bf7f-be22-4476-bb72-2d5ad7ae16bc",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2528,
400
],
"parameters": {
"color": 5,
"width": 192,
"height": 176,
"content": "Extracts the URL for the most recently uploaded receipt from the file list.\n"
},
"typeVersion": 1
},
{
"id": "7c1b00ae-e1c9-495e-81ed-1adfd2f68317",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2320,
400
],
"parameters": {
"color": 4,
"width": 176,
"height": 176,
"content": "Downloads the actual receipt image file using the extracted URL.\n"
},
"typeVersion": 1
},
{
"id": "2b3df853-ea8b-4d31-9299-776f78841213",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2128,
400
],
"parameters": {
"color": 5,
"width": 208,
"height": 176,
"content": "Encodes the downloaded image into a base64 string, preparing it for OCR.\n"
},
"typeVersion": 1
},
{
"id": "c0e1412d-ad4d-4946-b831-521736cb267a",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1904,
400
],
"parameters": {
"color": 4,
"width": 192,
"height": 176,
"content": "Converts the receipt image into plain, readable text.\n"
},
"typeVersion": 1
},
{
"id": "85a4879c-6f96-4f97-be8f-80c14382a5e9",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1696,
400
],
"parameters": {
"color": 6,
"width": 368,
"content": "Uses Gemini to clean the raw OCR text, identify XQ products, and extract structured data like prices and cashback."
},
"typeVersion": 1
},
{
"id": "b6e73eed-0bba-47e4-9935-ab0bfb029f2f",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1280,
400
],
"parameters": {
"color": 5,
"width": 272,
"content": "A conditional check; it only allows the workflow to proceed if the calculated cashback is greater than zero.\n"
},
"typeVersion": 1
},
{
"id": "384f6f49-6402-4ebf-865f-1bd2bfdbfb84",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-992,
320
],
"parameters": {
"color": 4,
"width": 224,
"content": "Logs the customer details and the calculated cashback amount to a Notion database.\n"
},
"typeVersion": 1
},
{
"id": "00d037bc-7d84-4e71-b696-894de6e0a4f4",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-720,
160
],
"parameters": {
"color": 5,
"content": "Sends a confirmation email to the customer detailing their earned cashback reward.\n"
},
"typeVersion": 1
},
{
"id": "99b4585d-9f9a-4f88-93f2-8163fa3d7522",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-720,
416
],
"parameters": {
"color": 5,
"content": "Sends an internal email notification with all transaction details to the marketing team for tracking."
},
"typeVersion": 1
},
{
"id": "af05870d-bd52-4b37-9a54-f1e49ef16963",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2992,
-368
],
"parameters": {
"width": 1024,
"height": 736,
"content": "# JotForm Setup Guide\n\n\n## \u26a1 Step 1: Link with the Webhook\n\n\n* **1. Log in to your JotForm account, select your Cashback Form, and navigate to Settings.**\n\n* **2. Go to Integrations and search for Webhooks.**\n\n* **3. Paste the JotForm Trigger Webhook URL provided by your n8n workflow into the field.**\n\n* **4. Save and activate! Your form is now live!**\n\n## \ud83d\udd11 Step 2: Unlock File Access (API Key)\n\n* **1.Generate a JotForm API Key in your JotForm account settings.**\n\n* **2.CRITICAL: Set the key permission level to \"Full Access\" (required for file downloads).**\n\n* **3.Go to your n8n workflow and insert this key into:**\n * **I.The JotForm Trigger node's credential.**\n * **II.The Fetch All Receipts node's query parameters.**\n\n## \u2699\ufe0f Step 3: Configure Your n8n Nodes\n\n* **In the JotForm Trigger node and the Fetch All Receipts node, replace the placeholder with your actual JotForm ID.**\n\n* **In the Notion node, update the Database ID so every cashback transaction is logged seamlessly.**"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "e1e2b6a4-b113-4c0b-9ac7-02c978c36323",
"connections": {
"AI Agent": {
"main": [
[
{
"node": "Is There's cashback",
"type": "main",
"index": 0
}
]
]
},
"OCR.Space": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"JotForm Trigger": {
"main": [
[
{
"node": "Fetch All Receipts",
"type": "main",
"index": 0
}
]
]
},
"Gets Last Receipt": {
"main": [
[
{
"node": "Fetch Receipt File",
"type": "main",
"index": 0
}
]
]
},
"Fetch All Receipts": {
"main": [
[
{
"node": "Gets Last Receipt",
"type": "main",
"index": 0
}
]
]
},
"Fetch Receipt File": {
"main": [
[
{
"node": "Convert Image to base64",
"type": "main",
"index": 0
}
]
]
},
"Is There's cashback": {
"main": [
[
{
"node": "Add info to Database",
"type": "main",
"index": 0
}
]
]
},
"Add info to Database": {
"main": [
[
{
"node": "Customer Email",
"type": "main",
"index": 0
},
{
"node": "Marketing Email",
"type": "main",
"index": 0
}
]
]
},
"Convert Image to base64": {
"main": [
[
{
"node": "OCR.Space",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Agent",
"type": "ai_outputParser",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This blueprint details a highly efficient, AI-powered workflow designed to automate customer reward fulfillment. Leveraging the accessible interface of Jotform, this system delivers superior reliability and exceptional processing speed.
Source: https://n8n.io/workflows/9417/ — 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.
Stop drowning in job applications. This workflow transforms your hiring process from a manual, time-consuming data-entry task into an automated, intelligent screening system.
This workflow turns every Jotform submission — whether from your website or a live marketing campaign — into a fully automated, AI-personalized outreach sequence.
Automatically transform Jotform survey responses into intelligent, professional reports. This workflow generates personalized insights for each respondent and statistical summaries for administrator,
Form managers, SaaS platforms, event organizers, recruitment teams, and any organization using Jotform who need automatic duplicate prevention with intelligent, personalized email responses without ma
LinkedIn_Job_Hunt_and_Cover_Letter. Uses outputParserStructured, outputParserAutofixing, googleDrive, agent. Scheduled trigger; 85 nodes.