This workflow follows the OpenAI → Postgres 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 →
{
"name": "27-ai-invoice-ocr-anomaly-detection",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "invoice-upload",
"responseMode": "lastNode",
"options": {}
},
"id": "g7h8i9j0-1111-4444-8888-000000000001",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
400
]
},
{
"parameters": {
"model": "gpt-4o",
"prompt": {
"messages": [
{
"role": "system",
"content": "You are an expert Financial AI Auditor. Analyze the provided invoice text. Extract: vendor_name, invoice_number, po_number, total_amount, and items (array of {description, amount}). ALSO, perform Anomaly Detection: check if the sum of items matches total_amount, if the date is in the future, or if the vendor name looks suspicious. Respond ONLY in valid JSON format with these exact keys: 'vendor_name', 'invoice_number', 'po_number', 'total_amount', 'items_sum', 'ai_anomaly_detected' (boolean), 'anomaly_reason' (string, or 'None' if valid)."
},
{
"role": "user",
"content": "Invoice Text Data:\n{{ $json.invoice_text }}"
}
]
},
"options": {
"responseFormat": "json_object"
}
},
"id": "g7h8i9j0-2222-4444-8888-000000000002",
"name": "OpenAI: OCR & Anomaly Check",
"type": "n8n-nodes-base.openAi",
"typeVersion": 1.2,
"position": [
460,
400
],
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(*) as dup_count FROM processed_invoices WHERE invoice_number = '{{ JSON.parse($json.content).invoice_number }}';",
"options": {}
},
"id": "g7h8i9j0-3333-4444-8888-000000000003",
"name": "PostgreSQL: Check Duplicate",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
680,
400
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// \u0645\u0646\u0637\u0642 \u0646\u0647\u0627\u06cc\u06cc \u062a\u0635\u0645\u06cc\u0645\u200c\u06af\u06cc\u0631\u06cc \u0648 \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc\nconst aiResult = JSON.parse($node['OpenAI: OCR & Anomaly Check'].json.content);\nconst dbResult = $input.first().json;\nconst dupCount = parseInt(dbResult.dup_count || 0);\n\nlet finalStatus = 'approved';\nlet rejectionReason = 'None';\n\n// 1. \u0628\u0631\u0631\u0633\u06cc \u062a\u06a9\u0631\u0627\u0631\u06cc \u0628\u0648\u062f\u0646\nif (dupCount > 0) {\n finalStatus = 'flagged';\n rejectionReason = 'Duplicate invoice number detected in database.';\n}\n// 2. \u0628\u0631\u0631\u0633\u06cc \u0646\u0627\u0647\u0646\u062c\u0627\u0631\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc\nelse if (aiResult.ai_anomaly_detected === true) {\n finalStatus = 'flagged';\n rejectionReason = `AI Anomaly: ${aiResult.anomaly_reason}`;\n}\n// 3. \u0628\u0631\u0631\u0633\u06cc \u0631\u06cc\u0627\u0636\u06cc \u0633\u0627\u062f\u0647 (\u0627\u062e\u062a\u06cc\u0627\u0631\u06cc\u060c \u0627\u06af\u0631 AI \u0627\u0646\u062c\u0627\u0645 \u0646\u062f\u0627\u062f\u0647 \u0628\u0627\u0634\u062f)\nelse if (Math.abs(aiResult.items_sum - aiResult.total_amount) > 0.01) {\n finalStatus = 'flagged';\n rejectionReason = `Math mismatch: Items sum (${aiResult.items_sum}) does not equal Total (${aiResult.total_amount}).`;\n}\n\nreturn [{\n json: {\n vendor_name: aiResult.vendor_name,\n invoice_number: aiResult.invoice_number,\n po_number: aiResult.po_number,\n total_amount: aiResult.total_amount,\n final_status: finalStatus,\n rejection_reason: rejectionReason,\n ai_anomaly_detected: aiResult.ai_anomaly_detected\n }\n}];"
},
"id": "g7h8i9j0-4444-4444-8888-000000000004",
"name": "Code: Final Validation",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
900,
400
]
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "c1",
"leftValue": "={{ $json.final_status }}",
"rightValue": "approved",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
}
}
]
},
"options": {
"fallbackOutput": "default"
}
},
"id": "g7h8i9j0-5555-4444-8888-000000000005",
"name": "Switch: Routing",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
1120,
400
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO processed_invoices (vendor_name, invoice_number, po_number, total_amount, status, processed_at) VALUES ('{{ $json.vendor_name }}', '{{ $json.invoice_number }}', '{{ $json.po_number }}', {{ $json.total_amount }}, 'APPROVED', NOW());",
"options": {}
},
"id": "g7h8i9j0-6666-4444-8888-000000000006",
"name": "PostgreSQL: Insert Approved",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
1340,
320
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"select": "channel",
"channelId": {
"__rl": true,
"value": "C2222333344",
"mode": "list",
"cachedResultName": "finance-alerts"
},
"text": "\ud83d\udea8 *INVOICE FLAGGED FOR REVIEW* \ud83d\udea8\n\n\ud83c\udfe2 *Vendor:* {{ $json.vendor_name }}\n\ud83e\uddfe *Invoice #:* {{ $json.invoice_number }}\n\ud83d\udcb0 *Amount:* ${{ $json.total_amount }}\n\u274c *Reason:* {{ $json.rejection_reason }}\n\n\ud83d\udd17 Action Required: Please review in the Finance Dashboard.",
"otherOptions": {}
},
"id": "g7h8i9j0-7777-4444-8888-000000000007",
"name": "Slack: Finance Alert",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
1340,
480
],
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO audit_log (invoice_number, action_taken, reason, timestamp) VALUES ('{{ $json.invoice_number }}', 'FLAGGED', '{{ $json.rejection_reason }}', NOW());",
"options": {}
},
"id": "g7h8i9j0-8888-4444-8888-000000000008",
"name": "PostgreSQL: Audit Log",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
1560,
480
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "OpenAI: OCR & Anomaly Check",
"type": "main",
"index": 0
}
]
]
},
"OpenAI: OCR & Anomaly Check": {
"main": [
[
{
"node": "PostgreSQL: Check Duplicate",
"type": "main",
"index": 0
}
]
]
},
"PostgreSQL: Check Duplicate": {
"main": [
[
{
"node": "Code: Final Validation",
"type": "main",
"index": 0
}
]
]
},
"Code: Final Validation": {
"main": [
[
{
"node": "Switch: Routing",
"type": "main",
"index": 0
}
]
]
},
"Switch: Routing": {
"main": [
[
{
"node": "PostgreSQL: Insert Approved",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack: Finance Alert",
"type": "main",
"index": 0
}
]
]
},
"Slack: Finance Alert": {
"main": [
[
{
"node": "PostgreSQL: Audit Log",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"saveDataErrorExecution": "all",
"saveDataSuccessExecution": "all"
},
"id": "27-ai-invoice-ocr-anomaly-detection",
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
openAiApipostgresslackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
27-ai-invoice-ocr-anomaly-detection. Uses openAi, postgres, slack. Webhook trigger; 8 nodes.
Source: https://github.com/kooroosh1363/agentic-automation-lab/blob/main/27-ai-invoice-ocr-anomaly-detection/workflow.json — 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.
Pyragogy AI Village - Orchestrazione Master (Architettura Profonda V2). Uses start, postgres, openAi, emailSend. Webhook trigger; 37 nodes.
AI-Driven Handbook Generator with Multi-Agent Orchestration (Pyragogy AI Village). Uses start, postgres, openAi, emailSend. Webhook trigger; 36 nodes.
AI-Driven Handbook Generator with Multi-Agent Orchestration (Pyragogy AI Village). Uses start, postgres, openAi, emailSend. Webhook trigger; 36 nodes.
AI-Driven Handbook Generator with Multi-Agent Orchestration (Pyragogy AI Village). Uses start, postgres, openAi, emailSend. Webhook trigger; 36 nodes.
Pyragogy AI Village - Orchestrazione Master (Architettura Profonda V2). Uses start, postgres, openAi, emailSend. Webhook trigger; 36 nodes.