Anyone doing business in Austria knows the questions: are the company name and address of my new customer correct? Is the company still in the company register, or is it in liquidation? Have insolvency proceedings been opened against a customer I have been supplying for two years? The answers are in the Firmenbuch (company register) of the Ministry of Justice, but hardly anyone checks regularly. In Odoo a contact is created once, and then it ages.
For this we developed the module Firmenbuch for Partners (partner_firmenbuch_at). It connects Odoo contacts with the Firmenbuch and with the BEV's official address register. It is written for Odoo 19 and is available free of charge on GitHub as free software under the LGPL-3 licence:
github.com/Alex0176/odoo-partner-firmenbuch-at
Contents of this article
- The problem: master data that nobody maintains
- What the Module Does
- Suggestions instead of overwriting
- Warnings: insolvency, liquidation, balance sheet
- Address validation with the BEV address register
- Technical implementation
- What the real service taught us
- Installation and set-up
- Data protection: what the module sends to whom
- Tests
- Limits and legal notice
- Frequently asked questions
- Support from Biricon IT Services
The problem: master data that nobody maintains
A contact in Odoo is usually created under time pressure: name, rough address, perhaps a VAT number. That is enough for the first quotation. It is not enough for invoices, which must be legally correctly addressed, and certainly not for noticing that something has changed at the customer. In practice, four gaps appear:
- Incomplete master data. The Firmenbuch number, court and legal form are almost always missing, because looking them up is manual work.
- Wrong spellings. Company name without legal form, typing errors in street or town, swapped postcode. You only notice when the post comes back.
- No monitoring. If a court opens insolvency proceedings or a customer dissolves their company, Odoo learns nothing about it. Sales carries on delivering on account.
- Scattered sources. The Firmenbuch, annual accounts and address register are in different places. Anyone who wants to check them copies data by hand between browser windows.
What the Module Does
- New companies are looked up. If someone creates a contact as a company (country Austria or empty), the module searches the Firmenbuch within a few minutes. If there is exactly one match, empty fields are filled in: street, postcode, town, country, Firmenbuch number, court and legal form.
- Discrepancies are suggested, never overwritten. If the contact says something different from the register, a change suggestion is created, which an employee approves field by field.
- Firmenbuch search on the contact. In the Firmenbuch tab, the search finds companies by name, even if the automatic match was not unambiguous.
- Daily monitoring. The module checks daily which companies and documents have changed in the register, and checks the customers concerned. In addition, every company is fully re-checked at configurable intervals.
- Warning levels. Opened insolvency and restructuring proceedings (from the register's legal facts), liquidation, deletion, negative equity and a low equity ratio are detected and made visible on the contact.
- Address validation. Austrian addresses are checked locally against the official address register of the Federal Office of Metrology and Surveying (BEV).
- Register data on the contact. Court, legal form, managing directors and the legal facts appear in the Firmenbuch tab. They mirror the register and are updated directly.
- Notifications internal only. All messages go to the internal Discuss channel Firmenbuch and to the contact's chatter. A check run across many companies produces one collective message instead of one per company. The module never sends anything to customers.
Suggestions instead of overwriting
Official data is not automatically the better data for your business: perhaps the contact deliberately holds the delivery address, perhaps a short name has been introduced. That is why the module never changes existing values by itself. It only fills in empty fields and, where there are discrepancies, creates a suggestion.
Under Contacts → Firmenbuch → Firmenbuch suggestions you see the current value and the register value for each field. Leave unticked the fields you do not want to apply. With Apply selected only the ticked fields are written; with Reject the suggestion lapses. A new suggestion replaces older open suggestions for the same contact, so that no outdated values are applied.
Warnings: insolvency, liquidation, balance sheet
The module distinguishes three levels:
- Unremarkable: There is nothing to report.
- Warning (yellow): The register contains valid entries on liquidation, dissolution, winding-up, deletion or merger, the company is marked as deleted, or a previous insolvency proceeding was lifted in recent years (default three years, configurable). Or the annual accounts show negative equity, an equity ratio below 8 % (default based on § 23 URG, configurable), an annual loss or a fall in turnover of 25 % or more.
- Critical (red): An insolvency, bankruptcy or restructuring proceeding has been opened and not yet lifted, or an application was dismissed for lack of assets to cover the costs. The latter counts as insolvency.
A coloured banner appears on the contact, a notice in the contact list, and in the search there are filters for Firmenbuch warning and Firmenbuch critical. If a customer becomes critical, the responsible salesperson (otherwise the administrator) receives an activity Firmenbuch: check customers, and the Firmenbuch channel receives a message.
Legal facts. In the register, insolvency proceedings appear not in the company text but as legal facts with a date, case number and court. The module reads them, assigns opening and lifting to the same case number, and shows them on the contact as a list. A lifted proceeding thus becomes mere information after a few years, while a current one is red.
Annual accounts. If the latest annual accounts are available as XML, the module reads equity, annual result, balance sheet total and turnover, and calculates the equity ratio, the change in turnover and the size class under § 221 UGB (including micro-entities). Small companies do not have to publish their turnover; in that case the module shows none. It derives their result from the balance sheet profit less the profit carried forward, and marks it as an estimate. The item names that are searched for are configurable, because the XML is structured differently depending on the form.
Address validation with the BEV address register
The BEV provides the address register as open data (Adresse Relationale Tabellen – Stichtagsdaten, a new reference date twice a year, free to use with attribution). The module downloads the extract via the official INSPIRE ATOM service, around 120 MB with about 2.5 million addresses, and imports it into dedicated, lean tables.
After that, every Austrian company address with a street is checked locally when it is created and whenever it is changed: postcode, street, house number, town and federal state. No address is sent to any service. The result appears as a marker below the address:
- Valid: The address exists like this in the register.
- House number unknown: Street and town are correct, the house number is not.
- Correction suggested: Typing error in street or town, wrong postcode. The correction is ready as a suggestion.
- Not found: The register does not know this address.
An empty federal state is filled in directly. Private contact addresses (type Private address) are not checked. The attribution © Österreichisches Adressregister, Stichtagsdaten vom … appears in the settings with the current reference date. The update runs weekly, but only downloads if the BEV has published a newer reference date.
Technical implementation
Access to the register
The Ministry of Justice offers the Firmenbuch via the FBW web services (HVD) on JustizOnline as a SOAP interface. Access is free of charge, but requires an API key, which you apply for with ID Austria under Informationsweiterverwendung (re-use of public sector information). The key is sent in the HTTP header X-API-KEY. The module uses the service directly, without screen scraping.
The client models/firmenbuch_client.py is pure Python with no Odoo dependency. It knows the queries SUCHEFIRMAREQUEST, AUSZUG_V2_REQUEST, SUCHEURKUNDEREQUEST, URKUNDEREQUEST as well as VERAENDERUNGENFIRMAREQUEST and VERAENDERUNGENURKUNDEREQUEST. This means it can be tested with stored responses. Requests are made at intervals of 0.3 seconds, change queries in blocks of seven days.
Evaluating the extract
Only entries that are still valid are used from the extract (attribute AUFRECHT not false). The name comes from the data identifier FI_DKZ02, the address from FI_DKZ03, the registered seat from FI_DKZ06 and the legal form from FI_DKZ07. In addition there are the court, web address, the persons authorised to represent the company and the legal facts. For the warning level, the texts of all valid entries are searched for the configurable keywords:
DEFAULT_CRITICAL = "Konkursverfahren, Insolvenzverfahren, Sanierungsverfahren, Konkurs eröffnet, ..."
DEFAULT_WARNING = "Liquidation, aufgelöst, Auflösung, Abwicklung, Löschung, gelöscht, Verschmelzung, in Liqu."
The advantage of the keyword check: it works regardless of which field the register uses to record a matter. The disadvantage is described in the section Limits.
Monitoring
The module creates three scheduled actions:
- Look up new companies (every 10 minutes, up to 20 contacts per run). It is also triggered immediately on creation.
- Monitor companies (daily at 04:30). Queries companies and documents changed since the last run (at most 30 days back), checks the customers concerned and then up to 50 customers whose last check is further back than the configured period. Each company is saved in its own transaction, so that an error does not lose earlier results. The result of the run arrives as one collective message in the channel.
- Update address register (weekly at 03:15).
Without an API key, the first two return immediately. A checksum per company prevents unchanged extracts from being evaluated again.
The address register
The BEV data is held in three tables (bev.locality, bev.street, bev.address) with an index on postcode, street code and house number. The import runs via COPY in one transaction, so the tables are replaced in a single step. House numbers are normalised to the register's notation (51-55, 12a). With house numbers the tables take up about 400 MB in the database. If you do not want that, switch off Check house numbers and you will get by with around 150,000 rows.
What the real service taught us
A module that has only been tested against self-written test responses is not yet considered finished. That is why we tested the client against the real service before publication, using the key of our own company. This revealed several deviations from our assumptions, which we have fixed:
- Only the short information. With this key, the extract can only be retrieved at the short information level. The service rejects requests for full information. In version 1.0.0 the daily run still requested it incorrectly; version 1.1.0 fixes this. From the persons, the module takes only the names of the managing directors authorised to represent the company; shareholders and personal addresses are not read.
- Street and house number separate. The address comes as
STRASSEandHAUSNUMMERin separate elements, not as one text. The module puts the two together. - Court in the enforcement block. The competent court is not in the company section, but in the last
VOLLZblock of the extract. - Deleted companies. A deleted company is recognised by an attribute (
MIT_FIRMA_GELOESCHT_DURCH_VNR) and not by a text. The module turns this into the finding Company deleted, which triggers a warning. - The company name is not the search term. The search compares the beginning of the name. “Muster GmbH” finds nothing if the register writes “Muster Gesellschaft m.b.H.”; companies in liquidation carry “in Liqu.” in their name, and the contact name sometimes still contains
&. The module therefore repeats the search without the legal form and compares names without spelling variants of the legal form, without HTML characters and without the suffix “in Liqu.”. A single match is only accepted if its name begins with that of the contact. - Document changes without a Firmenbuch number. The list of changed documents contains only a key. The Firmenbuch number (without check letter) is at the start of this key. The module uses it to assign the changes to customers.
For each of these points there is now an automated test with a replicated response.
The test on our own customer base
After version 1.1.0 we tried the module out on our own customer base. First only a read-only name search ran, then the assignment of the unambiguous matches. Nothing was changed regardless of existing values: empty fields were filled in, discrepancies are waiting as suggestions for approval, and not a single email went out. The result, without naming individual companies:
- 438 company contacts with customer status in Austria or with no country were searched for.
- 138 of these were unambiguously matched in the Firmenbuch. A further 18 had an unambiguous name match but a different address in the register (relocation or a company with the same name), and were therefore left untouched. 2 names are ambiguous.
- Around 280 we did not find, or found only as partial matches. These are private individuals, sole traders, foreign companies, contacts that name only a brand or a place, and companies whose name in the contact differs from the registration, for example because a different legal form is entered there. For them the manual Firmenbuch search remains.
- 63 change suggestions were generated, mostly for street and house number (spelling) and the country.
- 66 warnings, no critical level. 36 companies are marked as deleted in the register (9 of them also in liquidation), 2 had an insolvency proceeding that has since been lifted, and for 42 the annual accounts stood out: low equity ratio, loss or fall in turnover. A deleted company is not automatically a lost customer, but it is a reason to check the address and invoice recipient.
Two lessons from this: a customer base from real operations is a much better test than any replicated response. We found errors in the name search, which are fixed in version 1.1.1 (see above). And the hit rate depends heavily on how carefully the contacts are named: if you write the company name as the register has it, you will be found reliably.
Installation and set-up
Prerequisites: Odoo 19.0 with the standard apps Contacts and Discuss, the Python package requests (present in every Odoo installation) and outgoing HTTPS access to justizonline.gv.at and data.bev.gv.at. The module has no dependencies outside the standard apps, so it does not pull in any further modules.
- Put the folder
partner_firmenbuch_atinto theaddons_path, update the apps list and install the module; on production systems, preferably on a test database first. - The module creates the Discuss channel Firmenbuch (internal users) and adds all administrators. The three scheduled actions are also created.
- Apply for an API key: JustizOnline (ID Austria), Informationsweiterverwendung, API FBW.
- Settings → Firmenbuch: enter the key and Test connection. Then choose the channel, options, keywords and item codes.
odoo-bin -c /etc/odoo/odoo.conf -d <datenbank> -i partner_firmenbuch_at --stop-after-init
Important on production systems: The first run of the address register update starts automatically in the night after installation at 03:15 and downloads around 120 MB. After that, all Austrian contacts are checked; anomalies appear as suggestions and as one message in the channel. If you do not want this, deactivate the scheduled action Address register (BEV): update beforehand or switch off Check Austrian addresses in the settings.
Mass imports: Import with the context keys fb_no_lookup=True and bev_no_check=True. Otherwise every imported Austrian company would be queued for a register query (20 every ten minutes) and every address would be checked on creation.
Data protection: what the module sends to whom
- Personal data: The names of the managing directors are personal data, even though they are public in the register. The module stores them only to maintain the business relationship. If you do not want that, delete the field or do not use it.
- Firmenbuch: Only the name or the Firmenbuch number of contacts that are marked as a company (without a parent company, country Austria or empty) is sent to
justizonline.gv.at, together with the API key. Private individuals and contact persons of a company are never sent. - Address register: Only the public extract is downloaded. Customer addresses do not leave the system.
- No customer emails: Notifications go to the internal channel, to the chatter and, as an activity, to employees.
- Key: The API key is visible to administrators only.
The Firmenbuch is a public register. Re-use of the data is subject to the JustizOnline terms for the re-use of public sector information.
Tests
The module comes with 18 automated tests. They work with replicated register responses and a miniature address extract, and therefore need neither an API key nor a network:
- Normalisation of the Firmenbuch number
- Evaluating the extract (name, address, court, managing directors, deleted company, invalid entries are ignored)
- Name comparison: spelling variants of the legal form, “in Liqu.”, HTML characters, no match for an unrelated company
- Annual accounts: equity, result, balance sheet total
- New company is found, empty fields are filled in, discrepancies are suggested, suggestion is partially applied
- Monitoring: an opened insolvency proceeding sets the level to critical and creates the activity, a lifted proceeding results in a warning, contact persons are not checked separately
- Document changes are assigned via the key
- Without an API key nothing is queried
- Address validation against the miniature extract
odoo-bin -d <testdatenbank> -i partner_firmenbuch_at \
--test-enable --test-tags=/partner_firmenbuch_at --stop-after-init
The German translation is in i18n/de.po.
Limits and legal notice
- A match is a pointer, not legal advice. The status is derived from keywords in valid register entries. Check the register yourself before deciding on credit or terms of delivery.
- Insolvency detection only tested with replicated cases. The module recognises proceedings by words in the free text of the legal facts (opening, lifting, confirmed restructuring plan, for lack of assets). We replicated their format from a real register extract, but we did not have a real insolvency case to hand during development. An unusual wording can therefore be missed. The module does not replace the official Ediktsdatei insolvency database.
- Annual accounts only as XML. Pure PDF submissions are skipped. For very small companies, the balance sheet may have been filed in abridged form, without the figures that the module reads.
- Austria only. Foreign companies are not queried. Company websites are not in the register and are not added.
- Automatic assignment only for an unambiguous match. If there are several companies with the same name, a message in the channel asks for the manual Firmenbuch search.
- Interfaces can change. The module depends on the services of the BMJ and the BEV. If the endpoint, schema or ATOM feed changes, an update may become necessary.
- Tested for Odoo 19. Developed and tested for Odoo 19.0 Community. We have not tested it for other versions. This article is not legal advice.
Frequently asked questions
Does access to the register cost anything?
Not as far as we know: the FBW web services for the re-use of public sector information are free of charge, but require an API key, which you apply for via JustizOnline. The current terms of the Ministry of Justice are authoritative.
Are existing contact data overwritten?
No. The module only writes into empty fields. Differing values are created as a suggestion, which an employee approves field by field.
Do my customers notice anything of the checks?
No. All notifications go to the internal channel, to the contact's chatter and, as an activity, to employees. The module does not send any emails to customers.
Are managing directors or shareholders stored?
The names of the managing directors authorised to represent the company, yes (field Managing director in the Firmenbuch tab); shareholders and addresses of persons, no. Treat the names as personal data.
How many of our customers does the module find?
That depends on the customer base. For us it was 138 of 438 company contacts (around a third). The rest are private individuals, sole traders, foreign companies and contacts whose name does not match the company name. The figures are in the section The test on our own customer base.
Can I find a customer without a Firmenbuch number?
Yes. The Firmenbuch tab has the button Firmenbuch search with a search by name. The module enters data automatically only if exactly one company matches. Otherwise you select the match yourself.
What about companies in Germany or Switzerland?
They are not queried. The module only looks at contacts with country Austria or with no country.
How much storage does the address validation need?
With house numbers about 400 MB in the database and, during import, about 120 MB of temporary disk space. Without house number checking, about 150,000 rows are enough.
What if I only want the Firmenbuch and no address validation?
Switch off Check Austrian addresses in the settings and deactivate the scheduled action for the address register. Then nothing is downloaded.
Under which licence is the module released?
Under the LGPL-3. You may use, adapt and redistribute it. Bug reports and suggestions for improvement are welcome as an issue in the GitHub repository .
Support from Biricon IT Services
We look after Odoo installations for small and medium-sized businesses: from implementation through customisations and migrations to ongoing operation. If you want to keep customer master data in Odoo clean, detect credit risks earlier, or review a module like this one and bring it safely into your production instance, we will be glad to support you. You can find more in-house developments in our blog, for example Product sets in the quotation as a section and Web RBL, the blocklist for attack traffic.
As of: 3 November 2026. Module version 19.0.1.1.1. The sample data in the figures is freely chosen and does not refer to real companies.