Skip to content

Invoice Processing Workflow

Automate invoice data extraction from uploaded PDFs and save to your accounting system or spreadsheet.

Use Case

Problem: Manual data entry from invoices is time-consuming and error-prone.

Solution: Automatically extract invoice details (number, date, total, vendor, line items) and send to Google Sheets or accounting software.

Time Saved: ~5 minutes per invoice → Seconds

Workflow Overview

graph LR
    A[Email with Invoice] --> B[Email Trigger]
    B --> C[Filter: Has PDF]
    C --> D[DeepTagger Extract]
    D --> E[Google Sheets]
    E --> F[Slack Notification]

Prerequisites

  1. DeepTagger Setup:
  2. Trained invoice extraction project
  3. Project ID (e.g., fo_1759714105892)
  4. API key configured in n8n

  5. n8n Nodes Required:

  6. Email Trigger (IMAP) or Webhook
  7. DeepTagger (community node)
  8. Google Sheets or Airtable
  9. Slack (optional, for notifications)

  10. Accounts:

  11. Email account for receiving invoices
  12. Google/Airtable account
  13. Slack workspace (optional)

Step-by-Step Setup

Step 1: Create the Workflow

  1. Open n8n
  2. Click "+" to create a new workflow
  3. Name it: Invoice Processing Automation

Step 2: Add Email Trigger

  1. Add node: Email Trigger (IMAP)
  2. Configure:
    Email Account: your-email@company.com
    Folder: INBOX (or create "Invoices" folder)
    Check for emails: Every 5 minutes
    Download attachments: Yes
    
  3. Test: Send yourself a test email with PDF attachment
  1. Add node: Filter
  2. Configure:
    // Only process emails with PDF attachments
    {{ $json["attachments"] !== undefined &&
       $json["attachments"].length > 0 &&
       $json["attachments"][0]["fileName"].endsWith('.pdf') }}
    

This prevents processing emails without invoices.

Step 4: Add DeepTagger Node

  1. Add node: DeepTagger
  2. Select credential: Your DeepTagger API credential
  3. Configure:
    Operation: Extract Data
    Project ID: fo_1759714105892
    Input Type: File
    Binary Property: attachment0
    

!!! tip "Attachment Property" Email nodes name attachments as attachment0, attachment1, etc.

  1. Test: Execute the node to verify extraction works

Step 5: Add Google Sheets Node

  1. Add node: Google Sheets
  2. Authenticate with Google account
  3. Configure:
    Operation: Append Row
    Document: Invoice Tracker (create this spreadsheet)
    Sheet: Sheet1
    Columns:
      - Invoice Number: {{$json["invoice_number"]}}
      - Date: {{$json["date"]}}
      - Vendor: {{$json["vendor"]}}
      - Total: {{$json["total"]}}
      - Email From: {{$node["Email Trigger"].json["from"]}}
      - Processing Date: {{$now}}
    

Step 6: Add Slack Notification (Optional)

  1. Add node: Slack
  2. Configure:
    Operation: Send Message
    Channel: #accounting
    Message:
      New invoice processed!
      Invoice #: {{$json["invoice_number"]}}
      Vendor: {{$json["vendor"]}}
      Total: {{$json["total"]}}
    

Step 7: Activate the Workflow

  1. Click "Active" toggle (top-right)
  2. Workflow is now running automatically!

Complete Workflow JSON

You can import this workflow directly:

{
  "nodes": [
    {
      "name": "Email Trigger",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [250, 300],
      "parameters": {
        "mailbox": "INBOX",
        "options": {
          "downloadAttachments": true
        }
      }
    },
    {
      "name": "Filter PDF",
      "type": "n8n-nodes-base.if",
      "position": [450, 300],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$json[\"attachments\"] !== undefined && $json[\"attachments\"].length > 0}}",
              "value2": true
            }
          ]
        }
      }
    },
    {
      "name": "DeepTagger",
      "type": "n8n-nodes-deeptagger.deepTagger",
      "position": [650, 300],
      "parameters": {
        "operation": "extractData",
        "projectId": "fo_1759714105892",
        "inputType": "file",
        "binaryProperty": "attachment0"
      },
      "credentials": {
        "deepTaggerApi": "DeepTagger Production"
      }
    },
    {
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [850, 300],
      "parameters": {
        "operation": "append",
        "sheetId": "YOUR_SHEET_ID",
        "range": "Sheet1",
        "options": {},
        "columns": {
          "mappings": [
            {
              "key": "Invoice Number",
              "value": "={{$json[\"invoice_number\"]}}"
            },
            {
              "key": "Date",
              "value": "={{$json[\"date\"]}}"
            },
            {
              "key": "Vendor",
              "value": "={{$json[\"vendor\"]}}"
            },
            {
              "key": "Total",
              "value": "={{$json[\"total\"]}}"
            }
          ]
        }
      }
    },
    {
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "position": [1050, 300],
      "parameters": {
        "channel": "#accounting",
        "text": "New invoice processed!\nInvoice #: {{$json[\"invoice_number\"]}}\nVendor: {{$json[\"vendor\"]}}\nTotal: {{$json[\"total\"]}}"
      }
    }
  ],
  "connections": {
    "Email Trigger": {
      "main": [[{"node": "Filter PDF", "type": "main", "index": 0}]]
    },
    "Filter PDF": {
      "main": [[{"node": "DeepTagger", "type": "main", "index": 0}]]
    },
    "DeepTagger": {
      "main": [[{"node": "Google Sheets", "type": "main", "index": 0}]]
    },
    "Google Sheets": {
      "main": [[{"node": "Slack", "type": "main", "index": 0}]]
    }
  }
}

Testing the Workflow

  1. Send test email:
  2. Email yourself with a sample invoice PDF
  3. Subject: "Test Invoice"
  4. Attachment: invoice.pdf

  5. Watch execution:

  6. Go to Executions tab
  7. Click on the running execution
  8. Monitor each node's output

  9. Verify results:

  10. Check Google Sheets for new row
  11. Verify data accuracy
  12. Check Slack for notification (if enabled)

Expected Output

DeepTagger Node Output

{
  "invoice_number": "INV-2025-001",
  "date": "2025-01-15",
  "vendor": "Acme Corporation",
  "total": "$1,234.56",
  "subtotal": "$1,100.00",
  "tax": "$134.56",
  "line_items": [
    {
      "description": "Professional Services",
      "quantity": "10",
      "unit_price": "$100.00",
      "amount": "$1,000.00"
    },
    {
      "description": "Consulting",
      "quantity": "2",
      "unit_price": "$50.00",
      "amount": "$100.00"
    }
  ]
}

Google Sheets Output

Invoice Number Date Vendor Total Email From Processing Date
INV-2025-001 2025-01-15 Acme Corporation $1,234.56 vendor@acme.com 2025-01-15 10:30:00

Advanced Enhancements

1. Error Handling

Add an IF node after DeepTagger to handle extraction failures:

// Check if extraction succeeded
{{$json["error"] === undefined && $json["invoice_number"] !== undefined}}

Success branch: Continue to Google Sheets

Failure branch: Send error notification, log to error database

2. Data Validation

Add a Code node to validate extracted data:

const data = $input.first().json;

// Validation rules
const errors = [];

if (!data.invoice_number || data.invoice_number.length < 3) {
  errors.push("Invalid invoice number");
}

if (!data.total || !data.total.match(/\$[\d,]+\.\d{2}/)) {
  errors.push("Invalid total format");
}

if (!data.date || !data.date.match(/\d{4}-\d{2}-\d{2}/)) {
  errors.push("Invalid date format");
}

return {
  json: {
    ...data,
    validation_passed: errors.length === 0,
    validation_errors: errors
  }
};

3. Duplicate Detection

Add a Google Sheets lookup before appending:

1. Google Sheets (Lookup Rows)
   - Search column: Invoice Number
   - Search value: {{$json["invoice_number"]}}

2. IF Node
   - If found: Skip or update existing
   - If not found: Append new row

4. Multi-Attachment Processing

If emails can have multiple invoices, add a Loop node:

// Split attachments into separate items
{{$json["attachments"].map(att => ({
  attachment: att
}))}}

Then process each attachment through DeepTagger.

5. Archive Processed Emails

Add an Email node to move processed emails:

Operation: Move Email
To Folder: Processed/Invoices

6. Accounting Software Integration

Instead of Google Sheets, integrate with:

  • QuickBooks (via API)
  • Xero (via n8n node)
  • FreshBooks (via HTTP Request)
  • Stripe (for billing)

Example for QuickBooks:

{
  "Line": [
    {
      "Amount": "{{$json[\"total\"]}}",
      "DetailType": "SalesItemLineDetail",
      "SalesItemLineDetail": {
        "ItemRef": {
          "value": "1"
        }
      }
    }
  ],
  "CustomerRef": {
    "value": "{{$json[\"vendor_id\"]}}"
  }
}

Troubleshooting

No data extracted

Problem: DeepTagger returns empty object {}

Solutions: - Check Project ID is correct - Verify project is trained with similar invoices - Check invoice quality (is it readable?) - Test the project in DeepTagger dashboard first

Wrong attachment processed

Problem: Processing wrong file or no file

Solutions: - Check attachment naming in Email node output - Adjust Binary Property: try attachment1, attachment2, etc. - Add Filter to only process first PDF attachment

Duplicate entries in spreadsheet

Problem: Same invoice processed multiple times

Solutions: - Implement duplicate detection (see Advanced #3) - Move processed emails to different folder - Check email trigger is not re-processing old emails

Data format doesn't match spreadsheet

Problem: Dates, numbers in wrong format

Solutions: - Add formatting in Google Sheets node expression:

// Format date
{{$json["date"].split("-").reverse().join("/")}}

// Format currency
{{$json["total"].replace("$", "").replace(",", "")}}

Real-World Results

Case Study: Small Accounting Firm

Before: - Processed 200 invoices/month manually - 5 minutes per invoice = 16.7 hours/month - Error rate: ~5%

After (with this workflow): - Automated processing: 200 invoices/month - Review time: 30 seconds per invoice = 1.7 hours/month - Error rate: <1%

Time Saved: 15 hours/month

ROI: Paid for DeepTagger subscription in 1 week

Next Steps

Share Your Workflow

Built something cool with DeepTagger? Share it!