← Back to PropTech Guides
BIL-108 • 1800 words

Geautomatiseerde Servicekosten Afrekening & PDF-Factuurverwerking (Vattenfall, Eneco, Vitens) voor Vastgoedbeheerders

Vastgoedbeheerders en institutionele verhuurders in Nederland en Vlaanderen verliezen gemiddeld € 1.490 per maand per 100 woningen door niet-toegewezen Vattenfall-, Eneco-, Essent- en Vitens-facturen en foutieve proratering bij huurderswissels.

⚡ Live Interactive Multi-Apartment Utility Reconciler (billaily.com): Drop 500 utility PDFs from Vattenfall NL, Eneco, Essent, Vitens, Waternet en Luminus or forward utility emails to your dedicated portfolio inbox. Watch 98% auto-assign to exact apartment doors while resolving the remaining 2% with our constrained missing-utility candidate filter.

Open the 100-Door Interactive Reconciler Grid →   |   Sign In via Passwordless Magic Link →

1. Waarom handmatige verwerking van Vattenfall-, Eneco- en Vitens-facturen faalt bij schaalvergroting

Vastgoedbeheerders en residentiële fondsen met 100 tot 5.000 eenheden in Amsterdam, Rotterdam, Utrecht of Antwerpen verliezen maandelijks 27,5 uur en € 1.490 per 100 appartementen aan het handmatig overtypen van Vattenfall-, Eneco-, Essent- en Vitens-pdf-facturen in Excel. Across a typical 100-door residential building, monthly utility ingestion requires reconciling 300 to 500 separate PDF invoices spanning electricity, cold/hot water submetering, district heating, gas, and communal service charges. When property managers rely on shared spreadsheets and manual email attachments, four systemic revenue leaks compound simultaneously:

2. 3-Staps AI-Toewijzingsarchitectuur (98/100 Exact Huisnummer + 2/100 Gefilterde Uitzonderingen)

Billaily eliminates manual data entry by combining a multimodal Gemini 2.5 Pro Vision extraction pipeline with a deterministic 3-Pass Auto-Assignment Engine backed by PostgreSQL 16 Row-Level Security (RLS). Every incoming PDF from Vattenfall NL, Eneco, Essent, Vitens, Waternet en Luminus is parsed into strict JSON coordinates and evaluated through three sequential matching passes:

[Inbound Utility PDF Stream: Vattenfall NL, Eneco, Essent, Vitens, Waternet en Luminus]
       │
       ▼
[Multimodal Vision Parser (Gemini 2.5 Pro)]
  ├─► extracted_meter_serial: "MTR-884920-B"
  ├─► extracted_address_raw:  "Oak Residence, Apt 14"
  ├─► billing_period:         2026-10-01 .. 2026-10-31 (31 days)
  └─► total_amount_cents:     15500 (€)
       │
       ├─► PASS 1: Exact Meter Serial / Contract Lookup (unit_meters)
       │     └─► Match Found? ──► AUTO_ASSIGNED (confidence = 1.000) [84% of bills]
       │
       ├─► PASS 2: Normalized Street + Door Number Fuzzy Match (units)
       │     └─► Match Found? ──► AUTO_ASSIGNED (confidence = 0.950) [14% of bills]
       │
       └─► PASS 3: Constrained Missing-Utility Candidate Filter (2% Exception Queue)
             └─► SQL Filter: Select ONLY apartments in building X still missing
                 utility_type = 'WATER' for period 2026-10-01..2026-10-31
             └─► 1-Click Manager Assignment ──► UPSERT into unit_meters
                 (Future bills from this meter auto-assign in Pass 1 @ 1.000)

The architectural breakthrough lies in Pass 3 (The 2/100 Constrained Exception Queue). Instead of forcing a property manager to scroll through a dropdown of all 200 apartments when a PDF lacks a door number, Billaily queries GET /api/bills/:id/candidate-units to filter the dropdown exclusively to the 2 or 3 doors in that building that have not yet received that utility type for that billing period. The moment the manager clicks to assign the bill, Billaily writes the extracted meter serial into unit_meters so every subsequent monthly invoice from that meter matches automatically at 1.000 confidence.

3. Financiële ROI-Berekening & Unit Economics voor Vastgoedportefeuilles (€ EUR)

For an institutional landlord, co-living operator, or property management firm operating across Burgerlijk Wetboek Boek 7 (Servicekosten afrekening), Huurcommissie, Yardi, RealEstateCore en Exact Online, automating utility PDF ingestion produces immediate, auditable unit-economics returns. Consider a baseline portfolio of 100 apartments processing 500 utility PDFs per month:

4. Architectuurvergelijking: Excel-Spreadsheets vs. Legacy Vastgoedsoftware vs. Billaily 98/100 AI

The table below benchmarks manual spreadsheet workflows against legacy property management suites and Billaily's 98/100 AI Auto-Assignment & Continuous Tenant Ledger architecture:

Operational Dimension Chaotic Landlord Spreadsheets (Excel) Legacy Incumbent Property SaaS Billaily 98/100 AI + Continuous Tenant Ledger
Setup & Onboarding Time Ongoing manual maintenance (27.5 hrs/mo per 100 doors) 3 to 6 months custom ERP consulting Under 15 minutes (Drop PDFs + auto-learn meter serials)
Unassigned Utility PDF Rate 100% manual keying; 8%–14% orphaned or delayed bills 15%–25% OCR failure on multi-page European invoices 98/100 Auto-Assigned + 2/100 Constrained Candidate Queue
Mid-Month Turnover Proration Fragile manual formulas; high dispute rate on move-out Static monthly cycle only; manual journal adjustments Exact Daily Overlap Math (overlap_days / total_period_days)
Arrears vs. Overpayment Ledger Disconnected tabs; overpayments frequently lost Requires full double-entry accounting reconciliation Continuous Tenancy Running Balance (running_balance_cents)
Vacant-Unit Leak & Spike Auditing Zero proactive detection (discovered only after huge bill) Hardware smart-meter capex required (€250+/door) Automated PDF Anomaly Flags (VACANT_UNIT_USAGE & >1.5x spike)
Tenant Transparency & Payment Flow Manual PDF email attachments + WhatsApp screenshots Forces tenants to download a bloated mobile app Zero-App-Store Magic Link (/t/[token]) + 1-click receipt confirmation

5. Praktijkgevallen: Huurderswissel Halverwege de Maand, Voorschot-Tegoeden & Leegstandslekkages

Standard OCR wrappers and generic accounting tools break down when confronted with real-world residential tenancy edge cases. Billaily's database engine handles four mission-critical failure modes natively:

  1. Mid-Month Tenant Move-In / Move-Out Proration: Suppose a district heating invoice from Vattenfall NL, Eneco, Essent, Vitens, Waternet en Luminus covers 2026-10-01 to 2026-10-31 (31 days) for €155.00 (15500 cents). Tenant A moves out on October 14 (14 days = €70.00), the unit sits vacant on October 15 (1 day = €5.00 absorbed by the landlord vacancy ledger), and Tenant B moves in on October 16 (16 days = €80.00). Billaily automatically generates separate PRORATED_UTILITY_CHARGE entries with exact proration_days and total_period_days audit trails.
  2. Bulk Municipal Invoices Missing Apartment Numbers: Water and heating suppliers frequently issue pdf statements containing only a technical point-of-delivery code (POD / PPE / Zählernummer). Once assigned once via the 2/100 Constrained Queue, the meter serial is permanently bound to the apartment in unit_meters.
  3. Continuous Overpayment Credit Carry-Forward: When a tenant pays 150.00 against a 120.00 statement via their Magic Link (/t/[magic_link_token]), Billaily records a running_balance_cents = -3000 surplus credit and automatically deducts 30.00 from next month's utility charge.
  4. Silent Vacant-Unit Consumption & 1.5x Variance Spikes: Any utility bill arriving for a unit with zero active tenancies triggers anomaly_flag = 'VACANT_UNIT_USAGE', while any bill exceeding 1.5x the unit's trailing 6-month average triggers HIGH_VARIANCE_SPIKE before the landlord pays the supplier.

Interactive Engineering Tool: Test Your Portfolio Numbers Live

Run your own invoices or tenancy dates through our embedded calculator below, or open the full-screen tool at /tools/apartment-utility-variance-auditor.

7. 4-Weken Implementatieplan & Koppeling met Exact Online / Yardi / SEPA

Transitioning a 100 to 10,000+ door portfolio from spreadsheets to Billaily requires zero hardware installation and follows a structured 4-week rollout:

Start Automating Your Portfolio on Billaily Today

Join property managers and build-to-rent funds across Europe automating 98/100 utility PDFs with continuous tenant ledgers. Start immediately with our self-serve Stripe plans or request a custom 30-minute Enterprise ERP/SEPA architecture scope.

View Self-Serve Stripe Plans (€79/mo Portfolio Pro) →   |   Join Early-Access Waiting List / Book Enterprise Audit →

PostgreSQL + Supabase Row-Level Security (RLS) Schema

CREATE TABLE utility_bills (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  organization_id UUID NOT NULL,
  building_id UUID NOT NULL REFERENCES buildings(id) ON DELETE CASCADE,
  assigned_unit_id UUID REFERENCES units(id) ON DELETE SET NULL,
  provider_name TEXT NOT NULL,
  utility_type TEXT NOT NULL CHECK (utility_type IN ('ELECTRICITY', 'WATER', 'HEATING', 'GAS', 'INTERNET', 'HOA_COMMUNAL')),
  extracted_meter_serial TEXT,
  extracted_address_raw TEXT,
  billing_period_start DATE NOT NULL,
  billing_period_end DATE NOT NULL,
  total_amount_cents INTEGER NOT NULL,
  currency TEXT NOT NULL DEFAULT 'EUR',
  assignment_status TEXT NOT NULL CHECK (
    assignment_status IN ('AUTO_ASSIGNED', 'NEEDS_UNIT_SELECTION', 'MANUALLY_ASSIGNED', 'ANOMALY_FLAGGED')
  ),
  assignment_confidence NUMERIC(4, 3) NOT NULL DEFAULT 0.000,
  anomaly_flag TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE tenant_ledger_entries (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  organization_id UUID NOT NULL,
  tenancy_id UUID NOT NULL REFERENCES tenancies(id) ON DELETE CASCADE,
  utility_bill_id UUID REFERENCES utility_bills(id) ON DELETE SET NULL,
  entry_type TEXT NOT NULL CHECK (
    entry_type IN ('PRORATED_UTILITY_CHARGE', 'MANUAL_PAYMENT_REPORTED', 'PAYMENT_CONFIRMED', 'OVERPAYMENT_CREDIT_APPLIED')
  ),
  amount_cents INTEGER NOT NULL,
  running_balance_cents INTEGER NOT NULL,
  proration_days INTEGER,
  total_period_days INTEGER,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

ALTER TABLE utility_bills ENABLE ROW LEVEL SECURITY;
ALTER TABLE tenant_ledger_entries ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation_bills ON utility_bills
  USING (organization_id = current_setting('app.current_org_id')::uuid);
CREATE POLICY tenant_isolation_ledger ON tenant_ledger_entries
  USING (organization_id = current_setting('app.current_org_id')::uuid);