# DiPAgE — Record Field Reference

> PSM-Anwendungsdatensatz · `urn:psm:anwendung-datensatz:1.0.0` · JSON Schema draft 2020-12
> 69 documented fields across 18 sections, in German, English and Polish.

Machine-readable schema: `record.schema.json` · Complete example record: `record.example.json`

Generated by `scripts/generate-record-reference.ts` — do not edit by hand;
edit `src/app/data/record-reference.data.ts` and regenerate.

---
## Deutsch

Feldreferenz des PSM-Anwendungsdatensatzes. Erzeugt aus derselben Quelle wie die Referenzseite der DiPAgE-Website.

### Systemfelder

`(root)` — 3 Felder

Identität, Erstellungszeitpunkt und Formatversion. Die App vergibt alle drei selbst; beim Import werden sie ergänzt, wenn sie fehlen.

#### `datensatz_id`

`datensatz_id`

- **Typ:** `string (uuid)` — **Pflicht**
- **Einschränkungen:** `format: uuid`
- **Beispiel:** `"019e7271-637f-7412-87be-4073c257db12"`

Global eindeutige Datensatz-ID. Die App erzeugt UUIDv7 — zeitgeordnet, sodass eine Sortierung nach ID der Erstellungsreihenfolge entspricht.

> **Hinweis:** Beim Import mit leerer ID-Spalte wird pro Zeile eine frische UUID vergeben. Zwei Importe derselben Datei erzeugen daher unterschiedliche IDs; die Duplikaterkennung greift dann über den Inhalts-Fingerprint statt über die ID.

#### `datensatz_erstellung_zeitpunkt`

`datensatz_erstellung_zeitpunkt`

- **Typ:** `string (date-time)` — **Pflicht**
- **Einschränkungen:** `format: date-time`
- **Beispiel:** `"2026-05-27T14:32:00Z"`

Zeitpunkt der Erstellung des Datensatzes, nicht der Anwendung. Der Anwendungszeitpunkt steht in anwendung_zeitpunkt.

> **Hinweis:** Beim Speichern mehrerer Datensätze in einem Durchgang (Tankmischung, Sammelerfassung) erhalten sie synthetische Zeitstempel im Abstand von 10 ms ab einem gemeinsamen Basiswert. Gleiche Basis plus gleiches Anwendungsdatum ist genau das Merkmal, an dem die App eine Tankmischung wiedererkennt.

#### `datensatz_format_version`

`datensatz_format_version`

- **Typ:** `string (const)` — **Pflicht**
- **Einschränkungen:** `const: "1.0.0"`
- **Beispiel:** `"1.0.0"`

Version des Datensatzformats. Im Schema als const eingefroren: jeder gültige Datensatz trägt exakt "1.0.0".

> **Hinweis:** Nicht mit der IndexedDB-Version der App verwechseln. Es gibt drei unabhängige Zahlen: diese eingefrorene Formatversion, einen informellen Schema-Zähler in Kommentaren und Changelog, und die IndexedDB-DB_VERSION.

### Anwender

`anwender[]` — 4 Felder

Array mit mindestens einem Eintrag. Jeder Eintrag ist eine natürliche Person, die das Mittel tatsächlich angewandt hat.

#### `anwender`

`anwender`

- **Typ:** `array<object>` — **Pflicht**
- **Einschränkungen:** `minItems: 1`

Personen, die das Pflanzenschutzmittel angewandt haben. Mehrere Einträge beschreiben eine gemeinsam ausgeführte Anwendung, nicht mehrere getrennte Anwendungen.

> **Hinweis:** Bei Drohnen, Feldrobotern oder ferngesteuerten Geräten ist der Anwender die Person, die das Gerät bedient, programmiert, konfiguriert oder beaufsichtigt. Das Gerät selbst gehört nicht in dieses Feld; Modell oder Seriennummer gehören nach notizen.

#### `nachname`

`anwender[].nachname`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Mustermann"`

Nachname des Anwenders.

#### `vorname`

`anwender[].vorname`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Max"`

Vorname des Anwenders.

#### `zusatz`

`anwender[].zusatz`

- **Typ:** `string` — optional
- **Einschränkungen:** `maxLength: 50`
- **Beispiel:** `"Betriebsleiter"`

Zusatzangabe zur Person, typischerweise die Betriebsrolle: Betriebsleiter, Mitarbeiter, Lohnunternehmer.

> **Hinweis:** zusatz zählt zur Identität eines gespeicherten Anwender-Stammdatensatzes. Zwei Einträge mit gleichem Namen, aber unterschiedlichem zusatz, sind zwei Stammdatensätze, kein Duplikat.

### Pflanzenschutzmittel

`pflanzenschutzmittel` — 2 Felder

Genau ein Mittel pro Datensatz. Mehrere Mittel in einem Spritzgang ergeben mehrere Datensätze; siehe den Hinweis zur Tankmischung bei den Systemfeldern.

#### `handelsname`

`pflanzenschutzmittel.handelsname`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Abran"`

Produktname gemäß BVL-Zulassungsdatenbank. Das einzige Pflichtfeld des Mittels; ein Mittel ohne Zulassungsnummer bleibt gültig.

#### `zulassungsnummer`

`pflanzenschutzmittel.zulassungsnummer`

- **Typ:** `string` — optional
- **Beispiel:** `"00A657-63"`

Zulassungsnummer gemäß BVL-Zulassungsdatenbank.

> **Hinweis:** Zwei Fälle, in denen dieses Feld nicht das Naheliegende enthält. Bei einem Parallelimport steht die eigene Genehmigungsnummer des Imports darin (etwa 005314-00/013), nicht die Nummer des Referenzmittels. Bei einer Notfallzulassung nach Art. 53 bleibt das Feld leer, denn ein solches Mittel hat keine Zulassungsnummer.

### Aufwandmenge

`aufwandmenge` — 2 Felder

Zahlwert plus Einheitencode. Die Einheit ist eine geschlossene Liste, kein Freitext.

#### `einheit_wert`

`aufwandmenge.einheit_wert`

- **Typ:** `number` — **Pflicht**
- **Beispiel:** `0.8`

Zahlwert der Aufwandmenge. Die App erzwingt zusätzlich einen Wert größer null; das Schema selbst tut das nicht.

#### `einheit_kode`

`aufwandmenge.einheit_kode`

- **Typ:** `string (enum)` — **Pflicht**
- **Einschränkungen:** `enum: 284 values`
- **Zulässige Werte:** Geschlossene Liste mit 284 Werten, eine bewusst gekürzte Fassung der BVL-Kodeliste 25. Die vollständige Liste steht im herunterladbaren Schema unter properties.aufwandmenge.properties.einheit_kode.enum; die Excel-Arbeitsmappe der App führt sie auf einem eigenen Referenzblatt.
- **Beispiel:** `"l/ha"`

Einheit der Aufwandmenge gemäß BVL-PSM-Datenbank, etwa l/ha, kg/ha, ml/100 m² oder g pro Pflanze.

> **Hinweis:** Nicht jeder Code der BVL-Kodeliste 25 ist zulässig: 74 Codes sind bewusst ausgeschlossen. Ein Importwert außerhalb der Liste ist ungültig und der Datensatz wird abgelehnt.

### Anwendungszeitpunkt

`anwendung_zeitpunkt` — 2 Felder

Datum verpflichtend, Uhrzeit optional, außer das gewählte Mittel trägt eine Bienenschutzauflage.

#### `datum`

`anwendung_zeitpunkt.datum`

- **Typ:** `string (date)` — **Pflicht**
- **Einschränkungen:** `format: date`
- **Beispiel:** `"2026-05-27"`

Datum der Anwendung im Format JJJJ-MM-TT.

> **Hinweis:** Beim Import aus CSV oder der Excel-Arbeitsmappe wird die deutsche Schreibweise TT.MM.JJJJ erkannt und umgewandelt. Gespeichert wird immer die ISO-Form.

#### `uhrzeit`

`anwendung_zeitpunkt.uhrzeit`

- **Typ:** `string (time)` — optional
- **Einschränkungen:** `format: time`, `offset required (e.g. Z)`
- **Beispiel:** `"06:15:00Z"`

Uhrzeit der Anwendung mit Sekundenanteil und Zeitzonen-Offset.

> **Hinweis:** Zwei Fallstricke. Erstens der Offset: format time meint die RFC-3339-Form full-time, ein Offset ist also Pflicht. "06:15:00" fällt bei einem strengen Validator durch, "06:15:00Z" nicht — und ausgerechnet das examples-Feld des Schemas zeigt hier die Form ohne Offset. Die von der App erzeugten Datensätze tragen den Offset. Zweitens die Pflicht: im Schema ist das Feld optional, in der App bedingt verpflichtend — trägt das gewählte Mittel eine Bienenschutzauflage, verlangt das Formular eine Uhrzeit. Diese Regel steht nur im Anwendungscode; ein extern erzeugter Datensatz ohne Uhrzeit bleibt schemakonform.

### Kulturart

`kulturart` — 5 Felder

Name und EPPO-Code sind beide verpflichtend; das BBCH-Stadium ist optional und wird von der App nie selbst gesetzt.

#### `name`

`kulturart.name`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Winterweichweizen"`

Kulturname gemäß BVL-Zulassungsdatenbank. Die App synchronisiert die Kulturliste pro Sprache; der gespeicherte Name ist daher die Bezeichnung in der Sprache, in der erfasst wurde.

#### `eppo_code`

`kulturart.eppo_code`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"TRZAW"`

EPPO-Code der Kultur. Der sprachunabhängige Schlüssel; bei einem Abgleich über Sprachgrenzen hinweg ist das das Vergleichsfeld, nicht name.

> **Hinweis:** Im Formular ist der EPPO-Code die Schleuse zum Mittelbereich: solange kein gültiger Code gesetzt ist, bleibt der gesamte Abschnitt Pflanzenschutzmittel gesperrt.

#### `bbch`

`kulturart.bbch`

- **Typ:** `object` — optional

BBCH-Wachstumsstadium der Kultur laut Zulassung und BBCH-Monografie, abgebildet als Bereich von–bis.

> **Hinweis:** Die App schreibt BBCH nie selbst. Sie leitet aus den zugelassenen Indikationen die möglichen Fenster ab und bietet sie zur Auswahl an; der Wert stammt immer aus einer bewussten Eingabe.

#### `von`

`kulturart.bbch.von`

- **Typ:** `string` — optional
- **Beispiel:** `"55"`

Anfangs- bzw. aktuelles BBCH-Stadium, als Zahl oder in der offiziellen Langform.

> **Hinweis:** Die Eingabe im Formular ist auf drei Zeichen begrenzt; importierte Langformen werden bis 300 Zeichen akzeptiert. Beide Formen sind schemakonform.

#### `bis`

`kulturart.bbch.bis`

- **Typ:** `string` — optional
- **Beispiel:** `"59"`

End-BBCH-Stadium, wenn ein Bereich abgebildet wird. Bei einem einzelnen Stadium ist bis gleich von.

> **Hinweis:** Ein umgekehrter Bereich (von größer als bis) wird nur als Warnung angezeigt und blockiert das Speichern nicht. Die Prüfung ist rein numerisch und greift bei Langform-Eingaben nicht.

### Jahr

`jahr` — 1 Felder

Ein einzelnes Feld, dessen Bedeutung vom Anwendungsbereich abhängt.

#### `jahr`

`jahr`

- **Typ:** `string` — **Pflicht**
- **Einschränkungen:** `4 digits, 1990–2100 (enforced by the app)`
- **Beispiel:** `"2026"`

Bei landwirtschaftlichen Kulturen das Erntejahr, bei nicht-landwirtschaftlicher Anwendung (Forst, Nichtkulturland) das Anwendungsjahr. Ein String, keine Zahl.

> **Hinweis:** Fehlt das Jahr beim Import, leitet die App es aus dem Anwendungsdatum ab. Das ist reiner Fallback: ein vorhandener Wert wird nie überschrieben, auch wenn er vom Datum abweicht. Weicht er ab, zeigt das Formular eine nicht blockierende Warnung.

### Art der Verwendung

`art_der_verwendung` — 2 Felder

Ein Paar aus Bereich und Art, bei dem der Bereich bestimmt, welche Arten überhaupt zulässig sind.

#### `bereich`

`art_der_verwendung.bereich`

- **Typ:** `string (enum)` — **Pflicht**
- **Zulässige Werte:** `freiland`, `raum`, `beizung`
- **Beispiel:** `"freiland"`

Anwendungsbereich: Freiland, geschlossener Raum oder Beizung von Saatgut.

#### `art`

`art_der_verwendung.art`

- **Typ:** `string (conditional enum)` — optional
- **Zulässige Werte:** Die zulässigen Werte hängen von bereich ab: bei freiland kulturland, nicht_kulturland oder flaechen_allgemeinheit; bei raum lager, gewaechshaus oder innenraum; bei beizung beizung_saatgut oder beizung_pflanzgut.
- **Beispiel:** `"kulturland"`

Spezifische Art der Verwendung. Welche Werte zulässig sind, richtet sich nach bereich.

> **Hinweis:** Diese Zuordnung steht im Schema selbst, als if/then-Kette unter allOf — ein falsch gepaarter Wert wird also schon von einem generischen Validator abgelehnt, nicht erst von der App. Das Feld ist zugleich optional: fehlt art ganz, greift keine der Bedingungen und der Datensatz bleibt gültig.

### Behandeltes Objekt

`behandeltes_objekt` — 4 Felder

Was tatsächlich behandelt wurde, als Typ plus Größe. Nicht zu verwechseln mit der Größe des Standorts — das ist ein eigenes Feld unter behandlungsort.

#### `typ`

`behandeltes_objekt.typ`

- **Typ:** `string (enum)` — **Pflicht**
- **Zulässige Werte:** `behandelte_flaeche`, `behandelte_menge`, `behandeltes_volumen`
- **Beispiel:** `"behandelte_flaeche"`

Art des behandelten Objekts: behandelte Fläche, behandelte Menge oder behandeltes Volumen.

> **Hinweis:** Der Typ bestimmt per if/then im Schema, welche Einheitencodes in groesse_einheit zulässig sind: behandelte_flaeche erlaubt m² oder ha, behandelte_menge g, kg, dt oder t, behandeltes_volumen m³ oder l.

#### `einheit_wert`

`behandeltes_objekt.groesse_einheit.einheit_wert`

- **Typ:** `number` — **Pflicht**
- **Beispiel:** `4.25`

Zahlwert der Objektgröße.

> **Hinweis:** Dies ist die tatsächlich behandelte Ausdehnung — Fläche oder Volumen — nicht die Höhe oder das Wachstumsstadium einer Pflanze. Im Zierpflanzenbau wird das regelmäßig verwechselt, weil Zulassungsauflagen dort oft über die Pflanzengröße formuliert sind. Solche Auflagen gehören nach kulturart.bbch oder notizen.

#### `einheit_kode`

`behandeltes_objekt.groesse_einheit.einheit_kode`

- **Typ:** `string (conditional enum)` — **Pflicht**
- **Zulässige Werte:** Abhängig von typ: bei behandelte_flaeche m² oder ha, bei behandelte_menge g, kg, dt oder t, bei behandeltes_volumen m³ oder l.
- **Beispiel:** `"ha"`

Einheit der Objektgröße. Anders als aufwandmenge.einheit_kode stammt dieser Wert nicht aus der BVL-Kodeliste, sondern aus einer sehr kurzen, vom Typ abhängigen Liste.

#### `beschreibung`

`behandeltes_objekt.beschreibung`

- **Typ:** `string` — optional
- **Einschränkungen:** `maxLength: 50`
- **Beispiel:** `"Schlag Nordfeld"`

Freitextbeschreibung des behandelten Objekts.

> **Hinweis:** Wird beim anonymisierten Export entfernt, weil es einen Betrieb identifizieren kann.

### Behandlungsort

`behandlungsort[]` — 8 Felder

Array mit mindestens einem Eintrag. Mehrere Einträge beschreiben denselben Ort über verschiedene Referenzarten, nicht mehrere Orte.

#### `behandlungsort`

`behandlungsort`

- **Typ:** `array<object>` — **Pflicht**
- **Einschränkungen:** `minItems: 1`

Behandlungsorte der Anwendung. Mehrere Einträge ermöglichen es, denselben Ort über verschiedene Standortreferenzen zu beschreiben — etwa als Polygon und zusätzlich als InVeKoS-Referenz.

> **Hinweis:** Die App begrenzt die Zahl der Referenzen auf sieben, eine je Kennungsart. Wählt man im Geometrie-Picker ein Feld, schreibt die App zwei Einträge: das Polygon selbst und eine automatisch ergänzte zweite Referenz.

#### `standort_kennung_art`

`behandlungsort[].standort_kennung_art`

- **Typ:** `string (enum)` — **Pflicht**
- **Zulässige Werte:** `standort_koordinaten`, `flurstueckskennzeichen`, `invekos_id`, `flaechengeometrie`, `gleise`, `forst`, `wege`
- **Beispiel:** `"standort_koordinaten"`

Art der Standortreferenz. Der Diskriminator, der die Form von standort_kennung_wert festlegt.

> **Hinweis:** Im Schema als Kette von if/then-Bedingungen über allOf abgebildet, nicht als benannte Union. Wer eigene Validierung schreibt, muss diese Verzweigung nachbilden: der Wert allein ist ohne die Kennungsart nicht prüfbar.

#### `standort_kennung_wert`

`behandlungsort[].standort_kennung_wert`

- **Typ:** `oneOf<7 variants>` — **Pflicht**

Wert der Standortreferenz. Die Form richtet sich nach standort_kennung_art; die sieben Varianten sind unten einzeln beschrieben.

#### `standort_anbauart`

`behandlungsort[].standort_anbauart`

- **Typ:** `string (enum)` — optional
- **Zulässige Werte:** `konventionell`, `oekologisch`
- **Beispiel:** `"konventionell"`

Bewirtschaftungsart des Objekts, in dem die Anwendung erfolgt ist: konventionell oder ökologisch.

#### `standort_groesse_art`

`behandlungsort[].standort_groesse_art`

- **Typ:** `string (enum)` — optional
- **Zulässige Werte:** `flaeche`, `volumen`
- **Beispiel:** `"flaeche"`

Art der Standortgröße: Fläche oder Volumen.

> **Hinweis:** Dieses Feld schränkt im Schema per if/then die zulässigen Einheitencodes ein: bei flaeche nur m² oder ha, bei volumen nur m³ oder l. Ohne dieses Feld gilt die Einschränkung nicht.

#### `einheit_wert`

`behandlungsort[].standort_groesse_einheit.einheit_wert`

- **Typ:** `number` — **Pflicht**
- **Beispiel:** `4.25`

Zahlwert der Standortgröße — die Ausdehnung des gesamten Standorts, nicht der behandelten Teilfläche.

> **Hinweis:** Überschreitet die Größe des behandelten Objekts die Standortgröße, warnt das Formular (mit Einheitenumrechnung), blockiert das Speichern aber nicht.

#### `einheit_kode`

`behandlungsort[].standort_groesse_einheit.einheit_kode`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"ha"`

Einheit der Standortgröße. Bei gesetztem standort_groesse_art auf m²/ha bzw. m³/l eingeschränkt.

#### `bezeichnung`

`behandlungsort[].bezeichnung`

- **Typ:** `string` — optional
- **Einschränkungen:** `maxLength: 50`
- **Beispiel:** `"Nordfeld"`

Zusätzliche Angabe zum Behandlungsort, etwa der Name des Schlages oder die Gewächshaus-Abteilung.

> **Hinweis:** Zählt bewusst nicht zur Identität einer Standortreferenz: zwei Einträge, die sich nur in bezeichnung unterscheiden, gelten als derselbe Ort. Beim anonymisierten Export wird das Feld entfernt.

### Variante: Koordinaten

`standort_kennung_wert (standort_koordinaten)` — 2 Felder

Ein einzelner WGS84-Punkt. Achtung bei den Grenzen — sie sind bewusst nicht die üblichen ±90/±180.

#### `breitengrad`

`standort_kennung_wert.breitengrad`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: -100`, `maximum: 100`
- **Beispiel:** `52.52`

Geographische Breite (WGS84) in Dezimalgrad.

> **Hinweis:** Die Grenze ±100 ist keine Nachlässigkeit, sondern eine bewusste Produktentscheidung, und sie ist an zwei Stellen dupliziert: im Schema und in einer TypeScript-Konstante. Wer eine der beiden ändert, muss die andere mitziehen — JSON kann TypeScript nicht importieren.

#### `laengengrad`

`standort_kennung_wert.laengengrad`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: -50`, `maximum: 50`
- **Beispiel:** `13.405`

Geographische Länge (WGS84) in Dezimalgrad.

> **Hinweis:** Grenze ±50, ebenfalls bewusst enger als der WGS84-Bereich. Koordinaten außerhalb Europas werden dadurch abgelehnt.

### Variante: Flurstückskennzeichen

`standort_kennung_wert (flurstueckskennzeichen)` — 1 Felder

Die einzige Variante, deren Wert ein String und kein Objekt ist.

#### `standort_kennung_wert`

`standort_kennung_wert`

- **Typ:** `string` — **Pflicht**
- **Einschränkungen:** `pattern: ^[0-9_]{20}$`
- **Beispiel:** `"071411006000570099__"`

Amtliches ALKIS-Flurstückskennzeichen, exakt 20 Zeichen aus Ziffern und Unterstrichen. Unterstriche füllen nicht belegte Stellen auf.

> **Hinweis:** Führende Nullen sind bedeutungstragend. Beim Import aus Tabellen muss die Spalte als Text behandelt werden, sonst frisst die Zahleninterpretation die Nullen und der Wert verfehlt das Muster.

### Variante: InVeKoS-ID

`standort_kennung_wert (invekos_id)` — 3 Felder

Feldblock- und Schlagreferenz. Nur der FLIK ist verpflichtend.

#### `flik`

`standort_kennung_wert.flik`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"DETHLIAL50333H11"`

FLIK, der Feldblock-Identifikator gemäß InVeKoS.

#### `schlag_nummer`

`standort_kennung_wert.schlag_nummer`

- **Typ:** `string` — optional
- **Beispiel:** `"42"`

Schlagnummer des Betriebs innerhalb des Feldblocks. Identifiziert die konkrete, mit einer Kultur bestellte Teilfläche.

#### `teilschlag_nummer`

`standort_kennung_wert.teilschlag_nummer`

- **Typ:** `string` — optional
- **Beispiel:** `"1"`

Teilschlagnummer, falls der Schlag weiter unterteilt ist.

### Variante: Flächengeometrie

`standort_kennung_wert (flaechengeometrie)` — 2 Felder

GeoJSON-ähnliche Geometrie. Der Typ bestimmt, wie tief die Koordinaten verschachtelt sind.

#### `typ`

`standort_kennung_wert.typ`

- **Typ:** `string (enum)` — **Pflicht**
- **Zulässige Werte:** `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `GeometryCollection`
- **Beispiel:** `"Polygon"`

Geometrietyp, benannt wie in GeoJSON.

#### `koordinaten`

`standort_kennung_wert.koordinaten`

- **Typ:** `array` — **Pflicht**
- **Beispiel:** `[[[10.52,49.81],[10.53,49.81],[10.53,49.82],[10.52,49.81]]]`

Koordinaten als verschachtelte Arrays. Die Verschachtelungstiefe hängt vom Geometrietyp ab: ein Polygon führt Ringe, ein MultiPolygon Ringe von Ringen.

> **Hinweis:** Das Schema prüft die Tiefe nicht — es verlangt nur ein Array. Die Prüfung Typ gegen Verschachtelungstiefe liegt im Validierungscode der App. Beim Export bleiben die vollen Koordinaten in JSON, XML, CSV und Backup erhalten; nur die PDF-Zusammenfassung ersetzt sie durch Typ, Eckpunktzahl und Zentroid.

### Variante: Gleise

`standort_kennung_wert (gleise)` — 6 Felder

Streckenabschnitt einer Bahnstrecke. Alle sechs Felder sind verpflichtend.

#### `streckennummer`

`standort_kennung_wert.streckennummer`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"2981"`

VzG-Streckennummer der Bahnstrecke.

#### `richtungskennzahl`

`standort_kennung_wert.richtungskennzahl`

- **Typ:** `number (enum)` — **Pflicht**
- **Zulässige Werte:** `0`, `1`
- **Beispiel:** `0`

Richtungskennzahl der Strecke, 0 oder 1. Eine Zahl, kein String.

#### `km_von`

`standort_kennung_wert.km_von`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: 0`, `multipleOf: 0.1`
- **Beispiel:** `12`

Streckenkilometer des Abschnittsbeginns, in Schritten von 0,1.

> **Hinweis:** multipleOf: 0.1 verhält sich in Gleitkomma-Arithmetik nicht so, wie man erwartet. Übliche Validatoren prüfen, ob wert / 0.1 eine ganze Zahl ist — und 0.3 / 0.1 ergibt in IEEE-754 nicht 3, sondern 2,9999999999999996. Der Wert 0,3, den das Schema selbst als Beispiel führt, fällt damit durch. Betroffen sind unter anderem 0,3, 1,2 und 3,7; unproblematisch sind ganze Zahlen sowie 0,1, 0,2, 0,4, 0,5, 0,8 und 1,5. Wer krumme Kilometerwerte erfassen muss, sollte den eigenen Validator auf Toleranz konfigurieren.

#### `km_bis`

`standort_kennung_wert.km_bis`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: 0`, `multipleOf: 0.1`
- **Beispiel:** `14`

Streckenkilometer des Abschnittsendes, in Schritten von 0,1.

#### `m_von`

`standort_kennung_wert.m_von`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: 0`, `maximum: 99`
- **Beispiel:** `15`

Meterangabe innerhalb des Anfangskilometers, 0 bis 99.

#### `m_bis`

`standort_kennung_wert.m_bis`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: 0`, `maximum: 99`
- **Beispiel:** `21`

Meterangabe innerhalb des Endkilometers, 0 bis 99.

### Variante: Forst

`standort_kennung_wert (forst)` — 7 Felder

Forstliche Flächenadresse. Vier Felder verpflichtend, drei zur weiteren Verfeinerung.

#### `bundesland`

`standort_kennung_wert.bundesland`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"SN"`

Bundesland der forstlichen Fläche, als Bundesland-Kürzel.

#### `forstamt_betrieb`

`standort_kennung_wert.forstamt_betrieb`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"FOB Baerenfels bzw. 1509"`

Zuständiges Forstamt bzw. Forstbetrieb, als Name oder Nummer.

#### `revier`

`standort_kennung_wert.revier`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Tharandt"`

Forstrevier.

#### `abteilung`

`standort_kennung_wert.abteilung`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"503"`

Forstabteilung.

#### `unterabteilung`

`standort_kennung_wert.unterabteilung`

- **Typ:** `string` — optional
- **Beispiel:** `"a"`

Forstunterabteilung.

#### `teilflaeche`

`standort_kennung_wert.teilflaeche`

- **Typ:** `string` — optional
- **Beispiel:** `"4"`

Teilfläche innerhalb der Unterabteilung.

#### `behandlungseinheit`

`standort_kennung_wert.behandlungseinheit`

- **Typ:** `string` — optional
- **Beispiel:** `"BE 12"`

Bezeichnung der Behandlungseinheit.

### Variante: Wege

`standort_kennung_wert (wege)` — 14 Felder

Die tiefste Variante: eine Union in einer Union. Der Wegename verzweigt noch einmal in Koordinaten oder Streckenabschnitt.

#### `referenz_typ`

`standort_kennung_wert.referenz_typ`

- **Typ:** `string (enum)` — **Pflicht**
- **Zulässige Werte:** `strassen_wegebezeichnung`, `hausnummernbereich`
- **Beispiel:** `"strassen_wegebezeichnung"`

Art der Wegereferenz: über die Straßen-/Wegebezeichnung oder über einen Hausnummernbereich. Der Diskriminator für referenz_wert.

#### `bezeichnung_nummer`

`referenz_wert.bezeichnung_nummer`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"B22"`

Bezeichnung oder Nummer der Straße bzw. des Weges. Nur bei referenz_typ = strassen_wegebezeichnung.

#### `raeumliche_eingrenzung`

`referenz_wert.raeumliche_eingrenzung`

- **Typ:** `string (enum)` — optional
- **Zulässige Werte:** `koordinaten`, `streckenabschnitt`
- **Beispiel:** `"streckenabschnitt"`

Art der räumlichen Eingrenzung des Weges. Der zweite Diskriminator dieser Variante; er legt die Form von eingrenzung_wert fest.

#### `von.breitengrad`

`eingrenzung_wert.von.breitengrad`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: -100`, `maximum: 100`
- **Beispiel:** `49.812`

Breitengrad der Anfangskoordinate des Wegeabschnitts. Nur bei raeumliche_eingrenzung = koordinaten.

#### `von.laengengrad`

`eingrenzung_wert.von.laengengrad`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: -50`, `maximum: 50`
- **Beispiel:** `10.523`

Längengrad der Anfangskoordinate des Wegeabschnitts.

#### `bis.breitengrad`

`eingrenzung_wert.bis.breitengrad`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: -100`, `maximum: 100`
- **Beispiel:** `49.815`

Breitengrad der Endkoordinate des Wegeabschnitts.

#### `bis.laengengrad`

`eingrenzung_wert.bis.laengengrad`

- **Typ:** `number` — **Pflicht**
- **Einschränkungen:** `minimum: -50`, `maximum: 50`
- **Beispiel:** `10.531`

Längengrad der Endkoordinate des Wegeabschnitts.

#### `von (Streckenabschnitt)`

`eingrenzung_wert.von`

- **Typ:** `number` — **Pflicht**
- **Beispiel:** `0`

Anfangswert des Streckenabschnitts. Nur bei raeumliche_eingrenzung = streckenabschnitt; hier ist von eine Zahl, bei der Koordinatenvariante ein Objekt.

#### `bis (Streckenabschnitt)`

`eingrenzung_wert.bis`

- **Typ:** `number` — **Pflicht**
- **Beispiel:** `250`

Endwert des Streckenabschnitts.

#### `einheit`

`eingrenzung_wert.einheit`

- **Typ:** `string (enum)` — **Pflicht**
- **Zulässige Werte:** `m`, `km`
- **Beispiel:** `"m"`

Einheit des Streckenabschnitts, Meter oder Kilometer.

#### `von.ort / bis.ort`

`referenz_wert.von.ort`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Musterstadt"`

Ortsname der Anfangs- bzw. Endadresse. Nur bei referenz_typ = hausnummernbereich; die Adressen von und bis tragen dieselben vier Felder.

#### `von.postleitzahl / bis.postleitzahl`

`referenz_wert.von.postleitzahl`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"12049"`

Postleitzahl der Anfangs- bzw. Endadresse.

#### `von.strasse / bis.strasse`

`referenz_wert.von.strasse`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"Hauptstrasse"`

Straßenname der Anfangs- bzw. Endadresse.

#### `von.hausnummer / bis.hausnummer`

`referenz_wert.von.hausnummer`

- **Typ:** `string` — **Pflicht**
- **Beispiel:** `"15"`

Hausnummer der Anfangs- bzw. Endadresse. Ein String, damit Zusätze wie 15a möglich bleiben.

### Notizen

`notizen` — 1 Felder

Ein einzelnes Freitextfeld — und zugleich die Stelle, an der die App maschinenlesbare Marker ablegt.

#### `notizen`

`notizen`

- **Typ:** `string` — optional
- **Einschränkungen:** `maxLength: 500`
- **Beispiel:** `"Indikation: Blattlaeuse. Es wurde lediglich die Haelfte des Feldes behandelt."`

Freitext-Notizen zur Anwendung, maximal 500 Zeichen.

> **Hinweis:** Dieses Feld ist nicht nur Freitext. Eine Notfallzulassung nach Art. 53 hat im Schema kein eigenes Feld; die App markiert sie stattdessen mit sprachunabhängigen Codes in notizen (PPS_EA, PPS_NZ, ŚOR_ZN) und liest sie beim Bearbeiten und Importieren daraus zurück. Auch gewählte Indikation und Anwendungszeitpunkt werden hier angehängt. Wer notizen programmatisch überschreibt, löscht damit möglicherweise die einzige dauerhafte Spur einer Notfallzulassung. Beim anonymisierten Export wird das Feld vollständig entfernt.

---

## English

Field reference for the PSM-Anwendungsdatensatz. Generated from the same source as the reference page on the DiPAgE site.

### System fields

`(root)` — 3 fields

Identity, creation timestamp and format version. The app assigns all three itself; on import they are filled in when absent.

#### `datensatz_id`

`datensatz_id`

- **Type:** `string (uuid)` — **required**
- **Constraints:** `format: uuid`
- **Example:** `"019e7271-637f-7412-87be-4073c257db12"`

Globally unique record ID. The app generates UUIDv7 — timestamp-ordered, so sorting by ID matches creation order.

> **Note:** An import with a blank ID column gets a fresh UUID per row. Importing the same file twice therefore yields different IDs; duplicate detection falls back to the content fingerprint rather than the ID.

#### `datensatz_erstellung_zeitpunkt`

`datensatz_erstellung_zeitpunkt`

- **Type:** `string (date-time)` — **required**
- **Constraints:** `format: date-time`
- **Example:** `"2026-05-27T14:32:00Z"`

When the record was created, not when the application happened. The application time lives in anwendung_zeitpunkt.

> **Note:** Saving several records in one pass (tank mix, batch entry) stamps them with synthetic timestamps 10 ms apart from one shared base value. That shared base plus a shared application date is exactly how the app recognises a tank mix afterwards.

#### `datensatz_format_version`

`datensatz_format_version`

- **Type:** `string (const)` — **required**
- **Constraints:** `const: "1.0.0"`
- **Example:** `"1.0.0"`

Version of the record format. Frozen as a const in the schema: every valid record carries exactly "1.0.0".

> **Note:** Do not confuse this with the app’s IndexedDB version. Three independent numbers exist: this frozen format version, an informal schema counter in comments and the changelog, and the IndexedDB DB_VERSION.

### Operators

`anwender[]` — 4 fields

Array with at least one entry. Each entry is a natural person who actually applied the product.

#### `anwender`

`anwender`

- **Type:** `array<object>` — **required**
- **Constraints:** `minItems: 1`

The people who applied the plant protection product. Several entries describe one jointly executed application, not several separate ones.

> **Note:** For drones, field robots or remotely piloted equipment the operator is the person operating, programming, configuring or supervising the machine. The machine itself does not belong in this field; model or serial number belong in notizen.

#### `nachname`

`anwender[].nachname`

- **Type:** `string` — **required**
- **Example:** `"Mustermann"`

Operator’s surname.

#### `vorname`

`anwender[].vorname`

- **Type:** `string` — **required**
- **Example:** `"Max"`

Operator’s given name.

#### `zusatz`

`anwender[].zusatz`

- **Type:** `string` — optional
- **Constraints:** `maxLength: 50`
- **Example:** `"Betriebsleiter"`

Additional detail about the person, typically their role on the holding: farm manager, employee, contractor.

> **Note:** zusatz is part of a saved operator template’s identity. Two entries with the same name but a different zusatz are two templates, not one duplicate.

### Plant protection product

`pflanzenschutzmittel` — 2 fields

Exactly one product per record. Several products in one spray pass produce several records; see the tank-mix note under system fields.

#### `handelsname`

`pflanzenschutzmittel.handelsname`

- **Type:** `string` — **required**
- **Example:** `"Abran"`

Product name as held in the BVL authorization database. The only required product field; a product without an authorization number is still valid.

#### `zulassungsnummer`

`pflanzenschutzmittel.zulassungsnummer`

- **Type:** `string` — optional
- **Example:** `"00A657-63"`

Authorization number as held in the BVL authorization database.

> **Note:** Two cases where this field does not hold the obvious value. For a parallel import it carries the import’s own permit number (e.g. 005314-00/013), not the reference product’s number. For an Art. 53 emergency authorization it stays empty, because such a product has no authorization number at all.

### Application rate

`aufwandmenge` — 2 fields

A numeric value plus a unit code. The unit is a closed list, not free text.

#### `einheit_wert`

`aufwandmenge.einheit_wert`

- **Type:** `number` — **required**
- **Example:** `0.8`

Numeric value of the application rate. The app additionally enforces a value greater than zero; the schema itself does not.

#### `einheit_kode`

`aufwandmenge.einheit_kode`

- **Type:** `string (enum)` — **required**
- **Constraints:** `enum: 284 values`
- **Allowed values:** Closed list of 284 values, a deliberately trimmed subset of BVL Kodeliste 25. The full list is in the downloadable schema under properties.aufwandmenge.properties.einheit_kode.enum; the app’s Excel workbook carries it on a dedicated reference sheet.
- **Example:** `"l/ha"`

Unit of the application rate as used in the BVL PPP database, for example l/ha, kg/ha, ml/100 m² or g per plant.

> **Note:** Not every code in BVL Kodeliste 25 is accepted: 74 codes are deliberately excluded. An imported value outside the list is invalid and the record is rejected.

### Application time

`anwendung_zeitpunkt` — 2 fields

Date required, time optional, unless the chosen product carries a bee-hazard classification.

#### `datum`

`anwendung_zeitpunkt.datum`

- **Type:** `string (date)` — **required**
- **Constraints:** `format: date`
- **Example:** `"2026-05-27"`

Date of the application, in YYYY-MM-DD form.

> **Note:** CSV and Excel-workbook imports recognise the German DD.MM.YYYY form and convert it. What is stored is always the ISO form.

#### `uhrzeit`

`anwendung_zeitpunkt.uhrzeit`

- **Type:** `string (time)` — optional
- **Constraints:** `format: time`, `offset required (e.g. Z)`
- **Example:** `"06:15:00Z"`

Time of the application, including seconds and a timezone offset.

> **Note:** Two traps. First the offset: format time means the RFC 3339 full-time production, so an offset is mandatory. "06:15:00" fails a strict validator, "06:15:00Z" passes — and the schema’s own examples entry happens to show the offset-less form. Records the app produces do carry the offset. Second the requiredness: the schema marks the field optional, the app makes it conditionally required — if the chosen product carries a bee-hazard classification, the form demands a time. That rule lives only in application code; an externally produced record without a time still validates.

### Crop

`kulturart` — 5 fields

Name and EPPO code are both required; the BBCH stage is optional and never written by the app itself.

#### `name`

`kulturart.name`

- **Type:** `string` — **required**
- **Example:** `"Winterweichweizen"`

Crop name as held in the BVL authorization database. The app syncs the crop list per language, so the stored name is the label in whichever language the record was entered in.

#### `eppo_code`

`kulturart.eppo_code`

- **Type:** `string` — **required**
- **Example:** `"TRZAW"`

EPPO code of the crop. The language-independent key; when matching across languages this is the field to compare on, not name.

> **Note:** In the form the EPPO code is the gate to the product section: until a valid code is set, the entire plant protection product section stays locked.

#### `bbch`

`kulturart.bbch`

- **Type:** `object` — optional

BBCH growth stage of the crop per the authorization and the BBCH monograph, modelled as a von–bis range.

> **Note:** The app never writes BBCH on its own. It derives the authorized windows from the indications and offers them for selection; the value always comes from a deliberate entry.

#### `von`

`kulturart.bbch.von`

- **Type:** `string` — optional
- **Example:** `"55"`

Starting or current BBCH stage, as a number or in the official long form.

> **Note:** Form entry is capped at three characters; imported long forms are accepted up to 300 characters. Both forms validate.

#### `bis`

`kulturart.bbch.bis`

- **Type:** `string` — optional
- **Example:** `"59"`

Ending BBCH stage when a range is being recorded. For a single stage, bis equals von.

> **Note:** A reversed range (von greater than bis) surfaces as a warning only and never blocks saving. The check is numeric-only and does not fire on long-form entries.

### Year

`jahr` — 1 fields

A single field whose meaning depends on the area of use.

#### `jahr`

`jahr`

- **Type:** `string` — **required**
- **Constraints:** `4 digits, 1990–2100 (enforced by the app)`
- **Example:** `"2026"`

For agricultural crops the harvest year; for non-agricultural use (forestry, non-cultivated land) the year of application. A string, not a number.

> **Note:** When the year is missing on import the app derives it from the application date. That is a fallback only: an existing value is never overwritten, even when it disagrees with the date. Where they disagree, the form shows a non-blocking warning.

### Kind of use

`art_der_verwendung` — 2 fields

A pair of area and kind, where the area determines which kinds are permitted at all.

#### `bereich`

`art_der_verwendung.bereich`

- **Type:** `string (enum)` — **required**
- **Allowed values:** `freiland`, `raum`, `beizung`
- **Example:** `"freiland"`

Area of use: open field, enclosed space, or seed treatment.

#### `art`

`art_der_verwendung.art`

- **Type:** `string (conditional enum)` — optional
- **Allowed values:** Permitted values depend on bereich: under freiland kulturland, nicht_kulturland or flaechen_allgemeinheit; under raum lager, gewaechshaus or innenraum; under beizung beizung_saatgut or beizung_pflanzgut.
- **Example:** `"kulturland"`

Specific kind of use. Which values are permitted depends on bereich.

> **Note:** This mapping lives in the schema itself, as an if/then chain under allOf — so a mispaired value is rejected by a generic validator, not only by the app. The field is also optional: with art absent, none of the conditions bite and the record stays valid.

### Treated object

`behandeltes_objekt` — 4 fields

What was actually treated, as a type plus a size. Not to be confused with the size of the site, which is a separate field under behandlungsort.

#### `typ`

`behandeltes_objekt.typ`

- **Type:** `string (enum)` — **required**
- **Allowed values:** `behandelte_flaeche`, `behandelte_menge`, `behandeltes_volumen`
- **Example:** `"behandelte_flaeche"`

Kind of treated object: treated area, treated quantity, or treated volume.

> **Note:** Via if/then in the schema, the type determines which unit codes are permitted in groesse_einheit: behandelte_flaeche allows m² or ha, behandelte_menge g, kg, dt or t, behandeltes_volumen m³ or l.

#### `einheit_wert`

`behandeltes_objekt.groesse_einheit.einheit_wert`

- **Type:** `number` — **required**
- **Example:** `4.25`

Numeric value of the object size.

> **Note:** This is the extent actually treated — area or volume — not a plant’s height or growth stage. Ornamental horticulture confuses the two regularly, because authorization conditions there are often phrased in terms of plant size. Such conditions belong in kulturart.bbch or notizen.

#### `einheit_kode`

`behandeltes_objekt.groesse_einheit.einheit_kode`

- **Type:** `string (conditional enum)` — **required**
- **Allowed values:** Depends on typ: under behandelte_flaeche m² or ha, under behandelte_menge g, kg, dt or t, under behandeltes_volumen m³ or l.
- **Example:** `"ha"`

Unit of the object size. Unlike aufwandmenge.einheit_kode this value does not come from the BVL code list but from a very short, type-dependent list.

#### `beschreibung`

`behandeltes_objekt.beschreibung`

- **Type:** `string` — optional
- **Constraints:** `maxLength: 50`
- **Example:** `"Schlag Nordfeld"`

Free-text description of the treated object.

> **Note:** Removed by the anonymized export, because it can identify a holding.

### Treatment site

`behandlungsort[]` — 8 fields

Array with at least one entry. Several entries describe the same site through different reference kinds, not several sites.

#### `behandlungsort`

`behandlungsort`

- **Type:** `array<object>` — **required**
- **Constraints:** `minItems: 1`

Treatment sites of the application. Several entries let the same site be described through different location references — for instance as a polygon and additionally as an InVeKoS reference.

> **Note:** The app caps the number of references at seven, one per identification kind. Picking a field in the geometry picker writes two entries: the polygon itself and an automatically added second reference.

#### `standort_kennung_art`

`behandlungsort[].standort_kennung_art`

- **Type:** `string (enum)` — **required**
- **Allowed values:** `standort_koordinaten`, `flurstueckskennzeichen`, `invekos_id`, `flaechengeometrie`, `gleise`, `forst`, `wege`
- **Example:** `"standort_koordinaten"`

Kind of location reference. The discriminator that fixes the shape of standort_kennung_wert.

> **Note:** Expressed in the schema as a chain of if/then conditions under allOf, not as a named union. If you write your own validation you must reproduce that branching: the value alone cannot be checked without the kind.

#### `standort_kennung_wert`

`behandlungsort[].standort_kennung_wert`

- **Type:** `oneOf<7 variants>` — **required**

Value of the location reference. Its shape follows standort_kennung_art; the seven variants are documented individually below.

#### `standort_anbauart`

`behandlungsort[].standort_anbauart`

- **Type:** `string (enum)` — optional
- **Allowed values:** `konventionell`, `oekologisch`
- **Example:** `"konventionell"`

Management regime of the object where the application took place: conventional or organic.

#### `standort_groesse_art`

`behandlungsort[].standort_groesse_art`

- **Type:** `string (enum)` — optional
- **Allowed values:** `flaeche`, `volumen`
- **Example:** `"flaeche"`

Kind of site extent: area or volume.

> **Note:** This field narrows the permitted unit codes via if/then in the schema: with flaeche only m² or ha, with volumen only m³ or l. Without this field the narrowing does not apply.

#### `einheit_wert`

`behandlungsort[].standort_groesse_einheit.einheit_wert`

- **Type:** `number` — **required**
- **Example:** `4.25`

Numeric value of the site extent — the size of the whole site, not of the treated portion.

> **Note:** If the treated object size exceeds the site extent the form warns (converting units first) but does not block saving.

#### `einheit_kode`

`behandlungsort[].standort_groesse_einheit.einheit_kode`

- **Type:** `string` — **required**
- **Example:** `"ha"`

Unit of the site extent. Narrowed to m²/ha or m³/l when standort_groesse_art is set.

#### `bezeichnung`

`behandlungsort[].bezeichnung`

- **Type:** `string` — optional
- **Constraints:** `maxLength: 50`
- **Example:** `"Nordfeld"`

Additional detail about the treatment site, for example the field name or the greenhouse compartment.

> **Note:** Deliberately excluded from a location reference’s identity: two entries differing only in bezeichnung count as the same site. The anonymized export strips the field.

### Variant: coordinates

`standort_kennung_wert (standort_koordinaten)` — 2 fields

A single WGS84 point. Watch the bounds — they are deliberately not the usual ±90/±180.

#### `breitengrad`

`standort_kennung_wert.breitengrad`

- **Type:** `number` — **required**
- **Constraints:** `minimum: -100`, `maximum: 100`
- **Example:** `52.52`

Latitude (WGS84) in decimal degrees.

> **Note:** The ±100 bound is not sloppiness but a deliberate product decision, and it is duplicated in two places: the schema and a TypeScript constant. Changing one requires changing the other — JSON cannot import TypeScript.

#### `laengengrad`

`standort_kennung_wert.laengengrad`

- **Type:** `number` — **required**
- **Constraints:** `minimum: -50`, `maximum: 50`
- **Example:** `13.405`

Longitude (WGS84) in decimal degrees.

> **Note:** Bound ±50, again deliberately narrower than the WGS84 range. Coordinates outside Europe are rejected as a result.

### Variant: cadastral parcel

`standort_kennung_wert (flurstueckskennzeichen)` — 1 fields

The only variant whose value is a string rather than an object.

#### `standort_kennung_wert`

`standort_kennung_wert`

- **Type:** `string` — **required**
- **Constraints:** `pattern: ^[0-9_]{20}$`
- **Example:** `"071411006000570099__"`

Official ALKIS cadastral parcel identifier, exactly 20 characters of digits and underscores. Underscores pad unused positions.

> **Note:** Leading zeros are significant. Spreadsheet imports must treat the column as text, otherwise numeric interpretation eats the zeros and the value fails the pattern.

### Variant: InVeKoS ID

`standort_kennung_wert (invekos_id)` — 3 fields

Field-block and parcel reference. Only the FLIK is required.

#### `flik`

`standort_kennung_wert.flik`

- **Type:** `string` — **required**
- **Example:** `"DETHLIAL50333H11"`

FLIK, the field-block identifier under InVeKoS.

#### `schlag_nummer`

`standort_kennung_wert.schlag_nummer`

- **Type:** `string` — optional
- **Example:** `"42"`

The holding’s parcel number within the field block. Identifies the specific sub-area cropped with one culture.

#### `teilschlag_nummer`

`standort_kennung_wert.teilschlag_nummer`

- **Type:** `string` — optional
- **Example:** `"1"`

Sub-parcel number, when the parcel is subdivided further.

### Variant: field geometry

`standort_kennung_wert (flaechengeometrie)` — 2 fields

GeoJSON-like geometry. The type determines how deeply the coordinates are nested.

#### `typ`

`standort_kennung_wert.typ`

- **Type:** `string (enum)` — **required**
- **Allowed values:** `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `GeometryCollection`
- **Example:** `"Polygon"`

Geometry type, named as in GeoJSON.

#### `koordinaten`

`standort_kennung_wert.koordinaten`

- **Type:** `array` — **required**
- **Example:** `[[[10.52,49.81],[10.53,49.81],[10.53,49.82],[10.52,49.81]]]`

Coordinates as nested arrays. The nesting depth depends on the geometry type: a Polygon carries rings, a MultiPolygon rings of rings.

> **Note:** The schema does not check the depth — it only demands an array. The type-against-nesting-depth check lives in the app’s validation code. On export the full coordinates survive into JSON, XML, CSV and backups; only the PDF summary replaces them with type, vertex count and centroid.

### Variant: railway tracks

`standort_kennung_wert (gleise)` — 6 fields

A section of a railway line. All six fields are required.

#### `streckennummer`

`standort_kennung_wert.streckennummer`

- **Type:** `string` — **required**
- **Example:** `"2981"`

VzG line number of the railway line.

#### `richtungskennzahl`

`standort_kennung_wert.richtungskennzahl`

- **Type:** `number (enum)` — **required**
- **Allowed values:** `0`, `1`
- **Example:** `0`

Direction code of the line, 0 or 1. A number, not a string.

#### `km_von`

`standort_kennung_wert.km_von`

- **Type:** `number` — **required**
- **Constraints:** `minimum: 0`, `multipleOf: 0.1`
- **Example:** `12`

Line kilometre where the section starts, in steps of 0.1.

> **Note:** multipleOf: 0.1 does not behave the way you expect under floating-point arithmetic. Common validators check whether value / 0.1 is an integer — and 0.3 / 0.1 in IEEE 754 yields 2.9999999999999996, not 3. The value 0.3, which the schema itself carries as an example, therefore fails. Affected values include 0.3, 1.2 and 3.7; whole numbers plus 0.1, 0.2, 0.4, 0.5, 0.8 and 1.5 are fine. If you must record fractional kilometres, configure your validator with a tolerance.

#### `km_bis`

`standort_kennung_wert.km_bis`

- **Type:** `number` — **required**
- **Constraints:** `minimum: 0`, `multipleOf: 0.1`
- **Example:** `14`

Line kilometre where the section ends, in steps of 0.1.

#### `m_von`

`standort_kennung_wert.m_von`

- **Type:** `number` — **required**
- **Constraints:** `minimum: 0`, `maximum: 99`
- **Example:** `15`

Metre offset within the starting kilometre, 0 to 99.

#### `m_bis`

`standort_kennung_wert.m_bis`

- **Type:** `number` — **required**
- **Constraints:** `minimum: 0`, `maximum: 99`
- **Example:** `21`

Metre offset within the ending kilometre, 0 to 99.

### Variant: forestry

`standort_kennung_wert (forst)` — 7 fields

A forestry site address. Four required fields, three more for finer detail.

#### `bundesland`

`standort_kennung_wert.bundesland`

- **Type:** `string` — **required**
- **Example:** `"SN"`

Federal state of the forestry site, as the state abbreviation.

#### `forstamt_betrieb`

`standort_kennung_wert.forstamt_betrieb`

- **Type:** `string` — **required**
- **Example:** `"FOB Baerenfels bzw. 1509"`

Responsible forestry office or enterprise, as a name or a number.

#### `revier`

`standort_kennung_wert.revier`

- **Type:** `string` — **required**
- **Example:** `"Tharandt"`

Forest district.

#### `abteilung`

`standort_kennung_wert.abteilung`

- **Type:** `string` — **required**
- **Example:** `"503"`

Forest compartment.

#### `unterabteilung`

`standort_kennung_wert.unterabteilung`

- **Type:** `string` — optional
- **Example:** `"a"`

Forest sub-compartment.

#### `teilflaeche`

`standort_kennung_wert.teilflaeche`

- **Type:** `string` — optional
- **Example:** `"4"`

Sub-area within the sub-compartment.

#### `behandlungseinheit`

`standort_kennung_wert.behandlungseinheit`

- **Type:** `string` — optional
- **Example:** `"BE 12"`

Designation of the treatment unit.

### Variant: roads and paths

`standort_kennung_wert (wege)` — 14 fields

The deepest variant: a union inside a union. The road name branches once more into coordinates or a route section.

#### `referenz_typ`

`standort_kennung_wert.referenz_typ`

- **Type:** `string (enum)` — **required**
- **Allowed values:** `strassen_wegebezeichnung`, `hausnummernbereich`
- **Example:** `"strassen_wegebezeichnung"`

Kind of road reference: by road/path designation or by a house-number range. The discriminator for referenz_wert.

#### `bezeichnung_nummer`

`referenz_wert.bezeichnung_nummer`

- **Type:** `string` — **required**
- **Example:** `"B22"`

Designation or number of the road or path. Only for referenz_typ = strassen_wegebezeichnung.

#### `raeumliche_eingrenzung`

`referenz_wert.raeumliche_eingrenzung`

- **Type:** `string (enum)` — optional
- **Allowed values:** `koordinaten`, `streckenabschnitt`
- **Example:** `"streckenabschnitt"`

How the road is delimited in space. The second discriminator of this variant; it fixes the shape of eingrenzung_wert.

#### `von.breitengrad`

`eingrenzung_wert.von.breitengrad`

- **Type:** `number` — **required**
- **Constraints:** `minimum: -100`, `maximum: 100`
- **Example:** `49.812`

Latitude of the section’s start coordinate. Only for raeumliche_eingrenzung = koordinaten.

#### `von.laengengrad`

`eingrenzung_wert.von.laengengrad`

- **Type:** `number` — **required**
- **Constraints:** `minimum: -50`, `maximum: 50`
- **Example:** `10.523`

Longitude of the section’s start coordinate.

#### `bis.breitengrad`

`eingrenzung_wert.bis.breitengrad`

- **Type:** `number` — **required**
- **Constraints:** `minimum: -100`, `maximum: 100`
- **Example:** `49.815`

Latitude of the section’s end coordinate.

#### `bis.laengengrad`

`eingrenzung_wert.bis.laengengrad`

- **Type:** `number` — **required**
- **Constraints:** `minimum: -50`, `maximum: 50`
- **Example:** `10.531`

Longitude of the section’s end coordinate.

#### `von (Streckenabschnitt)`

`eingrenzung_wert.von`

- **Type:** `number` — **required**
- **Example:** `0`

Start value of the route section. Only for raeumliche_eingrenzung = streckenabschnitt; here von is a number, whereas in the coordinate variant it is an object.

#### `bis (Streckenabschnitt)`

`eingrenzung_wert.bis`

- **Type:** `number` — **required**
- **Example:** `250`

End value of the route section.

#### `einheit`

`eingrenzung_wert.einheit`

- **Type:** `string (enum)` — **required**
- **Allowed values:** `m`, `km`
- **Example:** `"m"`

Unit of the route section, metres or kilometres.

#### `von.ort / bis.ort`

`referenz_wert.von.ort`

- **Type:** `string` — **required**
- **Example:** `"Musterstadt"`

Town of the start or end address. Only for referenz_typ = hausnummernbereich; the von and bis addresses carry the same four fields.

#### `von.postleitzahl / bis.postleitzahl`

`referenz_wert.von.postleitzahl`

- **Type:** `string` — **required**
- **Example:** `"12049"`

Postal code of the start or end address.

#### `von.strasse / bis.strasse`

`referenz_wert.von.strasse`

- **Type:** `string` — **required**
- **Example:** `"Hauptstrasse"`

Street name of the start or end address.

#### `von.hausnummer / bis.hausnummer`

`referenz_wert.von.hausnummer`

- **Type:** `string` — **required**
- **Example:** `"15"`

House number of the start or end address. A string, so that suffixes such as 15a remain possible.

### Notes

`notizen` — 1 fields

A single free-text field — and also where the app parks machine-readable markers.

#### `notizen`

`notizen`

- **Type:** `string` — optional
- **Constraints:** `maxLength: 500`
- **Example:** `"Indikation: Blattlaeuse. Es wurde lediglich die Haelfte des Feldes behandelt."`

Free-text notes about the application, at most 500 characters.

> **Note:** This field is not only free text. An Art. 53 emergency authorization has no field of its own in the schema; the app marks it instead with language-independent codes inside notizen (PPS_EA, PPS_NZ, ŚOR_ZN) and reads them back on edit and on import. The selected indication and application timing are appended here too. Overwriting notizen programmatically may therefore erase the only durable trace of an emergency authorization. The anonymized export strips the field entirely.

---

## Polski

Dokumentacja pól PSM-Anwendungsdatensatz. Wygenerowana z tego samego źródła co strona dokumentacji w serwisie DiPAgE.

### Pola systemowe

`(root)` — 3 pola

Tożsamość, znacznik czasu utworzenia i wersja formatu. Aplikacja nadaje wszystkie trzy samodzielnie; przy imporcie są uzupełniane, gdy ich brakuje.

#### `datensatz_id`

`datensatz_id`

- **Typ:** `string (uuid)` — **wymagane**
- **Ograniczenia:** `format: uuid`
- **Przykład:** `"019e7271-637f-7412-87be-4073c257db12"`

Globalnie unikalny identyfikator rekordu. Aplikacja generuje UUIDv7 — uporządkowany czasowo, więc sortowanie po ID odpowiada kolejności utworzenia.

> **Uwaga:** Import z pustą kolumną ID otrzymuje nowy UUID dla każdego wiersza. Dwukrotny import tego samego pliku daje więc różne ID; wykrywanie duplikatów opiera się wtedy na odcisku treści zamiast na ID.

#### `datensatz_erstellung_zeitpunkt`

`datensatz_erstellung_zeitpunkt`

- **Typ:** `string (date-time)` — **wymagane**
- **Ograniczenia:** `format: date-time`
- **Przykład:** `"2026-05-27T14:32:00Z"`

Moment utworzenia rekordu, a nie moment zabiegu. Czas zabiegu znajduje się w anwendung_zeitpunkt.

> **Uwaga:** Zapis wielu rekordów w jednym przebiegu (mieszanina zbiornikowa, wprowadzanie wsadowe) nadaje im syntetyczne znaczniki czasu co 10 ms od wspólnej wartości bazowej. Ta wspólna baza plus wspólna data zabiegu to dokładnie sposób, w jaki aplikacja rozpoznaje później mieszaninę zbiornikową.

#### `datensatz_format_version`

`datensatz_format_version`

- **Typ:** `string (const)` — **wymagane**
- **Ograniczenia:** `const: "1.0.0"`
- **Przykład:** `"1.0.0"`

Wersja formatu rekordu. Zamrożona w schemacie jako const: każdy poprawny rekord zawiera dokładnie "1.0.0".

> **Uwaga:** Nie mylić z wersją IndexedDB aplikacji. Istnieją trzy niezależne liczby: ta zamrożona wersja formatu, nieformalny licznik schematu w komentarzach i changelogu oraz DB_VERSION IndexedDB.

### Wykonawcy zabiegu

`anwender[]` — 4 pola

Tablica z co najmniej jednym wpisem. Każdy wpis to osoba fizyczna, która faktycznie zastosowała środek.

#### `anwender`

`anwender`

- **Typ:** `array<object>` — **wymagane**
- **Ograniczenia:** `minItems: 1`

Osoby, które zastosowały środek ochrony roślin. Kilka wpisów opisuje jeden wspólnie wykonany zabieg, a nie kilka odrębnych.

> **Uwaga:** W przypadku dronów, robotów polowych lub sprzętu zdalnie sterowanego wykonawcą jest osoba obsługująca, programująca, konfigurująca lub nadzorująca maszynę. Sama maszyna nie należy do tego pola; model lub numer seryjny należą do notizen.

#### `nachname`

`anwender[].nachname`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Mustermann"`

Nazwisko wykonawcy.

#### `vorname`

`anwender[].vorname`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Max"`

Imię wykonawcy.

#### `zusatz`

`anwender[].zusatz`

- **Typ:** `string` — opcjonalne
- **Ograniczenia:** `maxLength: 50`
- **Przykład:** `"Betriebsleiter"`

Dodatkowa informacja o osobie, zwykle jej rola w gospodarstwie: kierownik, pracownik, usługodawca.

> **Uwaga:** zusatz stanowi część tożsamości zapisanego szablonu wykonawcy. Dwa wpisy o tym samym nazwisku, ale różnym zusatz, to dwa szablony, a nie duplikat.

### Środek ochrony roślin

`pflanzenschutzmittel` — 2 pola

Dokładnie jeden środek na rekord. Kilka środków w jednym zabiegu daje kilka rekordów; zobacz uwagę o mieszaninie zbiornikowej w polach systemowych.

#### `handelsname`

`pflanzenschutzmittel.handelsname`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Abran"`

Nazwa produktu zgodna z bazą zezwoleń BVL. Jedyne pole wymagane dla środka; środek bez numeru zezwolenia pozostaje poprawny.

#### `zulassungsnummer`

`pflanzenschutzmittel.zulassungsnummer`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"00A657-63"`

Numer zezwolenia zgodny z bazą zezwoleń BVL.

> **Uwaga:** Dwa przypadki, w których to pole nie zawiera oczywistej wartości. Przy imporcie równoległym zawiera własny numer pozwolenia importu (np. 005314-00/013), a nie numer produktu referencyjnego. Przy zezwoleniu awaryjnym z art. 53 pozostaje puste, ponieważ taki środek nie ma numeru zezwolenia.

### Dawka

`aufwandmenge` — 2 pola

Wartość liczbowa plus kod jednostki. Jednostka jest listą zamkniętą, nie tekstem dowolnym.

#### `einheit_wert`

`aufwandmenge.einheit_wert`

- **Typ:** `number` — **wymagane**
- **Przykład:** `0.8`

Wartość liczbowa dawki. Aplikacja dodatkowo wymusza wartość większą od zera; sam schemat tego nie robi.

#### `einheit_kode`

`aufwandmenge.einheit_kode`

- **Typ:** `string (enum)` — **wymagane**
- **Ograniczenia:** `enum: 284 values`
- **Dopuszczalne wartości:** Lista zamknięta 284 wartości, celowo skrócony podzbiór BVL Kodeliste 25. Pełna lista znajduje się w schemacie do pobrania pod properties.aufwandmenge.properties.einheit_kode.enum; skoroszyt Excel aplikacji zawiera ją na osobnym arkuszu referencyjnym.
- **Przykład:** `"l/ha"`

Jednostka dawki zgodna z bazą ŚOR BVL, na przykład l/ha, kg/ha, ml/100 m² lub g na roślinę.

> **Uwaga:** Nie każdy kod z BVL Kodeliste 25 jest dopuszczony: 74 kody są celowo wykluczone. Wartość importowana spoza listy jest nieprawidłowa i rekord zostaje odrzucony.

### Czas zabiegu

`anwendung_zeitpunkt` — 2 pola

Data wymagana, godzina opcjonalna, chyba że wybrany środek ma klasyfikację zagrożenia dla pszczół.

#### `datum`

`anwendung_zeitpunkt.datum`

- **Typ:** `string (date)` — **wymagane**
- **Ograniczenia:** `format: date`
- **Przykład:** `"2026-05-27"`

Data zabiegu w formacie RRRR-MM-DD.

> **Uwaga:** Import z CSV i skoroszytu Excel rozpoznaje niemiecki zapis DD.MM.RRRR i go konwertuje. Zapisywana jest zawsze forma ISO.

#### `uhrzeit`

`anwendung_zeitpunkt.uhrzeit`

- **Typ:** `string (time)` — opcjonalne
- **Ograniczenia:** `format: time`, `offset required (e.g. Z)`
- **Przykład:** `"06:15:00Z"`

Godzina zabiegu wraz z sekundami i przesunięciem strefy czasowej.

> **Uwaga:** Dwie pułapki. Po pierwsze przesunięcie: format time oznacza postać full-time według RFC 3339, więc przesunięcie jest obowiązkowe. "06:15:00" nie przechodzi rygorystycznego walidatora, "06:15:00Z" przechodzi — a wpis examples w samym schemacie pokazuje akurat postać bez przesunięcia. Rekordy tworzone przez aplikację zawierają przesunięcie. Po drugie wymagalność: schemat oznacza pole jako opcjonalne, aplikacja czyni je warunkowo wymaganym — jeśli wybrany środek ma klasyfikację zagrożenia dla pszczół, formularz wymaga godziny. Ta reguła istnieje tylko w kodzie aplikacji; rekord utworzony zewnętrznie bez godziny nadal przechodzi walidację.

### Uprawa

`kulturart` — 5 pola

Nazwa i kod EPPO są wymagane; faza BBCH jest opcjonalna i nigdy nie jest zapisywana przez samą aplikację.

#### `name`

`kulturart.name`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Winterweichweizen"`

Nazwa uprawy zgodna z bazą zezwoleń BVL. Aplikacja synchronizuje listę upraw dla każdego języka, więc zapisana nazwa jest etykietą w języku, w którym wprowadzono rekord.

#### `eppo_code`

`kulturart.eppo_code`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"TRZAW"`

Kod EPPO uprawy. Klucz niezależny od języka; przy dopasowywaniu między językami to jest pole do porównania, a nie name.

> **Uwaga:** W formularzu kod EPPO jest bramą do sekcji środka: dopóki nie ustawiono poprawnego kodu, cała sekcja środka ochrony roślin pozostaje zablokowana.

#### `bbch`

`kulturart.bbch`

- **Typ:** `object` — opcjonalne

Faza wzrostu BBCH uprawy według zezwolenia i monografii BBCH, modelowana jako zakres von–bis.

> **Uwaga:** Aplikacja nigdy nie zapisuje BBCH samodzielnie. Wyprowadza dopuszczone okna ze wskazań i oferuje je do wyboru; wartość zawsze pochodzi ze świadomego wprowadzenia.

#### `von`

`kulturart.bbch.von`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"55"`

Początkowa lub bieżąca faza BBCH, jako liczba lub w oficjalnej formie opisowej.

> **Uwaga:** Wprowadzanie w formularzu jest ograniczone do trzech znaków; importowane formy opisowe są akceptowane do 300 znaków. Obie formy przechodzą walidację.

#### `bis`

`kulturart.bbch.bis`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"59"`

Końcowa faza BBCH, gdy zapisywany jest zakres. Dla pojedynczej fazy bis równa się von.

> **Uwaga:** Odwrócony zakres (von większe niż bis) pojawia się tylko jako ostrzeżenie i nigdy nie blokuje zapisu. Sprawdzenie jest wyłącznie numeryczne i nie działa dla wpisów opisowych.

### Rok

`jahr` — 1 pola

Pojedyncze pole, którego znaczenie zależy od obszaru zastosowania.

#### `jahr`

`jahr`

- **Typ:** `string` — **wymagane**
- **Ograniczenia:** `4 digits, 1990–2100 (enforced by the app)`
- **Przykład:** `"2026"`

Dla upraw rolniczych rok zbioru; dla zastosowań nierolniczych (leśnictwo, grunty nieuprawne) rok zabiegu. Ciąg znaków, nie liczba.

> **Uwaga:** Gdy przy imporcie brakuje roku, aplikacja wyprowadza go z daty zabiegu. To wyłącznie wartość zastępcza: istniejąca wartość nigdy nie jest nadpisywana, nawet gdy nie zgadza się z datą. W razie rozbieżności formularz pokazuje nieblokujące ostrzeżenie.

### Rodzaj zastosowania

`art_der_verwendung` — 2 pola

Para obszaru i rodzaju, w której obszar określa, jakie rodzaje są w ogóle dopuszczalne.

#### `bereich`

`art_der_verwendung.bereich`

- **Typ:** `string (enum)` — **wymagane**
- **Dopuszczalne wartości:** `freiland`, `raum`, `beizung`
- **Przykład:** `"freiland"`

Obszar zastosowania: pole otwarte, przestrzeń zamknięta lub zaprawianie nasion.

#### `art`

`art_der_verwendung.art`

- **Typ:** `string (conditional enum)` — opcjonalne
- **Dopuszczalne wartości:** Dopuszczalne wartości zależą od bereich: dla freiland kulturland, nicht_kulturland lub flaechen_allgemeinheit; dla raum lager, gewaechshaus lub innenraum; dla beizung beizung_saatgut lub beizung_pflanzgut.
- **Przykład:** `"kulturland"`

Konkretny rodzaj zastosowania. Dopuszczalne wartości zależą od bereich.

> **Uwaga:** To odwzorowanie znajduje się w samym schemacie, jako łańcuch if/then w allOf — źle sparowana wartość jest więc odrzucana przez generyczny walidator, a nie dopiero przez aplikację. Pole jest zarazem opcjonalne: przy braku art żaden z warunków nie zadziała i rekord pozostaje poprawny.

### Obiekt poddany zabiegowi

`behandeltes_objekt` — 4 pola

Co faktycznie poddano zabiegowi, jako typ plus rozmiar. Nie mylić z wielkością lokalizacji, która jest osobnym polem w behandlungsort.

#### `typ`

`behandeltes_objekt.typ`

- **Typ:** `string (enum)` — **wymagane**
- **Dopuszczalne wartości:** `behandelte_flaeche`, `behandelte_menge`, `behandeltes_volumen`
- **Przykład:** `"behandelte_flaeche"`

Rodzaj obiektu poddanego zabiegowi: powierzchnia, ilość lub objętość.

> **Uwaga:** Przez if/then w schemacie typ określa, które kody jednostek są dopuszczalne w groesse_einheit: behandelte_flaeche dopuszcza m² lub ha, behandelte_menge g, kg, dt lub t, behandeltes_volumen m³ lub l.

#### `einheit_wert`

`behandeltes_objekt.groesse_einheit.einheit_wert`

- **Typ:** `number` — **wymagane**
- **Przykład:** `4.25`

Wartość liczbowa wielkości obiektu.

> **Uwaga:** To jest faktycznie poddany zabiegowi wymiar — powierzchnia lub objętość — a nie wysokość ani faza wzrostu rośliny. W roślinach ozdobnych te dwie rzeczy są regularnie mylone, ponieważ warunki zezwoleń są tam często formułowane w kategoriach wielkości rośliny. Takie warunki należą do kulturart.bbch lub notizen.

#### `einheit_kode`

`behandeltes_objekt.groesse_einheit.einheit_kode`

- **Typ:** `string (conditional enum)` — **wymagane**
- **Dopuszczalne wartości:** Zależnie od typ: dla behandelte_flaeche m² lub ha, dla behandelte_menge g, kg, dt lub t, dla behandeltes_volumen m³ lub l.
- **Przykład:** `"ha"`

Jednostka wielkości obiektu. W przeciwieństwie do aufwandmenge.einheit_kode ta wartość nie pochodzi z listy kodów BVL, lecz z bardzo krótkiej listy zależnej od typu.

#### `beschreibung`

`behandeltes_objekt.beschreibung`

- **Typ:** `string` — opcjonalne
- **Ograniczenia:** `maxLength: 50`
- **Przykład:** `"Schlag Nordfeld"`

Opis tekstowy obiektu poddanego zabiegowi.

> **Uwaga:** Usuwane przy eksporcie anonimizowanym, ponieważ może identyfikować gospodarstwo.

### Miejsce zabiegu

`behandlungsort[]` — 8 pola

Tablica z co najmniej jednym wpisem. Kilka wpisów opisuje to samo miejsce różnymi rodzajami odniesień, a nie kilka miejsc.

#### `behandlungsort`

`behandlungsort`

- **Typ:** `array<object>` — **wymagane**
- **Ograniczenia:** `minItems: 1`

Miejsca zabiegu. Kilka wpisów pozwala opisać to samo miejsce różnymi odniesieniami lokalizacyjnymi — na przykład jako wielokąt oraz dodatkowo jako odniesienie InVeKoS.

> **Uwaga:** Aplikacja ogranicza liczbę odniesień do siedmiu, po jednym na rodzaj identyfikacji. Wybór pola w selektorze geometrii zapisuje dwa wpisy: sam wielokąt oraz automatycznie dodane drugie odniesienie.

#### `standort_kennung_art`

`behandlungsort[].standort_kennung_art`

- **Typ:** `string (enum)` — **wymagane**
- **Dopuszczalne wartości:** `standort_koordinaten`, `flurstueckskennzeichen`, `invekos_id`, `flaechengeometrie`, `gleise`, `forst`, `wege`
- **Przykład:** `"standort_koordinaten"`

Rodzaj odniesienia lokalizacyjnego. Dyskryminator ustalający kształt standort_kennung_wert.

> **Uwaga:** W schemacie wyrażone jako łańcuch warunków if/then w allOf, a nie jako nazwana unia. Pisząc własną walidację, trzeba odtworzyć to rozgałęzienie: samej wartości nie da się sprawdzić bez rodzaju.

#### `standort_kennung_wert`

`behandlungsort[].standort_kennung_wert`

- **Typ:** `oneOf<7 variants>` — **wymagane**

Wartość odniesienia lokalizacyjnego. Jej kształt wynika z standort_kennung_art; siedem wariantów opisano poniżej osobno.

#### `standort_anbauart`

`behandlungsort[].standort_anbauart`

- **Typ:** `string (enum)` — opcjonalne
- **Dopuszczalne wartości:** `konventionell`, `oekologisch`
- **Przykład:** `"konventionell"`

Sposób gospodarowania obiektu, w którym wykonano zabieg: konwencjonalny lub ekologiczny.

#### `standort_groesse_art`

`behandlungsort[].standort_groesse_art`

- **Typ:** `string (enum)` — opcjonalne
- **Dopuszczalne wartości:** `flaeche`, `volumen`
- **Przykład:** `"flaeche"`

Rodzaj wielkości lokalizacji: powierzchnia lub objętość.

> **Uwaga:** To pole zawęża dopuszczalne kody jednostek przez if/then w schemacie: dla flaeche tylko m² lub ha, dla volumen tylko m³ lub l. Bez tego pola zawężenie nie obowiązuje.

#### `einheit_wert`

`behandlungsort[].standort_groesse_einheit.einheit_wert`

- **Typ:** `number` — **wymagane**
- **Przykład:** `4.25`

Wartość liczbowa wielkości lokalizacji — rozmiar całej lokalizacji, a nie części poddanej zabiegowi.

> **Uwaga:** Jeśli wielkość obiektu poddanego zabiegowi przekracza wielkość lokalizacji, formularz ostrzega (po przeliczeniu jednostek), ale nie blokuje zapisu.

#### `einheit_kode`

`behandlungsort[].standort_groesse_einheit.einheit_kode`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"ha"`

Jednostka wielkości lokalizacji. Zawężona do m²/ha lub m³/l, gdy ustawiono standort_groesse_art.

#### `bezeichnung`

`behandlungsort[].bezeichnung`

- **Typ:** `string` — opcjonalne
- **Ograniczenia:** `maxLength: 50`
- **Przykład:** `"Nordfeld"`

Dodatkowa informacja o miejscu zabiegu, na przykład nazwa działki lub komora szklarni.

> **Uwaga:** Celowo wyłączone z tożsamości odniesienia lokalizacyjnego: dwa wpisy różniące się tylko w bezeichnung liczą się jako to samo miejsce. Eksport anonimizowany usuwa to pole.

### Wariant: współrzędne

`standort_kennung_wert (standort_koordinaten)` — 2 pola

Pojedynczy punkt WGS84. Uwaga na granice — celowo nie są to zwykłe ±90/±180.

#### `breitengrad`

`standort_kennung_wert.breitengrad`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: -100`, `maximum: 100`
- **Przykład:** `52.52`

Szerokość geograficzna (WGS84) w stopniach dziesiętnych.

> **Uwaga:** Granica ±100 nie jest niedopatrzeniem, lecz świadomą decyzją produktową, i jest zduplikowana w dwóch miejscach: w schemacie i w stałej TypeScript. Zmiana jednej wymaga zmiany drugiej — JSON nie może importować TypeScript.

#### `laengengrad`

`standort_kennung_wert.laengengrad`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: -50`, `maximum: 50`
- **Przykład:** `13.405`

Długość geograficzna (WGS84) w stopniach dziesiętnych.

> **Uwaga:** Granica ±50, również celowo węższa niż zakres WGS84. Współrzędne spoza Europy są w efekcie odrzucane.

### Wariant: identyfikator działki

`standort_kennung_wert (flurstueckskennzeichen)` — 1 pola

Jedyny wariant, którego wartość jest ciągiem znaków, a nie obiektem.

#### `standort_kennung_wert`

`standort_kennung_wert`

- **Typ:** `string` — **wymagane**
- **Ograniczenia:** `pattern: ^[0-9_]{20}$`
- **Przykład:** `"071411006000570099__"`

Oficjalny identyfikator działki ALKIS, dokładnie 20 znaków z cyfr i podkreśleń. Podkreślenia wypełniają niewykorzystane pozycje.

> **Uwaga:** Wiodące zera mają znaczenie. Import z arkuszy musi traktować kolumnę jako tekst, w przeciwnym razie interpretacja liczbowa usunie zera i wartość nie pasuje do wzorca.

### Wariant: identyfikator InVeKoS

`standort_kennung_wert (invekos_id)` — 3 pola

Odniesienie do bloku pola i działki. Wymagany jest tylko FLIK.

#### `flik`

`standort_kennung_wert.flik`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"DETHLIAL50333H11"`

FLIK, identyfikator bloku pola według InVeKoS.

#### `schlag_nummer`

`standort_kennung_wert.schlag_nummer`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"42"`

Numer działki gospodarstwa w obrębie bloku pola. Identyfikuje konkretną podpowierzchnię obsianą jedną uprawą.

#### `teilschlag_nummer`

`standort_kennung_wert.teilschlag_nummer`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"1"`

Numer podrzędnej części działki, gdy działka jest dalej podzielona.

### Wariant: geometria powierzchni

`standort_kennung_wert (flaechengeometrie)` — 2 pola

Geometria w stylu GeoJSON. Typ określa, jak głęboko zagnieżdżone są współrzędne.

#### `typ`

`standort_kennung_wert.typ`

- **Typ:** `string (enum)` — **wymagane**
- **Dopuszczalne wartości:** `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `GeometryCollection`
- **Przykład:** `"Polygon"`

Typ geometrii, nazwany jak w GeoJSON.

#### `koordinaten`

`standort_kennung_wert.koordinaten`

- **Typ:** `array` — **wymagane**
- **Przykład:** `[[[10.52,49.81],[10.53,49.81],[10.53,49.82],[10.52,49.81]]]`

Współrzędne jako zagnieżdżone tablice. Głębokość zagnieżdżenia zależy od typu geometrii: Polygon zawiera pierścienie, MultiPolygon pierścienie pierścieni.

> **Uwaga:** Schemat nie sprawdza głębokości — wymaga jedynie tablicy. Sprawdzenie typu względem głębokości zagnieżdżenia znajduje się w kodzie walidacji aplikacji. Przy eksporcie pełne współrzędne zachowują się w JSON, XML, CSV i kopiach zapasowych; tylko podsumowanie PDF zastępuje je typem, liczbą wierzchołków i centroidem.

### Wariant: tory kolejowe

`standort_kennung_wert (gleise)` — 6 pola

Odcinek linii kolejowej. Wszystkie sześć pól jest wymaganych.

#### `streckennummer`

`standort_kennung_wert.streckennummer`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"2981"`

Numer linii VzG linii kolejowej.

#### `richtungskennzahl`

`standort_kennung_wert.richtungskennzahl`

- **Typ:** `number (enum)` — **wymagane**
- **Dopuszczalne wartości:** `0`, `1`
- **Przykład:** `0`

Kod kierunku linii, 0 lub 1. Liczba, nie ciąg znaków.

#### `km_von`

`standort_kennung_wert.km_von`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: 0`, `multipleOf: 0.1`
- **Przykład:** `12`

Kilometr linii, w którym zaczyna się odcinek, w krokach 0,1.

> **Uwaga:** multipleOf: 0.1 nie zachowuje się zgodnie z oczekiwaniami w arytmetyce zmiennoprzecinkowej. Typowe walidatory sprawdzają, czy wartość / 0.1 jest liczbą całkowitą — a 0,3 / 0,1 w IEEE 754 daje 2,9999999999999996, a nie 3. Wartość 0,3, którą sam schemat podaje jako przykład, nie przechodzi więc walidacji. Dotyczy to m.in. 0,3, 1,2 i 3,7; liczby całkowite oraz 0,1, 0,2, 0,4, 0,5, 0,8 i 1,5 są bezpieczne. Jeśli musisz zapisywać ułamkowe kilometry, skonfiguruj własny walidator z tolerancją.

#### `km_bis`

`standort_kennung_wert.km_bis`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: 0`, `multipleOf: 0.1`
- **Przykład:** `14`

Kilometr linii, na którym kończy się odcinek, w krokach 0,1.

#### `m_von`

`standort_kennung_wert.m_von`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: 0`, `maximum: 99`
- **Przykład:** `15`

Przesunięcie metrowe w obrębie kilometra początkowego, 0 do 99.

#### `m_bis`

`standort_kennung_wert.m_bis`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: 0`, `maximum: 99`
- **Przykład:** `21`

Przesunięcie metrowe w obrębie kilometra końcowego, 0 do 99.

### Wariant: leśnictwo

`standort_kennung_wert (forst)` — 7 pola

Adres powierzchni leśnej. Cztery pola wymagane, trzy kolejne dla większej szczegółowości.

#### `bundesland`

`standort_kennung_wert.bundesland`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"SN"`

Kraj związkowy powierzchni leśnej, jako skrót kraju.

#### `forstamt_betrieb`

`standort_kennung_wert.forstamt_betrieb`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"FOB Baerenfels bzw. 1509"`

Właściwe nadleśnictwo lub przedsiębiorstwo leśne, jako nazwa lub numer.

#### `revier`

`standort_kennung_wert.revier`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Tharandt"`

Leśnictwo.

#### `abteilung`

`standort_kennung_wert.abteilung`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"503"`

Oddział leśny.

#### `unterabteilung`

`standort_kennung_wert.unterabteilung`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"a"`

Pododdział leśny.

#### `teilflaeche`

`standort_kennung_wert.teilflaeche`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"4"`

Podpowierzchnia w obrębie pododdziału.

#### `behandlungseinheit`

`standort_kennung_wert.behandlungseinheit`

- **Typ:** `string` — opcjonalne
- **Przykład:** `"BE 12"`

Oznaczenie jednostki zabiegowej.

### Wariant: drogi i ścieżki

`standort_kennung_wert (wege)` — 14 pola

Najgłębszy wariant: unia w unii. Nazwa drogi rozgałęzia się jeszcze raz na współrzędne lub odcinek trasy.

#### `referenz_typ`

`standort_kennung_wert.referenz_typ`

- **Typ:** `string (enum)` — **wymagane**
- **Dopuszczalne wartości:** `strassen_wegebezeichnung`, `hausnummernbereich`
- **Przykład:** `"strassen_wegebezeichnung"`

Rodzaj odniesienia drogowego: przez oznaczenie drogi lub przez zakres numerów domów. Dyskryminator dla referenz_wert.

#### `bezeichnung_nummer`

`referenz_wert.bezeichnung_nummer`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"B22"`

Oznaczenie lub numer drogi. Tylko dla referenz_typ = strassen_wegebezeichnung.

#### `raeumliche_eingrenzung`

`referenz_wert.raeumliche_eingrenzung`

- **Typ:** `string (enum)` — opcjonalne
- **Dopuszczalne wartości:** `koordinaten`, `streckenabschnitt`
- **Przykład:** `"streckenabschnitt"`

Sposób przestrzennego ograniczenia drogi. Drugi dyskryminator tego wariantu; ustala kształt eingrenzung_wert.

#### `von.breitengrad`

`eingrenzung_wert.von.breitengrad`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: -100`, `maximum: 100`
- **Przykład:** `49.812`

Szerokość geograficzna współrzędnej początkowej odcinka. Tylko dla raeumliche_eingrenzung = koordinaten.

#### `von.laengengrad`

`eingrenzung_wert.von.laengengrad`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: -50`, `maximum: 50`
- **Przykład:** `10.523`

Długość geograficzna współrzędnej początkowej odcinka.

#### `bis.breitengrad`

`eingrenzung_wert.bis.breitengrad`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: -100`, `maximum: 100`
- **Przykład:** `49.815`

Szerokość geograficzna współrzędnej końcowej odcinka.

#### `bis.laengengrad`

`eingrenzung_wert.bis.laengengrad`

- **Typ:** `number` — **wymagane**
- **Ograniczenia:** `minimum: -50`, `maximum: 50`
- **Przykład:** `10.531`

Długość geograficzna współrzędnej końcowej odcinka.

#### `von (Streckenabschnitt)`

`eingrenzung_wert.von`

- **Typ:** `number` — **wymagane**
- **Przykład:** `0`

Wartość początkowa odcinka trasy. Tylko dla raeumliche_eingrenzung = streckenabschnitt; tutaj von jest liczbą, podczas gdy w wariancie współrzędnych jest obiektem.

#### `bis (Streckenabschnitt)`

`eingrenzung_wert.bis`

- **Typ:** `number` — **wymagane**
- **Przykład:** `250`

Wartość końcowa odcinka trasy.

#### `einheit`

`eingrenzung_wert.einheit`

- **Typ:** `string (enum)` — **wymagane**
- **Dopuszczalne wartości:** `m`, `km`
- **Przykład:** `"m"`

Jednostka odcinka trasy, metry lub kilometry.

#### `von.ort / bis.ort`

`referenz_wert.von.ort`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Musterstadt"`

Miejscowość adresu początkowego lub końcowego. Tylko dla referenz_typ = hausnummernbereich; adresy von i bis mają te same cztery pola.

#### `von.postleitzahl / bis.postleitzahl`

`referenz_wert.von.postleitzahl`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"12049"`

Kod pocztowy adresu początkowego lub końcowego.

#### `von.strasse / bis.strasse`

`referenz_wert.von.strasse`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"Hauptstrasse"`

Nazwa ulicy adresu początkowego lub końcowego.

#### `von.hausnummer / bis.hausnummer`

`referenz_wert.von.hausnummer`

- **Typ:** `string` — **wymagane**
- **Przykład:** `"15"`

Numer domu adresu początkowego lub końcowego. Ciąg znaków, aby możliwe były przyrostki takie jak 15a.

### Notatki

`notizen` — 1 pola

Pojedyncze pole tekstu dowolnego — a zarazem miejsce, w którym aplikacja umieszcza znaczniki maszynowe.

#### `notizen`

`notizen`

- **Typ:** `string` — opcjonalne
- **Ograniczenia:** `maxLength: 500`
- **Przykład:** `"Indikation: Blattlaeuse. Es wurde lediglich die Haelfte des Feldes behandelt."`

Notatki tekstowe o zabiegu, maksymalnie 500 znaków.

> **Uwaga:** To pole to nie tylko tekst dowolny. Zezwolenie awaryjne z art. 53 nie ma własnego pola w schemacie; aplikacja oznacza je zamiast tego kodami niezależnymi od języka wewnątrz notizen (PPS_EA, PPS_NZ, ŚOR_ZN) i odczytuje je przy edycji oraz imporcie. Wybrane wskazanie i termin zabiegu również są tutaj dopisywane. Programowe nadpisanie notizen może więc usunąć jedyny trwały ślad zezwolenia awaryjnego. Eksport anonimizowany usuwa to pole w całości.
