{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "54fa0439-a717-4a2c-8bdf-352d61d836ef",
      "name": "Gmail Trigger",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        2864,
        -160
      ],
      "parameters": {
        "filters": {
          "q": "=subject:\"Refund Request\"",
          "readStatus": "unread"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "05ac2dd6-1b0f-4dbc-9b86-5dc2b7069218",
      "name": "Groq Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        3168,
        64
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "f056b065-acc7-4491-9856-0d29a85ffe61",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        3888,
        -160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "516738b9-b280-45cc-becb-7a5d182c3f7f",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Delivered"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c67589fa-d373-4df6-8cee-4e8e7c11a819",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        3360,
        -160
      ],
      "parameters": {
        "jsCode": "// Get the output string from the AI Agent\nconst aiRawOutput = items[0].json.output;\n\n// Parse the string into a real JSON object\nconst cleanData = JSON.parse(aiRawOutput);\n\n// Return the data in a way n8n understands\nreturn [\n  {\n    json: {\n      order_id: cleanData.order_id,\n      reason: cleanData.reason,\n      original_summary: cleanData.reason // Optional: just in case you want a backup\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "150e6302-f8f8-49ab-9136-fa9194e2e303",
      "name": "Send a message to customer",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4272,
        -256
      ],
      "parameters": {
        "sendTo": "={{ $('Gmail Trigger').item.json.From }}",
        "message": "=\"Hi there,    Good news! We have reviewed your request for Order #{{ $('Code in JavaScript').item.json.order_id }} and your refund has been approved. You should see the credit in your account within 5-7 business days.\"",
        "options": {},
        "subject": "=Refund Approved: Order #{{ $('Code in JavaScript').item.json.order_id }}"
      },
      "typeVersion": 2.2
    },
    {
      "id": "e5192a70-224f-46c0-a239-185b12e388e0",
      "name": "Send a message to the team",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4176,
        -48
      ],
      "parameters": {
        "sendTo": "<TEAM_EMAIL>",
        "message": "=\"A refund request was received but could not be auto-approved.   Order ID: {{ $('Code in JavaScript').item.json.order_id }}  Reason: {{ $('Code in JavaScript').item.json.reason }}  Current Sheet Status:{{ $('Get row(s) in sheet').item.json.Status }} \"",
        "options": {},
        "subject": "=ACTION REQUIRED: Manual Refund Review (Order {{ $('Code in JavaScript').item.json.order_id }})"
      },
      "typeVersion": 2.2
    },
    {
      "id": "ae637d4a-ed87-4f92-a3dc-9b00fa0c64c0",
      "name": "Send a message to customer for \"Pending\" Status",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4368,
        -48
      ],
      "parameters": {
        "sendTo": "={{ $('Gmail Trigger').item.json.From }}",
        "message": "=\"Hi, we've received your refund request. Because your order is currently marked as{{ $('Get row(s) in sheet').item.json.Status }}, a member of our team needs to review this manually. We will get back to you shortly.\"",
        "options": {},
        "subject": "=Update on your Refund Request: Order #{{ $('Code in JavaScript').item.json.order_id }}"
      },
      "typeVersion": 2.2
    },
    {
      "id": "2c323e52-6be1-4666-a4dc-891537e1a833",
      "name": "Logs to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4560,
        -160
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $now }}",
            "Notes": "=Original Status: {{ $('Get row(s) in sheet').item.json.Status }}",
            "Reason": "={{ $('Code in JavaScript').item.json.reason }}",
            "Outcome": "={{ $('If').item.json.Status  === 'Delivered' ? 'Auto-Approved' : 'Pending Manual Review ' }}",
            "Order ID": "={{ $('Code in JavaScript').item.json.order_id }}",
            "Customer Email": "={{ $('Gmail Trigger').item.json.From }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Order ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Order ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Customer Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Customer Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Outcome",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Outcome",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Notes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1726448121,
          "cachedResultUrl": "",
          "cachedResultName": "Refund_Logs"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fH2EVCTuUI-AreFpc5fHxUrt5gdl6xSO5O4Tu5OzttY",
          "cachedResultUrl": "",
          "cachedResultName": "Customer Orders"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "89516d69-f7ef-43de-ab52-207c1e836661",
      "name": "Get an order",
      "type": "n8n-nodes-base.shopify",
      "position": [
        3664,
        -160
      ],
      "parameters": {
        "options": {},
        "orderId": "={{ $json.order_id }}",
        "operation": "get",
        "authentication": "accessToken"
      },
      "typeVersion": 1
    },
    {
      "id": "8b6c737e-ac4e-44cf-8b90-c24a89de8f98",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2224,
        -512
      ],
      "parameters": {
        "width": 592,
        "height": 704,
        "content": "# Automated Refund Request Handler\n\n### How it works\nThis workflow automates refund handling from incoming Gmail messages. It detects emails with \u201cRefund Request\u201d, extracts the Order ID and reason using AI, and fetches real-time order data from Shopify. Based on the order status, it decides whether the refund can be auto-approved or requires manual review. Customers are notified automatically, and every action is logged into Google Sheets for tracking and analytics.\n\n### Setup steps\n1. Connect Gmail OAuth2 (set to production in Google Cloud).\n2. Add Groq API key for AI processing.\n3. Connect Shopify using an access token with read_orders permission.\n4. Connect Google Sheets OAuth2 for logging.\n5. Ensure your sheet contains columns: Date, Order ID, Customer Email, Reason, Outcome, Notes.\n\n### Customization tips\n- Add a date filter to allow refunds only within a specific time window.\n- Replace Gmail alerts with Slack or Discord for faster team response.\n- Extend logic to check payment status before approving refunds."
      },
      "typeVersion": 1
    },
    {
      "id": "3df540c0-efae-4d74-bb0f-dd80b9535600",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2832,
        -512
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 704,
        "content": "## Step 1: Intake & AI Extraction\nTriggers on refund emails.\nExtracts order ID and reason using AI."
      },
      "typeVersion": 1
    },
    {
      "id": "cdc16763-46e7-491c-8ebf-96ef3ecc79d6",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3536,
        -512
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 704,
        "content": "## Step 2: Shopify Validation\nFetches order details from Shopify.\nUsed to verify refund eligibility."
      },
      "typeVersion": 1
    },
    {
      "id": "18c043e7-32d8-480e-938b-0d34103e14d8",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3856,
        -512
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 704,
        "content": "## Step 3: Decision Logic\nChecks if order is delivered.\nRoutes to auto-approve or manual review."
      },
      "typeVersion": 1
    },
    {
      "id": "85d6489c-bd60-482e-901b-a5349982e15d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4144,
        -512
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 704,
        "content": "## Step 4: Notifications & Logging\nSends customer/team emails.\nLogs outcome into Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "813eba65-4e60-4c13-af1a-3c5c5beee814",
      "name": "AI Agent2",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        3056,
        -160
      ],
      "parameters": {
        "text": "=Extract the Order ID and the Reason for the refund from the email details provided below. \n\nInstructions:\n- Look for the Order ID (usually a 4-digit number like 1001).\n- Summarize the reason for the refund in 5 words or less.\n- Respond ONLY with a clean JSON object. No extra text, no \"Here is your data\", just JSON.\n\nDesired Format:\n{\n  \"order_id\": \"value\",\n  \"reason\": \"value\"\n}\n\nEmail Data:\nSubject: {{ $json.Subject }}\nSnippet: {{ $json.snippet }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3
    }
  ],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Send a message to customer",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send a message to the team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent2": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get an order": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Trigger": {
      "main": [
        [
          {
            "node": "AI Agent2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent2",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Get an order",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message to customer": {
      "main": [
        [
          {
            "node": "Logs to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message to the team": {
      "main": [
        [
          {
            "node": "Send a message to customer for \"Pending\" Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message to customer for \"Pending\" Status": {
      "main": [
        [
          {
            "node": "Logs to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}