Fynteq logo
Financial Automation6 min read

How to Automate Accounts Payable with n8n and AI (German Mittelstand Guide)

Step-by-step guide to AP automation for German Mittelstand using n8n workflows, AI invoice extraction, E-Rechnung processing, and DATEV integration.

Fynteq Team

Summary

German Mittelstand companies can automate 80% of accounts payable processing using n8n orchestration, AI-powered invoice extraction, E-Rechnung intake, and DATEV export: without enterprise ERP budgets.

Definition

Accounts payable automation for the German Mittelstand combines invoice intake (email, portal, E-Rechnung), AI-powered data extraction, approval routing, and ERP/DATEV export, orchestrated by workflow tools like n8n without requiring SAP or enterprise AP platforms.

Why n8n for Mittelstand AP

Enterprise AP solutions (Basware, Tipalti, Yokoy) cost €50K+ annually and assume SAP/Oracle backends. German Mittelstand companies: 50 to 500 employees, €10M–€100M revenue: need automation that connects to DATEV, Lexware, or SevDesk without six-figure contracts.

n8n provides:

  • Self-hosted data control (GDPR, GoBD)
  • Visual workflow builder finance teams can modify
  • 400+ integrations including email, Slack, HTTP, databases
  • AI node support for Claude/GPT extraction
  • One-time setup cost, low ongoing fees

Architecture Overview

Invoice Intake → Format Detection → Extraction → Validation → Approval → Export
     ↓                  ↓               ↓            ↓           ↓          ↓
  Email/IMAP      XRechnung/ZUGFeRD   AI/OCR     Rules Engine  Slack    DATEV CSV
  Supplier Portal    PDF scan       Claude      PO Match     Email    Lexware API

Step 1: Invoice Intake Workflow

Create an n8n workflow triggered by email (IMAP) or webhook:

{
  "nodes": [
    {
      "name": "Email Trigger",
      "type": "n8n-nodes-base.emailReadImap",
      "parameters": {
        "mailbox": "rechnungen@company.de",
        "downloadAttachments": true
      }
    },
    {
      "name": "Detect Format",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const items = $input.all();\nreturn items.map(item => {\n  const filename = item.binary?.attachment_0?.fileName || '';\n  const mime = item.binary?.attachment_0?.mimeType || '';\n  let format = 'unknown';\n  if (mime === 'application/xml' || filename.endsWith('.xml')) format = 'xrechnung';\n  else if (mime === 'application/pdf') format = 'pdf';\n  return { json: { ...item.json, format, filename } };\n});"
      }
    }
  ]
}

Route by format: XML → direct parsing, PDF → AI extraction, ZUGFeRD → embedded XML extraction first, fallback to AI.

Step 2: AI Invoice Extraction

For PDF invoices without structured data, use Claude with structured output:

// n8n Code node - call Claude API
const pdfBase64 = items[0].binary.attachment_0.data;

const response = await fetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: {
    'x-api-key': $env.ANTHROPIC_API_KEY,
    'anthropic-version': '2023-06-01',
    'content-type': 'application/json'
  },
  body: JSON.stringify({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 2000,
    messages: [{
      role: 'user',
      content: [
        {
          type: 'document',
          source: { type: 'base64', media_type: 'application/pdf', data: pdfBase64 }
        },
        {
          type: 'text',
          text: `Extract invoice data as JSON with fields:
            rechnungsnummer, rechnungsdatum, faelligkeitsdatum,
            lieferant_name, lieferant_ustid, nettobetrag, ust_betrag,
            bruttobetrag, waehrung, positionen (array of beschreibung, menge, einzelpreis, steuersatz).
            Return ONLY valid JSON.`
        }
      ]
    }]
  })
});

const extracted = JSON.parse(response.content[0].text);
return [{ json: extracted }];

Set confidence thresholds: auto-approve extractions above 95% field match against vendor master data. Route lower confidence to human review.

Step 3: Validation Rules

Before approval, validate extracted data:

RuleAction on Fail
USt-IdNr. format valid (DE + 9 digits)Flag for review
USt-IdNr. matches vendor masterBlock until verified
Duplicate Rechnungsnummer + LieferantReject as duplicate
PO number match (if required)Route to procurement
Amount within PO tolerance (±5%)Route to manager
Bank details changed from last invoiceRequire dual approval
// Validation code node
const invoice = $input.first().json;
const vendor = await $('PostgreSQL').execute({
  query: 'SELECT * FROM vendors WHERE ust_id = $1',
  params: [invoice.lieferant_ustid]
});

const errors = [];
if (!vendor) errors.push('Unknown vendor USt-IdNr.');
if (vendor && vendor.default_iban !== invoice.lieferant_iban) {
  errors.push('IBAN changed from vendor master');
}

const duplicate = await $('PostgreSQL').execute({
  query: 'SELECT id FROM invoices WHERE number = $1 AND vendor_id = $2',
  params: [invoice.rechnungsnummer, vendor?.id]
});
if (duplicate.length) errors.push('Duplicate invoice');

return [{ json: { ...invoice, validation_errors: errors, status: errors.length ? 'review' : 'approved' } }];

Step 4: Approval Routing

Use n8n Switch node for approval matrix:

  • < €500: Auto-approve if validation passes
  • €500–€5,000: Slack approval to department head
  • €5,000–€25,000: Email + Slack to finance manager
  • > €25,000: Sequential approval (FM → CFO)
{
  "name": "Approval Router",
  "type": "n8n-nodes-base.switch",
  "parameters": {
    "rules": {
      "rules": [
        { "value": "={{ $json.bruttobetrag }}", "operation": "smallerEqual", "output": 0, "value2": 500 },
        { "value": "={{ $json.bruttobetrag }}", "operation": "smallerEqual", "output": 1, "value2": 5000 },
        { "value": "={{ $json.bruttobetrag }}", "operation": "smallerEqual", "output": 2, "value2": 25000 }
      ]
    }
  }
}

Wait for approval via n8n Wait node with webhook callback from Slack interactive buttons.

Step 5: DATEV Export

Generate DATEV-compatible CSV (EXTF Buchungsstapel):

const invoice = $input.first().json;
const datevRow = [
  '11000',                              // Umsatz
  'H',                                  // Soll/Haben
  'EUR',                                // Währung
  '',                                   // Kurs
  '',                                   // Basisumsatz
  '',                                   // WKZ Basis
  invoice.nettobetrag.toFixed(2).replace('.', ','),  // Netto
  '8400',                               // Gegenkonto (Aufwand)
  '0000',                               // BU-Schlüssel
  formatDate(invoice.rechnungsdatum),   // Belegdatum
  invoice.rechnungsnummer,              // Belegnummer
  '',                                   // Belegtext
  '1',                                  // Postensperre
  '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''
].join(';');

await writeFile(`/exports/datev_${Date.now()}.csv`, datevRow);

Upload to DATEV Unternehmen online via DATEVconnect API or manual import: depending on your DATEV package.

Step 6: E-Rechnung Processing

For XRechnung/ZUGFeRD, skip AI extraction when structured XML is available:

# External Python service called via n8n HTTP node
from lxml import etree

def parse_xrechnung(xml_bytes):
    ns = {'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
          'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'}
    root = etree.fromstring(xml_bytes)
    return {
        'rechnungsnummer': root.find('.//cbc:ID', ns).text,
        'rechnungsdatum': root.find('.//cbc:IssueDate', ns).text,
        'lieferant_name': root.find('.//cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name', ns).text,
        'lieferant_ustid': root.find('.//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', ns).text,
        'bruttobetrag': float(root.find('.//cbc:TaxInclusiveAmount', ns).text),
        'nettobetrag': float(root.find('.//cbc:TaxExclusiveAmount', ns).text),
    }

Structured extraction is faster, cheaper, and more accurate than AI: always prefer XML when available.

Monitoring and Metrics

Track in n8n or connected Grafana:

MetricTarget
Auto-processing rate>80% of invoices
AI extraction accuracy>95% field-level
Average processing timeunder 5 minutes
Duplicate detection rate100%
DATEV export errorsunder 1%

Common Pitfalls

  • Running n8n cloud without self-hosting for sensitive invoice data (GDPR concern)
  • No vendor master data maintenance: AI extraction cannot validate unknown vendors
  • Skipping IBAN change detection: primary fraud vector in AP
  • Manual DATEV CSV without automated upload: creates second bottleneck
  • Over-automating first invoice from new vendors: always require human review

Business Outcomes

Mittelstand companies implementing this stack process invoices in under 5 minutes versus 15–20 minutes manually, reduce AP headcount needs by 1–2 FTE, achieve 99%+ duplicate detection, and maintain GoBD-compliant audit trails through n8n execution logs.

Related: E-Rechnung 2025 Guide · E-Rechnung integration

Need help connecting your finance systems?

Fynteq connects E-Rechnung, DATEV, Stripe, ERP and bank workflows for German SMEs and growing digital businesses. Frankfurt-based, fixed-scope implementation.

Frequently Asked Questions

Related articles

View all insights →

Finance integration insights

Practical guides on E-Rechnung, DATEV, Stripe, reconciliation and finance automation for teams in Germany.

By downloading, you agree to our privacy policy. We use your email to send the PDF and follow up on related services. Or contact info@fynteq.com.