For the complete documentation index, see llms.txt. This page is also available as Markdown.

Financial Accounting

Export bookings and debtor/creditor master data to an accounting system.

A financial accounting app exports the ERP's bookings and debtor/creditor master data to an accounting system. DATEV is the reference implementation.

Read App Backends first; this page only covers what is specific to accounting.

Registering the finance backend

await methods.createFinanceBackend('DATEV');

Registering it makes your app appear as an export target in the ERP's finance export.

createFinanceBackend takes only a label. Passing a description as a second argument does nothing — it is silently ignored. Set the description afterwards with changeFinanceBackend(label, description).

Note that changeFinanceBackend looks the backend up by your app identifier, not by the label — the label argument only appears in its log message. It returns null instead of throwing when nothing is found.

The export is two-phase

Do not collapse these. The ERP model separates producing the files from transmitting them:

1. Build    ERP data ──► formatted files ──► DMS
2. Transmit DMS files ──► accounting system ──► job status

Phase 1 is triggered by the user, reads the booking run, and writes finished files into the DMS. Phase 2 picks those files up and uploads them. Keeping them apart means a transmission can be retried without regenerating, and the exported files stay auditable.

Both phases are long-running. The reference app answers the HTTP request immediately and continues in the background, writing progress into a status record the UI polls.

Reading the data

Bookings come from computed queries — the booking run, its bookings, and the individual records:

Within a booking, the first record is the header and the remaining records are the lines. A booking with only one record therefore produces no output.

The accounts come straight from the data — there is no mapping table in the app:

Export field
Source

Account (Konto)

the header record's ledger

Contra account (Gegenkonto)

the line record's ledger

Tax key (BU-Schlüssel)

the line record's transaction key

Skip lines whose amount is zero or whose booking state is not OK.

Format details are unforgiving

Accounting formats are validated strictly on import. The things that actually break exports:

Encoding. Write UTF-8 with a byte-order mark. Strip it again when reading your own files back.

Numbers. German decimal comma, exactly two decimals, no thousands separator, and the absolute value — the sign is carried by the debit/credit indicator. If that indicator is lost, the booking silently inverts.

Dates are partial. In the DATEV booking format the document date is only day and month; the year comes from the file header. That is precisely why the export must be split per business year — a booking outside the header's year would be filed under the wrong one. Walk backwards and forwards from the main business year and write additional files as needed.

Field widths and quoting. Fields have maximum lengths and per-field quoting rules. Truncation is silent, and an embedded quote character is usually removed rather than escaped — so validate values before writing rather than trusting the writer.

Timezones. Date formatters typically use local time while a date-only configuration value parses as UTC midnight. On a server west of UTC that shifts the business year by a day. Normalise before comparing.

Configuration

An accounting integration needs client identification — for DATEV the consultant number and client number, which combine into the client id used on every API call. Along with the business-year start and the ledger account length, these are required before an export can run: gate the export button on them rather than failing mid-run.

Store them where both your export code and your API layer can read them, and remember that values round-trip as strings.

What to watch out for

Make re-exports distinguishable. A regenerated file must not silently overwrite the previous one — add a suffix. Auditors need to see what was sent and when.

Deduplicate transmissions. Track which files and documents already succeeded and skip them on a re-run, or you create duplicate jobs in the accounting system. Treat the accounting system's own "duplicate" response as success, not as an error.

Guard against concurrent runs, with a staleness timeout so a crashed run doesn't block the export forever.

Respect rate limits and retry properly. Honour Retry-After on 429/503, then back off exponentially with a cap. Distinguish fatal errors (missing rights, expired authorisation) — which should abort the whole run — from per-document failures, which should be logged and skipped.

Check the export rights explicitly. An authorised session is not the same as an authorised service. Verify the required services are enabled for the client and surface a clear message; otherwise a missing entitlement looks like a generic authorisation failure.

Attachments have size limits. Document upload limits are enforced on both sides — check the size before uploading and report oversized documents as warnings rather than aborting the run.

Long-lived authorisation expires. Refresh tokens for accounting APIs can last months or years, but they do expire; handle the expiry as a normal state with a re-authorisation prompt.

Last updated

Was this helpful?