{
  "name": "Intelligent Invoice Processing with AI Classification and XML Export",
  "nodes": [
    {
      "id": "sticky-overview",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        288
      ],
      "parameters": {
        "width": 420,
        "height": 752,
        "content": "## Intelligent Invoice Processing with AI Classification and XML Export\n\n### Overview\nAutomated invoice processing pipeline that extracts data from PDF invoices, uses AI for intelligent categorization, and exports to accounting systems via XML format.\n\n### Key Features\n- **PDF Text Extraction**: Parse invoice PDFs automatically\n- **AI-Powered Classification**: Categorize expenses, detect anomalies\n- **XML Export**: Generate accounting-compatible XML files\n- **Human Approval Workflow**: Optional review for high-value invoices\n- **Multi-Channel Notifications**: Slack and Email alerts\n\n### Required Credentials\n- Google Drive OAuth (for PDF source)\n- OpenAI API key\n- Slack Bot Token\n- Google Sheets OAuth\n- Gmail OAuth\n\n### Processing Flow\n1. Detect new PDF invoices\n2. Extract text content\n3. AI analyzes and categorizes\n4. Generate XML for accounting\n5. Route for approval if needed\n6. Archive and notify"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-step1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        640
      ],
      "parameters": {
        "color": 7,
        "width": 260,
        "height": 120,
        "content": "### Step 1: Invoice Detection\n- Monitor Google Drive folder\n- Filter for PDF files only\n- Download invoice content"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-step2",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        624
      ],
      "parameters": {
        "color": 7,
        "width": 260,
        "height": 120,
        "content": "### Step 2: Data Extraction\n- Extract text from PDF\n- Parse invoice fields\n- Structure data for AI analysis"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-step3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 260,
        "height": 124,
        "content": "### Step 3: AI Classification\n- AI Agent categorizes expense\n- Detects unusual patterns\n- Suggests GL codes\n- Determines approval needs"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-step4",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        272,
        1120
      ],
      "parameters": {
        "color": 7,
        "width": 260,
        "height": 140,
        "content": "### Step 4: Export & Archive\n- Convert to XML format\n- Route high-value for approval\n- Archive to Sheets\n- Send notifications"
      },
      "typeVersion": 1
    },
    {
      "id": "drive-trigger",
      "name": "New Invoice Trigger",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "position": [
        112,
        304
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 1
    },
    {
      "id": "webhook-trigger",
      "name": "Manual Upload Trigger",
      "type": "n8n-nodes-base.webhook",
      "onError": "continueRegularOutput",
      "position": [
        112,
        480
      ],
      "parameters": {
        "path": "process-invoice",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "merge-triggers",
      "name": "Merge Triggers",
      "type": "n8n-nodes-base.merge",
      "position": [
        320,
        384
      ],
      "parameters": {
        "mode": "chooseBranch"
      },
      "typeVersion": 3
    },
    {
      "id": "filter-pdf",
      "name": "Filter PDF Files",
      "type": "n8n-nodes-base.filter",
      "position": [
        528,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "pdf-check",
              "operator": {
                "type": "string",
                "operation": "endsWith"
              },
              "leftValue": "={{ $json.name || $json.fileName || '' }}",
              "rightValue": ".pdf"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "download-pdf",
      "name": "Download Invoice PDF",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        720,
        384
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "typeVersion": 3
    },
    {
      "id": "extract-pdf",
      "name": "Extract PDF Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        928,
        384
      ],
      "parameters": {
        "options": {},
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "parse-invoice",
      "name": "Parse Invoice Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1120,
        384
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst text = item.json.text || '';\n\nconst patterns = {\n  invoiceNumber: /invoice\\s*#?:?\\s*([A-Z0-9-]+)/i,\n  date: /(\\d{1,2}[\\/\\-]\\d{1,2}[\\/\\-]\\d{2,4})/,\n  total: /total:?\\s*\\$?([\\d,]+\\.?\\d*)/i,\n  vendor: /from:?\\s*([^\\n]+)/i,\n  dueDate: /due\\s*date:?\\s*(\\d{1,2}[\\/\\-]\\d{1,2}[\\/\\-]\\d{2,4})/i\n};\n\nconst extracted = {\n  rawText: text.substring(0, 2000),\n  invoiceNumber: text.match(patterns.invoiceNumber)?.[1] || 'UNKNOWN',\n  invoiceDate: text.match(patterns.date)?.[1] || new Date().toISOString().split('T')[0],\n  totalAmount: parseFloat((text.match(patterns.total)?.[1] || '0').replace(',', '')) || 0,\n  vendorName: text.match(patterns.vendor)?.[1]?.trim() || 'Unknown Vendor',\n  dueDate: text.match(patterns.dueDate)?.[1] || null,\n  fileName: item.json.fileName || 'invoice.pdf',\n  processedAt: new Date().toISOString()\n};\n\nreturn [{ json: extracted }];"
      },
      "typeVersion": 2
    },
    {
      "id": "openai-model",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1264,
        560
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {
          "temperature": 0.2
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ai-classifier",
      "name": "AI Invoice Classifier",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1264,
        384
      ],
      "parameters": {
        "text": "=Analyze this invoice and provide classification:\n\nInvoice Number: {{ $json.invoiceNumber }}\nVendor: {{ $json.vendorName }}\nAmount: ${{ $json.totalAmount }}\nDate: {{ $json.invoiceDate }}\n\nRaw Text (excerpt):\n{{ $json.rawText.substring(0, 500) }}\n\nProvide analysis in this exact JSON format:\n{\n  \"category\": \"one of: Office Supplies, Software, Professional Services, Travel, Equipment, Marketing, Utilities, Other\",\n  \"glCode\": \"suggested GL code like 6100, 6200, etc.\",\n  \"confidence\": 0.0 to 1.0,\n  \"requiresApproval\": true/false (true if amount > 5000 or low confidence),\n  \"anomalyDetected\": true/false,\n  \"anomalyReason\": \"explanation if anomaly detected, null otherwise\",\n  \"summary\": \"brief 1-sentence description of this invoice\"\n}",
        "options": {
          "systemMessage": "You are an expert accountant AI assistant specialized in invoice classification and expense categorization. Analyze invoices carefully and provide accurate categorization. Flag any unusual patterns or potential issues."
        }
      },
      "typeVersion": 1.7
    },
    {
      "id": "parse-ai-result",
      "name": "Parse AI Classification",
      "type": "n8n-nodes-base.code",
      "position": [
        160,
        896
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst originalData = $('Parse Invoice Data').first().json;\n\nlet classification;\ntry {\n  const responseText = item.json.output || item.json.text || '';\n  const jsonMatch = responseText.match(/\\{[\\s\\S]*\\}/);\n  classification = jsonMatch ? JSON.parse(jsonMatch[0]) : {\n    category: 'Other',\n    glCode: '6900',\n    confidence: 0.5,\n    requiresApproval: true,\n    anomalyDetected: false,\n    anomalyReason: null,\n    summary: 'Classification failed - manual review required'\n  };\n} catch (e) {\n  classification = {\n    category: 'Other',\n    glCode: '6900',\n    confidence: 0.5,\n    requiresApproval: true,\n    anomalyDetected: false,\n    anomalyReason: null,\n    summary: 'Parse error: ' + e.message\n  };\n}\n\nreturn [{\n  json: {\n    ...originalData,\n    classification: classification,\n    needsApproval: classification.requiresApproval || originalData.totalAmount > 5000,\n    processingStatus: 'classified'\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "convert-xml",
      "name": "Convert to XML",
      "type": "n8n-nodes-base.xml",
      "position": [
        336,
        896
      ],
      "parameters": {
        "mode": "jsonToxml",
        "options": {
          "rootName": "Invoice"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "format-xml-output",
      "name": "Format XML Output",
      "type": "n8n-nodes-base.set",
      "position": [
        528,
        896
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "xmlContent",
              "type": "string",
              "value": "={{ $json.data }}"
            },
            {
              "id": "2",
              "name": "fileName",
              "type": "string",
              "value": "=invoice_{{ $('Parse Invoice Data').first().json.invoiceNumber }}_{{ $now.format('yyyyMMdd') }}.xml"
            },
            {
              "id": "3",
              "name": "invoiceData",
              "type": "object",
              "value": "={{ $('Parse AI Classification').first().json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "check-approval",
      "name": "Needs Approval?",
      "type": "n8n-nodes-base.if",
      "position": [
        736,
        896
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "approval-check",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.invoiceData.needsApproval }}",
              "rightValue": true
            },
            {
              "id": "high-value",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.invoiceData.totalAmount }}",
              "rightValue": 5000
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "send-approval-email",
      "name": "Request Approval Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        960,
        800
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=Invoice requires approval:\n\nInvoice #: {{ $json.invoiceData.invoiceNumber }}\nVendor: {{ $json.invoiceData.vendorName }}\nAmount: ${{ $json.invoiceData.totalAmount }}\nCategory: {{ $json.invoiceData.classification.category }}\nGL Code: {{ $json.invoiceData.classification.glCode }}\n\nAI Summary: {{ $json.invoiceData.classification.summary }}\n\nPlease review and approve in the finance system.",
        "options": {},
        "subject": "=Invoice Approval Required: {{ $json.invoiceData.vendorName }} - ${{ $json.invoiceData.totalAmount }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-slack-notification",
      "name": "Slack Notification",
      "type": "n8n-nodes-base.slack",
      "position": [
        960,
        992
      ],
      "parameters": {
        "text": "=Invoice Processed\n\n*Invoice:* {{ $json.invoiceData.invoiceNumber }}\n*Vendor:* {{ $json.invoiceData.vendorName }}\n*Amount:* ${{ $json.invoiceData.totalAmount }}\n*Category:* {{ $json.invoiceData.classification.category }}\n*Status:* {{ $json.invoiceData.needsApproval ? 'Pending Approval' : 'Auto-Approved' }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#finance-notifications"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "merge-paths",
      "name": "Merge Processing Paths",
      "type": "n8n-nodes-base.merge",
      "position": [
        1168,
        896
      ],
      "parameters": {},
      "typeVersion": 3
    },
    {
      "id": "log-to-sheets",
      "name": "Archive to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1360,
        896
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "respond-webhook",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1568,
        896
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ {success: true, invoiceNumber: $json.invoiceData.invoiceNumber, status: $json.invoiceData.needsApproval ? 'pending_approval' : 'processed'} }}"
      },
      "typeVersion": 1.1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Convert to XML": {
      "main": [
        [
          {
            "node": "Format XML Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Triggers": {
      "main": [
        [
          {
            "node": "Filter PDF Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Needs Approval?": {
      "main": [
        [
          {
            "node": "Request Approval Email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract PDF Text": {
      "main": [
        [
          {
            "node": "Parse Invoice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter PDF Files": {
      "main": [
        [
          {
            "node": "Download Invoice PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format XML Output": {
      "main": [
        [
          {
            "node": "Needs Approval?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Invoice Classifier",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse Invoice Data": {
      "main": [
        [
          {
            "node": "AI Invoice Classifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Notification": {
      "main": [
        [
          {
            "node": "Merge Processing Paths",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Invoice Trigger": {
      "main": [
        [
          {
            "node": "Merge Triggers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Invoice PDF": {
      "main": [
        [
          {
            "node": "Extract PDF Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Invoice Classifier": {
      "main": [
        [
          {
            "node": "Parse AI Classification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Upload Trigger": {
      "main": [
        [
          {
            "node": "Merge Triggers",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Processing Paths": {
      "main": [
        [
          {
            "node": "Archive to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request Approval Email": {
      "main": [
        [
          {
            "node": "Merge Processing Paths",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Classification": {
      "main": [
        [
          {
            "node": "Convert to XML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Archive to Google Sheets": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}