{
  "id": "jUy81lCLfstHK4wl",
  "name": "Customer Feedback Automation Workflow with Webhook, OpenAI, Jira & Slack",
  "tags": [],
  "nodes": [
    {
      "id": "897474a0-9537-4083-a3b5-cb309bb2c016",
      "name": "Collect Feedback",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1808,
        96
      ],
      "parameters": {
        "path": "customer-feedback",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "fe6b076a-9dc6-48db-9d6b-f140eac913e4",
      "name": "Validate Payload",
      "type": "n8n-nodes-base.if",
      "position": [
        -1568,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "baa976fa-a7b9-462d-9ec2-aaf7f5e82bc6",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.feedback_text ?? '' }}"
            },
            {
              "id": "5ca540be-9a79-4388-bfc7-0f86cbf473a9",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.sentiment ?? '' }}"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "824a6439-613d-4b1b-9745-fe528c9cabf1",
      "name": "Slack \u2013 Payload Error",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1264,
        160
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *Feedback Webhook Error*\nIncoming customer feedback payload is corrupted.\nPlease review and import manually.\n\nPayload received:\n```{{ JSON.stringify($json.body, null, 2) }}```",
        "select": "channel",
        "channelId": "C09S57E2JQ2",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "60a2e196-e5e4-43f9-b1b7-086ae2c3c168",
      "name": "Determine Sentiment",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -1296,
        0
      ],
      "parameters": {
        "modelId": "gpt-4.1",
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=Return only one lowercase word: \"positive\", \"negative\", \"suggestion\", or \"neutral\".\nFeedback:  {{ $json.body.feedback_text }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "12a54d8f-ce42-4a46-8a87-dc902fad61d2",
      "name": "Is Negative or Feature Request?",
      "type": "n8n-nodes-base.if",
      "position": [
        -896,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "b3e5a743-a8b5-43a2-adf6-e950ede423b9",
              "options": {
                "version": 1,
                "caseSensitive": false,
                "typeValidation": "strict"
              },
              "operator": {
                "type": "string",
                "operation": "equal"
              },
              "leftValue": "={{ $json.output[0].content[0].text }}",
              "rightValue": "negative"
            },
            {
              "id": "eb0dcfb4-f104-44ca-9210-06d990418afd",
              "options": {
                "version": 1,
                "caseSensitive": false,
                "typeValidation": "strict"
              },
              "operator": {
                "type": "string",
                "operation": "equal"
              },
              "leftValue": "={{ $json.output[0].content[0].text }}",
              "rightValue": "suggestion"
            },
            {
              "id": "51f59663-ded0-42de-aa0d-e51a8b911320",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.output[0].content[0].text }}",
              "rightValue": "negative"
            },
            {
              "id": "17369b33-e31c-4216-811d-ba113920cbe6",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.output[0].content[0].text }}",
              "rightValue": "suggestion"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "bfc5ad41-6a16-4ac3-8424-b37f9e4a950b",
      "name": "Create Jira Task",
      "type": "n8n-nodes-base.jira",
      "position": [
        -624,
        16
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "id",
          "value": "10000"
        },
        "summary": "=Customer Feedback From \u2013 {{ $('Collect Feedback').item.json.body.user_name }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10003",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "description": "=**Customer Feedback**\n**User:** {{ $('Collect Feedback').item.json.body.user_name }}\n**Email:** {{ $('Collect Feedback').item.json.body.email }}\n**Sentiment:** {{ $json.output[0].content[0].text }}\n\n---\n{{ $('Collect Feedback').item.json.body.feedback_text }}\n\n---\nReceived: {{$now}}\n"
        }
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7276b4c2-821e-410f-842d-baac704da71a",
      "name": "Weekly Summary Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1664,
        592
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "bd87ea1c-c5d0-472c-b346-9302e1208874",
      "name": "Search Weekly Issues",
      "type": "n8n-nodes-base.jira",
      "position": [
        -1440,
        592
      ],
      "parameters": {
        "options": {
          "jql": "project = KAN AND created >= startOfDay()"
        },
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "018ae0ec-d072-4dcc-b4fc-724181644d3f",
      "name": "Send Weekly Slack Summary",
      "type": "n8n-nodes-base.slack",
      "position": [
        -864,
        592
      ],
      "parameters": {
        "text": "=\ud83d\udcca *Weekly Customer Feedback Summary*\n\n{{ $json.output[0].content[0].text }}",
        "select": "channel",
        "channelId": "C09S57E2JQ2",
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "775ca163-29f6-4884-a4c3-cfc79861bf4e",
      "name": "Create Weekly Summary",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -1216,
        592
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "GPT-4.1"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "You are an assistant summarizing customer feedback for management.\nWrite a clear, concise weekly report based only on the provided issues.\nInclude:\n- Overall sentiment distribution\n- Positive patterns\n- Negative patterns / issues\n- Feature requests\n- High-priority problems\n\nFormat the output in official formal message\n"
            },
            {
              "content": "=Here are the feedback issues:\n{{ $json.fields.description }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "558d96d1-54c4-45a4-bcb3-2c24e490b190",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1904,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 278,
        "height": 224,
        "content": "\nReceives customer feedback data via POST webhook."
      },
      "typeVersion": 1
    },
    {
      "id": "ab3d5be5-e71d-4e0f-abeb-4909461da113",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1584,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 1286,
        "height": 432,
        "content": "## AI-Driven Feedback Analysis and Ticket Generation\nThis part of the workflow first checks if the incoming feedback has all the required details. If something is missing, it sends an alert to Slack so the team knows the data is not complete. If everything looks good, OpenAI reads the feedback and decides whether the message is positive, negative, neutral, or a feature request. Then the workflow checks if the result is \u201cnegative\u201d or a \u201csuggestion.\u201d If yes, it automatically creates a Jira task with all the details so the team can review and fix the issue."
      },
      "typeVersion": 1
    },
    {
      "id": "743c5f7d-5ad5-4f43-97e7-951c8c516386",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1760,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 1094,
        "height": 432,
        "content": "**Weekly Summary Trigger:** Runs automatically once per week to generate the summary.\n\n**Search Weekly Issues:** Fetches all Jira issues created today (or within defined time) for weekly reporting.\n\n**Create Weekly Summary:** Uses GPT to prepare a formal summary of all weekly issues and feedback patterns.\n\n**Send Weekly Slack Summary:** Sends the generated weekly summary report to a Slack channel.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1e9013ef-e2f6-4790-bb9c-318e330ede9a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2432,
        -192
      ],
      "parameters": {
        "width": 480,
        "height": 816,
        "content": "## How it Works:\nThis workflow automatically handles customer feedback sent through a webhook. When feedback arrives, the system first checks whether the required fields are present. If something is missing or incorrect, a Slack alert is sent to inform the team that the payload is incomplete. If everything is valid, the workflow sends the feedback text to OpenAI, which analyzes the content and identifies the sentiment \u2014 such as positive, negative, neutral, or a feature suggestion.\n\nIf the sentiment is negative or a feature request, the workflow creates a Jira task so the team can track and resolve the issue. In parallel, there is a weekly scheduled process that collects all Jira feedback issues created during the week. It then sends these issues to OpenAI to generate a clear and easy-to-read weekly summary, which is finally delivered to Slack for the team to review.\n\nOverall, the workflow reduces manual effort, ensures timely alerts, and helps the team stay updated on feedback trends.\n\n\n## Setup Steps:\n\n1.Create a webhook in n8n to receive customer feedback.\n\n2.Add validation logic to check if feedback text and sentiment exist.\n\n3.Connect a Slack account to send error alerts.\n\n4.Configure the OpenAI node with your API key to analyze sentiment.\n\n5.Add conditions to detect negative or suggestion-type feedback.\n\n6.Connect your Jira account and set project/issue type details.\n\n7.Add a weekly Schedule Trigger to run weekly summaries.\n\n8.Connect Slack again to send the final weekly summary report."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7e10cf4d-6577-472c-a1f2-1225d7fd1e2b",
  "connections": {
    "Collect Feedback": {
      "main": [
        [
          {
            "node": "Validate Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Payload": {
      "main": [
        [
          {
            "node": "Determine Sentiment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack \u2013 Payload Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Determine Sentiment": {
      "main": [
        [
          {
            "node": "Is Negative or Feature Request?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Weekly Issues": {
      "main": [
        [
          {
            "node": "Create Weekly Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Weekly Summary": {
      "main": [
        [
          {
            "node": "Send Weekly Slack Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Summary Trigger": {
      "main": [
        [
          {
            "node": "Search Weekly Issues",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Negative or Feature Request?": {
      "main": [
        [
          {
            "node": "Create Jira Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}