{
  "name": "Invoice Approval Handler (Slack Listener)",
  "tags": [
    {
      "name": "Finance"
    },
    {
      "name": "Invoice Automation"
    },
    {
      "name": "Slack"
    }
  ],
  "nodes": [
    {
      "id": "f024271f-524f-4ab5-b7fb-43ed93e2bea3",
      "name": "Receive Slack Button Click",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -64,
        416
      ],
      "parameters": {
        "path": "invoice-approval-handler",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "3c8f8381-a479-4e37-a35a-32f185762422",
      "name": "Parse Slack Payload",
      "type": "n8n-nodes-base.set",
      "position": [
        208,
        416
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a493fcd6-0bf3-4887-bd69-4026c14c3d22",
              "name": "payload",
              "type": "object",
              "value": "={{ JSON.parse($json.body.payload) }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e22d06ad-d82d-433d-8360-3089e8ad35e4",
      "name": "Extract Decision & Invoice Data",
      "type": "n8n-nodes-base.set",
      "position": [
        480,
        416
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ecc7c2a7-85a2-4bb6-8213-06b409ab9281",
              "name": "decision",
              "type": "string",
              "value": "={{ $json.payload.actions[0].value }}"
            },
            {
              "id": "d6f8aad0-508f-4a38-99ed-00eb76bcd7f8",
              "name": "decided_by",
              "type": "string",
              "value": "={{ $json.payload.user.name }}"
            },
            {
              "id": "277dbaef-143b-4603-85d4-b69f1284b3d9",
              "name": "decided_by_id",
              "type": "string",
              "value": "={{ $json.payload.user.id }}"
            },
            {
              "id": "44951b7f-73c9-48df-b8ce-189bbcaa2112",
              "name": "channel_id",
              "type": "string",
              "value": "={{ $json.payload.channel.id }}"
            },
            {
              "id": "224e0814-6d1f-4ff8-90d5-a08bb05da837",
              "name": "message_ts",
              "type": "string",
              "value": "={{ $json.payload.message.ts }}"
            },
            {
              "id": "1d96a304-f9ca-43e1-b1c2-590b8ce92c21",
              "name": "supplier_name",
              "type": "string",
              "value": "={{ $json.payload.message.blocks[1].fields[0].text.split('\\n')[1] }}"
            },
            {
              "id": "99f3f0a9-b595-4057-ac33-2421cc5b6ca5",
              "name": "invoice_number",
              "type": "string",
              "value": "={{ $json.payload.message.blocks[1].fields[1].text.split('\\n')[1] }}"
            },
            {
              "id": "fb44a6ec-6441-4c8e-9143-85fe7577211c",
              "name": "amount",
              "type": "string",
              "value": "={{ $json.payload.message.blocks[1].fields[2].text.split('\\n')[1] }}"
            },
            {
              "id": "3b17ccc8-108a-4586-b6de-2b1685b21539",
              "name": "invoice_date",
              "type": "string",
              "value": "={{ $json.payload.message.blocks[1].fields[3].text.split('\\n')[1] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "899c3038-7397-441e-990e-8ef38977fa97",
      "name": "Route: Approved / Rejected / Flagged",
      "type": "n8n-nodes-base.switch",
      "position": [
        752,
        400
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Approved",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.decision }}",
                    "rightValue": "approved"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Rejected",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.decision }}",
                    "rightValue": "rejected"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Flagged",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.decision }}",
                    "rightValue": "flagged"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "dfe0a576-d0f1-4b6e-affb-ec93ab80597f",
      "name": "Log to Sheets: Approved",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1024,
        240
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.invoice_date }}",
            "Amount": "={{ $json.amount }}",
            "Supplier Name": "={{ $json.supplier_name }}",
            "Invoice Number": "={{ $json.invoice_number }}"
          },
          "schema": [
            {
              "id": "Supplier Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Supplier Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Invoice Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Invoice Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Approved"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "9fb05679-ed5b-44b2-a72a-e2f0f88ea622",
      "name": "Log to Sheets: Rejected",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1024,
        416
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.invoice_date }}",
            "Amount": "={{ $json.amount }}",
            "Supplier Name": "={{ $json.supplier_name }}",
            "Invoice Number": "={{ $json.invoice_number }}"
          },
          "schema": [
            {
              "id": "Supplier Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Supplier Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Invoice Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Invoice Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Rejected"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "a2d9b4fe-16e0-4514-aa9c-daf65ee080ad",
      "name": "Log to Sheets: Flagged",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1024,
        592
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.invoice_date }}",
            "Amount": "={{ $json.amount }}",
            "Supplier Name": "={{ $json.supplier_name }}",
            "Invoice Number": "={{ $json.invoice_number }}"
          },
          "schema": [
            {
              "id": "Supplier Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Supplier Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Invoice Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Invoice Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Flagged"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "f444c5fb-0d76-413d-b170-4dd085d668c8",
      "name": "Slack DM: Approved \u2705",
      "type": "n8n-nodes-base.slack",
      "position": [
        1296,
        240
      ],
      "parameters": {
        "text": "=\u2705 *Invoice Approved & Ready to Pay*\n\n*Supplier:* {{ $json['Supplier Name'] }}\n*Invoice #:* {{ $json['Invoice Number'] }}\n*Amount:* {{ $json.Amount }}\n*Date:* {{ $json.Date }}\n*Approved by:* {{ $('Route: Approved / Rejected / Flagged').item.json.decided_by }}",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_USER_ID"
        },
        "select": "user",
        "otherOptions": {}
      },
      "typeVersion": 2.3
    },
    {
      "id": "58e53f7a-c8f1-4ddd-b8ad-f16691d55cab",
      "name": "Slack DM: Rejected \u274c",
      "type": "n8n-nodes-base.slack",
      "position": [
        1296,
        416
      ],
      "parameters": {
        "text": "=\u274c *Invoice Rejected*\n\n*Supplier:* {{ $json['Supplier Name'] }}\n*Invoice #:* {{ $json['Invoice Number'] }}\n*Amount:* {{ $json.Amount }}\n*Date:* {{ $json.Date }}\n*Rejected by:* {{ $('Route: Approved / Rejected / Flagged').item.json.decided_by }}",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_USER_ID"
        },
        "select": "user",
        "otherOptions": {}
      },
      "typeVersion": 2.3
    },
    {
      "id": "5473fdea-f831-4da8-8c0d-94fcae527931",
      "name": "Slack DM: Flagged \ud83d\udea9",
      "type": "n8n-nodes-base.slack",
      "position": [
        1296,
        592
      ],
      "parameters": {
        "text": "=\ud83d\udea9 *Invoice Flagged for Review*\n\n*Supplier:* {{ $json['Supplier Name'] }}\n*Invoice #:* {{ $json['Invoice Number'] }}\n*Amount:* {{ $json.Amount }}\n*Date:* {{ $json.Date }}\n*Flagged by:* {{ $('Route: Approved / Rejected / Flagged').item.json.decided_by }}\n\n\u26a0\ufe0f Please review this invoice manually.",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_USER_ID"
        },
        "select": "user",
        "otherOptions": {}
      },
      "typeVersion": 2.3
    },
    {
      "id": "45e5c100-b3c5-430d-b5cb-33c8ba1b7f8a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 272,
        "content": "### \ud83d\udd14 Slack Webhook\nReceives button click events from Slack Interactivity"
      },
      "typeVersion": 1
    },
    {
      "id": "6ebf1842-3c96-425a-9cf5-454a491bb489",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 272,
        "content": "### \ud83d\udce6 Parse Payload\nConverts Slack's URL-encoded payload into JSON object"
      },
      "typeVersion": 1
    },
    {
      "id": "f536f100-b96e-45dd-aa23-8b2a36d7063f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 272,
        "content": "### \ud83d\udccb Extract Decision Data\nPulls decision, user, and invoice details from Slack message"
      },
      "typeVersion": 1
    },
    {
      "id": "0c8770a8-1c00-455d-acb0-b6b6f3f48c5b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 336,
        "content": "### \ud83d\udd00 Route by Decision\nBranches flow: Approved \u2192 Rejected \u2192 Flagged"
      },
      "typeVersion": 1
    },
    {
      "id": "3e58c7fc-8301-490f-acaa-85a013c82ef1",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 608,
        "content": "### \ud83d\udcca Log to Sheets\nAppends invoice data to the appropriate Google Sheets tab"
      },
      "typeVersion": 1
    },
    {
      "id": "783c33e9-68a3-4082-9184-a2a4db6f04e4",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 608,
        "content": "### \ud83d\udcac Send Confirmation\nNotifies the approver via Slack DM"
      },
      "typeVersion": 1
    },
    {
      "id": "32f0f5bd-897b-49dc-b85f-71dcfe5505a6",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -832,
        -160
      ],
      "parameters": {
        "width": 672,
        "height": 1264,
        "content": "# \ud83d\udce5 Invoice Approval Handler\n(Slack Button Listener)\n\n## What This Workflow Does\nListens for button clicks from the **Invoice \u2192 Slack Approval** workflow. When someone clicks Approve, Reject, or Flag on an invoice in Slack, this workflow captures that decision, logs it to **Google Sheets**, and sends a confirmation notification.\n\n## How It Works\n1. **Webhook Trigger** \u2013 Receives POST request from Slack when a button is clicked\n2. **Parse Payload** \u2013 Extracts the JSON payload from Slack's request body\n3. **Extract Decision Data** \u2013 Pulls decision, user info, and invoice details from the message\n4. **Route by Decision** \u2013 Branches to Approved, Rejected, or Flagged path\n5. **Log to Sheets** \u2013 Appends invoice data to the appropriate sheet tab\n6. **Notify via Slack** \u2013 Sends confirmation DM to the approver\n\n## Decision Routes\n- \u2705 **Approved** \u2192 Logs to \"Approved\" sheet \u2192 DM confirmation\n- \u274c **Rejected** \u2192 Logs to \"Rejected\" sheet \u2192 DM confirmation\n- \ud83d\udea9 **Flagged** \u2192 Logs to \"Flagged\" sheet \u2192 DM for manual review\n\n---\n\n## Setup Guide\n\n### 1. Create Google Sheet\n1. Create a new Google Sheet with 3 tabs: `Approved`, `Rejected`, `Flagged`\n2. Add these column headers to each tab:\n   - Supplier Name\n   - Invoice Number\n   - Amount\n   - Date\n3. Copy the **Sheet ID** from the URL\n\n### 2. Connect the Nodes in n8n\n1. Add your **Google Sheets OAuth2** credential to all three logging nodes\n2. Update the **Document ID** in each Google Sheets node to your Sheet ID\n3. Add your **Slack API** credential to all three notification nodes\n4. Update the **User ID** in the notification nodes (or change to channel)\n\n### 3. Configure Slack Interactivity\n1. Go to **api.slack.com/apps** \u2192 your app \u2192 **Interactivity & Shortcuts**\n2. Set the Request URL to this workflow's webhook URL\n3. Save Changes\n\n### 4. Activate & Test\n1. Click **Active** in the top-right corner of n8n\n2. Trigger the Invoice Approval workflow to send a Slack message\n3. Click a button in Slack\n4. Check Google Sheets and Slack for results"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Parse Slack Payload": {
      "main": [
        [
          {
            "node": "Extract Decision & Invoice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Sheets: Flagged": {
      "main": [
        [
          {
            "node": "Slack DM: Flagged \ud83d\udea9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Sheets: Approved": {
      "main": [
        [
          {
            "node": "Slack DM: Approved \u2705",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Sheets: Rejected": {
      "main": [
        [
          {
            "node": "Slack DM: Rejected \u274c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Slack Button Click": {
      "main": [
        [
          {
            "node": "Parse Slack Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Decision & Invoice Data": {
      "main": [
        [
          {
            "node": "Route: Approved / Rejected / Flagged",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route: Approved / Rejected / Flagged": {
      "main": [
        [
          {
            "node": "Log to Sheets: Approved",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log to Sheets: Rejected",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log to Sheets: Flagged",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}