{ "name": "Receipt OCR Analysis", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "receipt-upload", "responseMode": "responseNode", "options": {} }, "id": "webhook-receipt-upload", "name": "Webhook - Receipt Upload", "type": "n8n-nodes-base.webhook", "typeVersion": 1, "position": [250, 300], "webhookId": "receipt-upload-webhook" }, { "parameters": { "assignments": { "assignments": [ { "id": "extract-image", "name": "image", "value": "={{ $json.body.image }}", "type": "string" }, { "id": "extract-user-id", "name": "userId", "value": "={{ $json.body.userId }}", "type": "string" } ] }, "options": {} }, "id": "extract-data", "name": "Extract Receipt Data", "type": "n8n-nodes-base.set", "typeVersion": 1, "position": [450, 300] }, { "parameters": { "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "httpHeaderAuth": { "name": "Authorization", "value": "Bearer {{ $env.OCR_API_KEY }}" }, "requestMethod": "POST", "url": "https://api.ocr.space/parse/image", "sendBody": true, "bodyParameters": { "parameters": [ { "name": "apikey", "value": "={{ $env.OCR_API_KEY }}" }, { "name": "base64Image", "value": "={{ $json.image }}" }, { "name": "language", "value": "eng" }, { "name": "isOverlayRequired", "value": "false" } ] }, "options": {} }, "id": "ocr-api-call", "name": "OCR API Call", "type": "n8n-nodes-base.httpRequest", "typeVersion": 1, "position": [650, 300] }, { "parameters": { "jsCode": "// Extract text from OCR response\nconst ocrResponse = $input.item.json;\nconst parsedText = ocrResponse.ParsedResults?.[0]?.ParsedText || '';\n\n// Regular expressions to extract receipt data\nconst amountRegex = /(?:total|amount|sum|\\$|€|£)\\s*:?\\s*([\\d,]+\\.[\\d]{2})/i;\nconst dateRegex = /(\\d{1,2}[\\/\\-]\\d{1,2}[\\/\\-]\\d{2,4})/;\nconst vendorRegex = /^([A-Z][A-Za-z\\s&]+?)(?:\\s|$)/m;\nconst taxRegex = /(?:tax|vat|gst)\\s*:?\\s*([\\d,]+\\.[\\d]{2})/i;\n\n// Extract amount\nlet amount = null;\nconst amountMatch = parsedText.match(amountRegex);\nif (amountMatch) {\n amount = parseFloat(amountMatch[1].replace(/,/g, ''));\n}\n\n// Extract date\nlet date = null;\nconst dateMatch = parsedText.match(dateRegex);\nif (dateMatch) {\n date = dateMatch[1];\n}\n\n// Extract vendor (first line or company name)\nlet vendor = null;\nconst vendorMatch = parsedText.match(vendorRegex);\nif (vendorMatch) {\n vendor = vendorMatch[1].trim();\n}\n\n// Extract tax\nlet tax = null;\nconst taxMatch = parsedText.match(taxRegex);\nif (taxMatch) {\n tax = parseFloat(taxMatch[1].replace(/,/g, ''));\n}\n\n// Calculate confidence score based on extracted data\nlet confidence = 0;\nif (amount) confidence += 0.4;\nif (date) confidence += 0.2;\nif (vendor) confidence += 0.2;\nif (tax) confidence += 0.2;\n\nreturn {\n json: {\n userId: $input.item.json.userId,\n originalImage: $input.item.json.image,\n extractedText: parsedText,\n amount: amount,\n date: date,\n vendor: vendor,\n tax: tax || 0,\n confidence: confidence,\n status: confidence >= 0.6 ? 'needs_review' : 'pending',\n ocrRawResponse: ocrResponse\n }\n};" }, "id": "parse-receipt-data", "name": "Parse Receipt Data", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [850, 300] }, { "parameters": { "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "httpHeaderAuth": { "name": "Authorization", "value": "Bearer {{ $env.BACKEND_API_KEY }}" }, "requestMethod": "POST", "url": "={{ $env.BACKEND_API_URL }}/api/receipts", "sendBody": true, "bodyParameters": { "parameters": [ { "name": "userId", "value": "={{ $json.userId }}" }, { "name": "amount", "value": "={{ $json.amount }}" }, { "name": "date", "value": "={{ $json.date }}" }, { "name": "vendor", "value": "={{ $json.vendor }}" }, { "name": "tax", "value": "={{ $json.tax }}" }, { "name": "confidence", "value": "={{ $json.confidence }}" }, { "name": "status", "value": "={{ $json.status }}" }, { "name": "extractedText", "value": "={{ $json.extractedText }}" } ] }, "options": {} }, "id": "save-to-backend", "name": "Save to Backend", "type": "n8n-nodes-base.httpRequest", "typeVersion": 1, "position": [1050, 300] }, { "parameters": { "respondWith": "json", "responseBody": "={{ { \"success\": true, \"receiptId\": $json.id, \"amount\": $json.amount, \"confidence\": $json.confidence, \"status\": $json.status } }}" }, "id": "respond-success", "name": "Respond Success", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [1250, 300] } ], "connections": { "Webhook - Receipt Upload": { "main": [ [ { "node": "Extract Receipt Data", "type": "main", "index": 0 } ] ] }, "Extract Receipt Data": { "main": [ [ { "node": "OCR API Call", "type": "main", "index": 0 } ] ] }, "OCR API Call": { "main": [ [ { "node": "Parse Receipt Data", "type": "main", "index": 0 } ] ] }, "Parse Receipt Data": { "main": [ [ { "node": "Save to Backend", "type": "main", "index": 0 } ] ] }, "Save to Backend": { "main": [ [ { "node": "Respond Success", "type": "main", "index": 0 } ] ] } }, "pinData": {}, "settings": { "executionOrder": "v1" }, "staticData": null, "tags": [], "triggerCount": 1, "updatedAt": "2024-01-01T00:00:00.000Z", "versionId": "1" }