Format reference · EXTF · 0.2.0

The line before the headings.

A Buchungsstapel file opens with a management record whose shape has nothing to do with the booking rows beneath it. Getting it wrong is the most common reason an otherwise correct export is rejected.

Three records, two shapes

A complete file is three layers: the EXTF management record, the exact versioned column heading, and the booking rows. Only the last two share a shape. The management record always has 31 fields, whichever format version you target.

The first five fields are fixed identifiers. They are what a reader uses to recognise the file at all:

Fixed identifying fields of the management record
FieldValueMeaning
1EXTFIdentifies an EXTF export file.
2700Header version.
321Format category for Buchungsstapel.
4BuchungsstapelFormat name.
513 / 12Data format version: 13 or 12.

A real management record

These lines are produced by the library itself, from metadata with a fixed timestamp so the output is reproducible.

Format version 13

"EXTF";700;21;"Buchungsstapel";13;20260812093000000;;"RE";"my_application";"";1001;1;20260101;4;20260801;20260831;"August 2026";"";1;0;1;"EUR";;"";;;"";;;"";"my-application"

Format version 12 — identical except field 5

"EXTF";700;21;"Buchungsstapel";12;20260812093000000;;"RE";"my_application";"";1001;1;20260101;4;20260801;20260831;"August 2026";"";1;0;1;"EUR";;"";;;"";;;"";"my-application"
Empty is not the same as absent

Reserved fields are written as empty cells, and text fields stay quoted even when empty. Dropping a field instead of emptying it shifts every later field by one position.

Formats that trip people up

  • Created-at timestamp uses yyyyMMddHHmmssSSS — 17 digits including milliseconds, unquoted.
  • Fiscal year start and posting period use yyyyMMdd, unquoted.
  • Text fields are quoted, including designated empty ones. A quote inside application information is escaped by doubling it.
  • Numeric fields are unquoted, including the adviser and client numbers.

The coded fields

Four fields take values from a closed set rather than free input.

Booking type
ConstantDATEV value
FINANCIAL_ACCOUNTING1
ANNUAL_FINANCIAL_STATEMENTS2
Accounting purpose
ConstantDATEV value
INDEPENDENT0
TAX_LAW30
CALCULATION40
COMMERCIAL_LAW50
IFRS64

Building it from Java

Metadata is built once per file and validated on construction, so an impossible combination fails before any row is written. The builder chooses the format version, and the exporter refuses a management record whose version does not match its heading.

import io.github.mrtyldr.datev.core.DatevMetadata;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Currency;

DatevMetadata metadata = DatevMetadata.bookingBatchV13()
        .createdAt(LocalDateTime.now())
        .origin("RE")
        .exportedBy("my_application")
        .advisorNumber(1001)
        .clientNumber(1)
        .fiscalYearStart(LocalDate.of(2026, 1, 1))
        .accountLength(4)
        .period(LocalDate.of(2026, 8, 1), LocalDate.of(2026, 8, 31))
        .description("August 2026")
        .currency(Currency.getInstance("EUR"))
        .applicationInformation("my-application")
        .build();

String record = metadata.toCsvLine();   // the 31-field management record
One version per file

A v12 management record cannot be combined with the 125-column v13 heading. The builder rejects the mismatch rather than writing a file that no importer can interpret.