Data warehouse integration

Documents to Delta tables in Databricks

Holofin reads PDFs and scans and writes every field into a Delta table governed by Unity Catalog, next to the rest of your lakehouse.

Nordbank Hanse AG
KONTOAUSZUG
Nr. 10/2026 · Blatt 1 von 3
KontoinhaberJonas Weber
IBANDE89 3704 0044 0532 0130 00
Zeitraum01.10.2026 bis 31.10.2026
Alter Kontostand2.184,55 EUR
Summe Gutschriften4.312,00 EUR
Summe Lastschriften3.967,41 EUR
Neuer Kontostand2.592,14 EUR

✓8 fields loaded

!1 flagged for review

A bank statement read by Holofin and loaded into Databricks. Sample document; every name and number on it is invented.

How it works

  1. 1

    Connect Databricks once

    Create a role with insert rights on one schema and paste its credentials into Holofin. Holofin creates the table on the first load; nothing else in Databricks is visible to it.

  2. 2

    Send documents the way you already do

    Upload in the app, forward by email, or post to the API. Holofin classifies each file, splits bundles into documents and reads the fields of each type.

  3. 3

    Query the rows

    Each field lands as one row with its confidence, the page it came from and a needs_review flag. Join it to your own tables in Databricks like any other source.

How the Databricks connector writes

Holofin writes to a Delta table in Unity Catalog through a SQL warehouse, signing in as a service principal with OAuth machine-to-machine credentials. Grants are on one schema, and Unity Catalog keeps the lineage and audit log of every write.

The only grant Holofin needs:

-- Service principal: holofin-loader (OAuth machine-to-machine)
GRANT USE CATALOG ON CATALOG holofin TO `holofin-loader`;
GRANT USE SCHEMA, CREATE TABLE ON SCHEMA holofin.extracted TO `holofin-loader`;
GRANT MODIFY, SELECT ON SCHEMA holofin.extracted TO `holofin-loader`;

The table Holofin writes

One row per field, so a new document type never changes the table. The same columns exist in every warehouse; types follow Databricks's own names.

holofin.extracted.document_fields
document_idSTRINGHolofin's identifier for the document, stable across reloads.
document_typeSTRINGThe class Holofin gave the document: supplier_invoice, payslip, bank_statement, and so on.
fieldSTRINGThe field name, in snake_case, as defined in your extraction schema.
valueSTRINGThe value as normalized text: ISO dates, dot decimals, IBANs without spaces.
confidenceFLOATBetween 0 and 1. How sure Holofin is of the value.
pageINTEGERThe page of the source file the value was read on.
bboxARRAY<FLOAT>Where on that page: x, y, width, height, as fractions of the page.
needs_reviewBOOLEANTrue when the confidence is low or a rule failed, such as a balance that does not add up.
reviewed_bySTRINGWho confirmed or corrected the value in Holofin, once someone has.
loaded_atTIMESTAMPWhen the row was written. Corrections write a new row; the latest wins.

Query it in Databricks

Count the statements whose balances do not add up, week by week, with FILTER and GROUP BY ALL:

-- Statements whose balances do not add up, by week loaded
SELECT
  date_trunc('WEEK', loaded_at) AS week,
  count(DISTINCT document_id) AS statements,
  count(DISTINCT document_id) FILTER (
    WHERE field = 'closing_balance' AND needs_review
  ) AS balance_mismatches
FROM holofin.extracted.document_fields
WHERE document_type = 'bank_statement'
GROUP BY ALL
ORDER BY week DESC

Security

  • Documents are processed in Europe, on OVHcloud servers in France certified ISO 27001.
  • Holofin only ever writes to the schema you grant. It cannot read your other tables.
  • Retention of the source files in Holofin is set per organization, from zero data retention to indefinite. Rows in your warehouse follow your own policies.
  • GDPR: Holofin acts as your processor. No document leaves the European Union.

Frequently asked questions

Can I read the table from a notebook?

Yes. It is a regular Delta table: read it with Spark, SQL or pandas from any notebook or job that has SELECT on the schema.

Why is a closing balance flagged on a bank statement?

Holofin recomputes the closing balance from the opening balance and the transactions it read. When they disagree, the value is loaded with needs_review set to true, whatever its confidence.

How quickly do fields appear in Databricks?

Within seconds of the document being read. Most documents are read in under a minute, so a file sent by email is usually queryable in Databricks a minute later.

What happens when a reviewer corrects a value?

Holofin writes a new row for that field with the corrected value, needs_review set to false and reviewed_by filled in. Keep the latest row per document and field to get the current state, or keep every row for a full audit trail.

Can I choose which fields are loaded?

Yes. Each document type has an extraction schema in Holofin. Add, rename or remove fields there and the next documents load with the new names. Nothing in the table structure changes.

Which documents does Holofin read?

Any business document sent as a PDF, a scan or a photo: invoices, payslips, bank statements, tax notices, company extracts, IDs, certificates. Holofin also checks each file for tampering and can flag a suspicious document before its fields are trusted.

Put Holofin on your own documents.

Every value linked to the page it came from, every PDF checked for tampering, rules checked across the whole file.

Holofin