{
  "openapi": "3.0.3",
  "info": {
    "title": "cpmhub REST-API für trawa",
    "version": "0.5.2",
    "description": "Stand 13.11.2026 · API-Vertrag 0.5.2 · Ticket 22160.\nA–E einschließlich Stapel, kontrolliertem lokalem Storno und Zählerstandskorrekturen sind für die getrennte\ntrawa-Testkopie implementiert. Der aktuelle Bereitstellungsnachweis steht im Ticket.\nC/D und Korrekturen benötigen einen eigenen Freischalter. Webhooks sind technisch vorbereitet und werden erst mit\nvereinbartem Ziel und Signaturschlüssel aktiviert; solange steht Polling zur Verfügung. Die Testkopie versendet keine Marktkommunikation.\nCPM und XAP arbeiten auf kopierten Daten. Die MIS-Netzbetreiberabfrage ist gezielt lesend freigegeben.\nAlle Beispiele sind synthetisch. Nicht bekannte Daten werden als null ausgewiesen.\n"
  },
  "servers": [
    {
      "url": "https://trawa-test.wattform.de/cpm/evu/cpmhub/v1",
      "description": "Getrennte trawa-Testkopie; Bereitstellungsstand siehe Ticket."
    }
  ],
  "tags": [
    {
      "name": "A – Aufträge"
    },
    {
      "name": "B – Status"
    },
    {
      "name": "C – Klärung"
    },
    {
      "name": "D – Lieferende"
    },
    {
      "name": "E – Zählerstände"
    }
  ],
  "paths": {
    "/auftraege": {
      "post": {
        "operationId": "auftragAnnehmen",
        "summary": "Vertrag mit Lieferstellenübergaben übermitteln",
        "description": "201 bedeutet dauerhafter Eingang, keine erfolgreiche Anmeldung. Dasselbe vollständige Paket mit identischer paket_id und gleichem normalisiertem Inhalt liefert die unveränderte Eingangsquittung erneut (HTTP 200). Den aktuellen Verarbeitungsstand liefert GET auf den Auftrag. Geänderter Inhalt unter derselben Kennung ergibt 409. Nach Ablehnung: neue uebergabe_id und ersetzt_uebergabe_id; bei Vertragskorrektur zusätzlich höhere vertrag_version.",
        "tags": [
          "A – Aufträge"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [],
        "responses": {
          "201": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Auftrag"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "200": {
            "description": "Identische Wiederholung; gespeicherte Quittung.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Auftrag"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuftragEingang"
              },
              "example": {
                "vertrag": {
                  "schema_version": "1.0",
                  "vertrag_id": "20000000-0000-4000-8000-000000000001",
                  "vertrag_version": 1,
                  "externe_vertragsnummer": "TRAWA-TEST-001",
                  "vertragsart": "Einzug",
                  "versorgungsart": "Strom",
                  "eingangskanal": "Schriftlich",
                  "auftragseingang": "2026-11-12",
                  "kunde": {
                    "kunde_id": "10000000-0000-4000-8000-000000000001",
                    "anrede": "Firma",
                    "firmenname": "Synthetischer Testbetrieb GmbH",
                    "email": "auftrag@example.invalid",
                    "kommunikation": {
                      "dokumente_per_mail": false,
                      "bestaetigungsmail": false
                    }
                  },
                  "produkt": {
                    "tarif": "TRAWA-TEST",
                    "vertragstyp": "Sondervertragskunde",
                    "waermestromoption": "KEINE"
                  },
                  "preise": {
                    "arbeitspreis_eur_kwh": 0.12,
                    "grundpreis_pauschale_eur_monat": 10,
                    "ust_satz": 0.19,
                    "preisgarantie": {
                      "wert": 12,
                      "einheit": "Monate"
                    }
                  },
                  "laufzeit": {
                    "mindestlaufzeit": {
                      "wert": 12,
                      "einheit": "Monate"
                    },
                    "anschlusslaufzeit": {
                      "wert": 1,
                      "einheit": "Monate"
                    },
                    "kuendigungsfrist": {
                      "wert": 1,
                      "einheit": "Monate",
                      "bezug": "Rollierend"
                    },
                    "kuendigungsfrist_anschluss": {
                      "wert": 1,
                      "einheit": "Monate",
                      "bezug": "Rollierend"
                    }
                  },
                  "uebergaben": [
                    {
                      "uebergabe_id": "40000000-0000-4000-8000-000000000001",
                      "lieferstelle_id": "30000000-0000-4000-8000-000000000001"
                    }
                  ],
                  "dokumente": []
                },
                "uebergaben": [
                  {
                    "schema_version": "1.0",
                    "uebergabe_id": "40000000-0000-4000-8000-000000000001",
                    "paket_id": "50000000-0000-4000-8000-000000000001",
                    "erstellt_am": "2026-11-12T10:00:00+01:00",
                    "vertrag_ref": {
                      "vertrag_id": "20000000-0000-4000-8000-000000000001",
                      "vertrag_version": 1
                    },
                    "lieferstelle": {
                      "lieferstelle_id": "30000000-0000-4000-8000-000000000001",
                      "lieferbeginn": "2027-01-01",
                      "netzfrequenz": "50",
                      "adresse": {
                        "strasse": "Teststraße",
                        "hausnummer": "12a",
                        "plz": "12345",
                        "ort": "Teststadt"
                      }
                    },
                    "rechnungsadresse": {
                      "anrede": "Firma",
                      "firmenname": "Synthetischer Testbetrieb GmbH",
                      "strasse": "Teststraße",
                      "hausnummer": "12a",
                      "plz": "12345",
                      "ort": "Teststadt",
                      "email": "rechnung@example.invalid"
                    },
                    "zaehler": {
                      "zaehlernummer": "TRAWA-TEST-001",
                      "zaehlertyp": "MME",
                      "prognoseverbrauch_kwh": 10000
                    },
                    "zahlung": {
                      "lastschrifteinzug": false
                    },
                    "angebotszusammenfassung_erzeugen": false,
                    "bestaetigungsmail": false,
                    "importmodus": "Anmeldung"
                  }
                ],
                "dokumente": []
              }
            }
          }
        }
      }
    },
    "/auftraege/{id}": {
      "get": {
        "operationId": "auftragLesen",
        "summary": "Quittungen und Bearbeitungsstand lesen",
        "description": "",
        "tags": [
          "A – Aufträge"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Auftrag"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Versionskennung einschließlich Anführungszeichen, für If-Match unverändert übernehmen.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/auftraege/stapel": {
      "post": {
        "operationId": "stapelAnnehmen",
        "summary": "Auftragsstapel asynchron annehmen",
        "description": "Stapel-ID und Empfang sofort; Verarbeitung und Quittung je Übergabe später. Wiederholung derselben stapel_id ist idempotent und liefert die erste Quittung unverändert. Vollständige Strukturprüfung erfolgt vor Annahme; danach bleiben fachliche Einzelfehler je Position sichtbar. Das Manifest enthält SHA-256 des normalisierten gesamten Stapels und je Position.",
        "tags": [
          "A – Aufträge"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Stapel"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StapelEingang"
              }
            }
          }
        }
      }
    },
    "/auftraege/stapel/{id}": {
      "get": {
        "operationId": "stapelLesen",
        "summary": "Stapelstand und Einzelquittungen lesen",
        "description": "",
        "tags": [
          "A – Aufträge"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Stapel"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/auftraege/{id}/storno": {
      "post": {
        "operationId": "auftragStornieren",
        "summary": "Auftrag kontrolliert abbrechen",
        "description": "Direkter lokaler Abbruch nur vor Beginn von Kündigung oder Anmeldung. Nach Versand: 409 und operative Klärung, auch wenn noch keine Bestätigung eingegangen ist. Keine Behauptung einer Markt-Rücknahme.",
        "tags": [
          "A – Aufträge"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Aktuelle Versionskennung aus ETag der vorherigen GET-Antwort."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": "Neue UUID je fachlichem Änderungsauftrag; bei Transportwiederholung wiederverwenden."
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bearbeitungsauftrag"
                }
              }
            },
            "headers": {
              "Location": {
                "description": "Abruf des Bearbeitungsauftrags.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Storno"
              }
            }
          }
        }
      }
    },
    "/vertraege/{nr}/status": {
      "get": {
        "operationId": "vertragsstatusLesen",
        "summary": "Aktuellen Vertragsstatus lesen",
        "description": "nr ist die solvit-Vertragsnummer oder die externe vertrag_id aus einem API-Auftrag. Bei mehreren Lieferstellen zum externen Vertrag ist lieferstelle_id erforderlich. Der Einzelabruf aktualisiert die Sicht unmittelbar aus den vorhandenen CPM-Prozessdaten.",
        "tags": [
          "B – Status"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "nr",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "solvit-Vertragsnummer oder externe vertrag_id, keine Datenbank-ID. Bei mehreren Lieferstellen lieferstelle_id angeben."
          },
          {
            "name": "lieferstelle_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Vertragsstatus"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Versionskennung einschließlich Anführungszeichen, für If-Match unverändert übernehmen.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/status": {
      "get": {
        "operationId": "statusAenderungenLesen",
        "summary": "Geänderte Vertragsstatus seitenweise lesen",
        "description": "Änderungsprotokoll der beobachteten Statussichten; ein Vertrag kann mit mehreren Versionen vorkommen. Erster Abruf optional mit geaendert_seit. Alle naechster_cursor-Seiten abarbeiten, danach beim nächsten Poll fortsetzungs_cursor als cursor verwenden. Cursor nicht mit geaendert_seit kombinieren. Der fortsetzungs_cursor enthält eine commit-geordnete Sequenz; snapshot_bis dient nur zur Orientierung. Neuere Änderungen verändern laufende Seiten nicht. Deduplizieren anhand status_id und version. Die Hintergrundsicht wird in begrenzten Portionen aktualisiert; sie kann dem Einzelabruf nachlaufen. initialisierung_abgeschlossen bleibt bis zum ersten vollständigen erfolgreichen Bestandslauf false.",
        "tags": [
          "B – Status"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": ""
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "geaendert_seit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
              "format": "date-time"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusSeite"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/vertraege/{nr}/klaerung": {
      "post": {
        "operationId": "klaerungEinreichen",
        "summary": "Korrektur oder Entscheidung einreichen",
        "description": "",
        "tags": [
          "C – Klärung"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [
          {
            "name": "nr",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "solvit-Vertragsnummer oder externe vertrag_id, keine Datenbank-ID. Bei mehreren Lieferstellen lieferstelle_id angeben."
          },
          {
            "name": "lieferstelle_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": ""
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Aktuelle Versionskennung aus ETag der vorherigen GET-Antwort."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": "Neue UUID je fachlichem Änderungsauftrag; bei Transportwiederholung wiederverwenden."
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bearbeitungsauftrag"
                }
              }
            },
            "headers": {
              "Location": {
                "description": "Abruf des Bearbeitungsauftrags.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Klaerung"
              }
            }
          }
        }
      }
    },
    "/vertraege/{nr}/lieferende": {
      "post": {
        "operationId": "lieferendeEinreichen",
        "summary": "Reguläre Abmeldung beauftragen",
        "description": "",
        "tags": [
          "D – Lieferende"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [
          {
            "name": "nr",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "solvit-Vertragsnummer oder externe vertrag_id, keine Datenbank-ID. Bei mehreren Lieferstellen lieferstelle_id angeben."
          },
          {
            "name": "lieferstelle_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": ""
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Aktuelle Versionskennung aus ETag der vorherigen GET-Antwort."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": "Neue UUID je fachlichem Änderungsauftrag; bei Transportwiederholung wiederverwenden."
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bearbeitungsauftrag"
                }
              }
            },
            "headers": {
              "Location": {
                "description": "Abruf des Bearbeitungsauftrags.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Lieferende"
              }
            }
          }
        }
      }
    },
    "/vertraege/{nr}/kuendigung/antwort": {
      "post": {
        "operationId": "kuendigungsantwortEinreichen",
        "summary": "Eingegangene Kündigung beantworten",
        "description": "",
        "tags": [
          "D – Lieferende"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [
          {
            "name": "nr",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "solvit-Vertragsnummer oder externe vertrag_id, keine Datenbank-ID. Bei mehreren Lieferstellen lieferstelle_id angeben."
          },
          {
            "name": "lieferstelle_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": ""
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Aktuelle Versionskennung aus ETag der vorherigen GET-Antwort."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": "Neue UUID je fachlichem Änderungsauftrag; bei Transportwiederholung wiederverwenden."
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bearbeitungsauftrag"
                }
              }
            },
            "headers": {
              "Location": {
                "description": "Abruf des Bearbeitungsauftrags.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Kuendigungsantwort"
              }
            }
          }
        }
      }
    },
    "/zaehlerstaende": {
      "post": {
        "operationId": "zaehlerstaendeEinreichen",
        "summary": "Zählerstand oder Liste zur Prüfung übermitteln",
        "description": "Nur Eingang in den geprüften Bearbeitungsweg. Für Listen gilt dieselbe Quittung je uebermittlung_id. Identische Wiederholung liefert unverändert die erste Quittung (202), geänderter Inhalt 409. Ein defektes Element rollt die gesamte Liste zurück. GET /zaehlerstaende/{id} liefert den aktuellen Bearbeitungsstand. in_pruefung enthält keine noch ungeklärte fachliche Ablehnung.",
        "tags": [
          "E – Zählerstände"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ZaehlerstandQuittung"
                    },
                    {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ZaehlerstandQuittung"
                      },
                      "minItems": 1,
                      "maxItems": 100
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/ZaehlerstandEingang"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ZaehlerstandEingang"
                    },
                    "minItems": 1,
                    "maxItems": 100
                  }
                ]
              },
              "example": {
                "uebermittlung_id": "60000000-0000-4000-8000-000000000001",
                "zaehlernummer": "TRAWA-TEST-001",
                "ablesedatum": "2026-11-12",
                "herkunft": "trawa",
                "ablesegrund": "Zwischenablesung",
                "messwerte": [
                  {
                    "obis": "1-1:1.8.0",
                    "wert": 12345.67,
                    "einheit": "kWh"
                  }
                ]
              }
            }
          }
        }
      },
      "get": {
        "operationId": "zaehlerstaendeLesen",
        "summary": "Freigegebene Zählerstände lesen",
        "description": "Mindestens malo, melo oder zaehlernummer erforderlich. von/bis einschließlich. Keine Herausgabe noch ungeklärter unplausibler Werte. Seiten gehören zu einem unveränderlichen Snapshot (24 Stunden gültig); Cursor mit denselben Filtern verwenden. Bei mehr als 5000 Messwertzeilen oder 1000 Ablesungen den Zeitraum eingrenzen. Ohne von gilt 1900-01-01, ohne bis der aktuelle Tag. Historische Herkunft wird ohne Beleg als unbekannt gekennzeichnet. daten enthält nur fortlaufende Stände. Verbrauchs-/Rückstellwerte stehen getrennt in mengen_und_rueckstellwerte mit wertarten, wandlerfaktoren und quellreferenzen. Beide Bereiche teilen denselben Cursor und dasselbe Limit; auch bei leerem daten kann es weitere Seiten geben. Cursor aus 0.5.1 sind nach dem Wechsel zu 0.5.2 ungültig; den ersten Abruf mit denselben Filtern neu starten.",
        "tags": [
          "E – Zählerstände"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": ""
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "malo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "melo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "zaehlernummer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "von",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Fachliches Datum, YYYY-MM-DD.",
              "format": "date"
            },
            "description": ""
          },
          {
            "name": "bis",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Fachliches Datum, YYYY-MM-DD.",
              "format": "date"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ZaehlerstandSeite"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/zaehlerstaende/{id}": {
      "get": {
        "operationId": "zaehlerstandQuittungLesen",
        "summary": "Bearbeitungsstand des Zählerstandseingangs lesen",
        "description": "",
        "tags": [
          "E – Zählerstände"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ZaehlerstandQuittung"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "demo",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/zaehlerstaende/{id}/korrektur": {
      "post": {
        "operationId": "zaehlerstandKorrigieren",
        "summary": "Neue Korrekturversion einreichen",
        "description": "",
        "tags": [
          "E – Zählerstände"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:write"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Aktuelle Versionskennung aus ETag der vorherigen GET-Antwort."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
              "format": "uuid"
            },
            "description": "Neue UUID je fachlichem Änderungsauftrag; bei Transportwiederholung wiederverwenden."
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ZaehlerstandQuittung"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ZaehlerstandKorrektur"
              }
            }
          }
        }
      }
    },
    "/bearbeitungsauftraege/{id}": {
      "get": {
        "operationId": "bearbeitungsauftragLesen",
        "summary": "Stand einer Klärung oder D-Änderung lesen",
        "description": "",
        "tags": [
          "C – Klärung"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bearbeitungsauftrag"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    },
    "/zaehlerstaende/werte/{id}": {
      "get": {
        "operationId": "ableseversionLesen",
        "summary": "Freigegebene aktuelle oder historische Version lesen",
        "description": "id stammt aus GET /zaehlerstaende. ETag enthält die Version für einen Korrekturauftrag. Historische Versionen verfallen nicht mit dem 24-Stunden-Seitencursor.",
        "tags": [
          "E – Zählerstände"
        ],
        "security": [
          {
            "OAuth2": []
          }
        ],
        "x-erforderliche-client-rollen": [
          "cpmhub:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Interne, von der API vergebene Kennung.",
              "format": "uuid"
            },
            "description": "Kennung des jeweiligen Objekts; siehe Beschreibung der Operation."
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Zaehlerstand"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Versionskennung einschließlich Anführungszeichen, für If-Match unverändert übernehmen.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiges JSON oder Anfrageformat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Token fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Mandant, Rolle oder Funktion nicht freigegeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Referenz nicht gefunden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Idempotenz- oder Zustandskonflikt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "412": {
            "description": "If-Match oder Korrekturbasis veraltet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "428": {
            "description": "If-Match fehlt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "413": {
            "description": "Anfrage zu groß.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "422": {
            "description": "Fachliche Eingangsprüfung fehlgeschlagen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Aufrufgrenze erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "503": {
            "description": "Abhängiger Dienst vorübergehend nicht erreichbar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "x-ausbaustufe": "test",
        "x-bereitstellungsstand": "im_test_bereitgestellt"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "description": "Berechtigung durch Client-Rollen in resource_access.cpm-trawa-test.roles; erforderliche Rollen je Operation unter x-erforderliche-client-rollen. Keine gleichnamigen OAuth2-Scopes erforderlich.",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://trawa-test.wattform.de/auth/realms/trawa-test/protocol/openid-connect/token",
            "scopes": {}
          }
        }
      }
    },
    "schemas": {
      "Adresse": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "strasse": {
            "type": "string",
            "maxLength": 140
          },
          "hausnummer": {
            "type": "string",
            "description": "Auch Zusätze und Bereiche, etwa 12a oder 2-8.",
            "maxLength": 30
          },
          "hausnummer_zusatz": {
            "type": "string",
            "maxLength": 60,
            "nullable": true
          },
          "plz": {
            "type": "string",
            "pattern": "^[0-9]{5}$"
          },
          "ort": {
            "type": "string",
            "maxLength": 140
          }
        },
        "required": [
          "strasse",
          "hausnummer",
          "plz",
          "ort"
        ]
      },
      "Rechnungsadresse": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "strasse": {
            "type": "string",
            "maxLength": 140
          },
          "hausnummer": {
            "type": "string",
            "description": "Auch Zusätze und Bereiche, etwa 12a oder 2-8.",
            "maxLength": 30
          },
          "hausnummer_zusatz": {
            "type": "string",
            "maxLength": 60,
            "nullable": true
          },
          "plz": {
            "type": "string",
            "pattern": "^[0-9]{5}$"
          },
          "ort": {
            "type": "string",
            "maxLength": 140
          },
          "anrede": {
            "type": "string",
            "enum": [
              "Herr",
              "Frau",
              "Firma"
            ]
          },
          "titel": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "vorname": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "nachname": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "firmenname": {
            "type": "string",
            "maxLength": 140,
            "nullable": true
          },
          "co": {
            "type": "string",
            "maxLength": 140,
            "nullable": true
          },
          "postfach": {
            "type": "string",
            "maxLength": 30,
            "nullable": true
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254,
            "nullable": true
          }
        },
        "description": "Vertragsbezogene Rechnungsadresse. Bei Postfach können Straße und Hausnummer entfallen. Rechnungs-E-Mail und Versandkanal werden je Lieferstellenvertrag ausgewertet."
      },
      "Kommunikation": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "email_rechnungen": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "email_mahnungen": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "dokumente_per_mail": {
            "type": "boolean"
          },
          "dokumente_stammdaten_per_mail": {
            "type": "boolean"
          },
          "bestaetigungsmail": {
            "type": "boolean"
          }
        }
      },
      "Kunde": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "kunde_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "externe_kundennummer": {
            "type": "string",
            "maxLength": 100,
            "nullable": true
          },
          "starqhub_kundennummer": {
            "type": "string",
            "description": "Kompatibilitätsfeld des STARQ-Formats. Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "maxLength": 100,
            "nullable": true,
            "x-bereitstellungsstand": "spezifiziert"
          },
          "kundengruppe": {
            "type": "string",
            "maxLength": 100,
            "nullable": true
          },
          "konzernintern": {
            "type": "boolean",
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "segment": {
            "type": "string",
            "maxLength": 40,
            "nullable": true,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "anrede": {
            "type": "string",
            "enum": [
              "Herr",
              "Frau",
              "Firma"
            ]
          },
          "titel": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "vorname": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "nachname": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "firmenname": {
            "type": "string",
            "maxLength": 140,
            "nullable": true
          },
          "telefon": {
            "type": "string",
            "maxLength": 70,
            "nullable": true
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "kommunikation": {
            "$ref": "#/components/schemas/Kommunikation"
          },
          "rechnungsadresse": {
            "type": "object",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/Rechnungsadresse"
              }
            ]
          }
        },
        "required": [
          "kunde_id",
          "anrede"
        ],
        "description": "Bei Firma ist firmenname erforderlich, sonst nachname. Externe Kundennummern sind keine internen CPM-IDs."
      },
      "Zeitraum": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "wert": {
            "type": "integer",
            "minimum": 0
          },
          "einheit": {
            "type": "string",
            "enum": [
              "Tage",
              "Wochen",
              "Monate",
              "Jahre"
            ]
          }
        },
        "required": [
          "wert",
          "einheit"
        ]
      },
      "Kuendigungsfrist": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "wert": {
            "type": "integer",
            "minimum": 0
          },
          "einheit": {
            "type": "string",
            "enum": [
              "Tage",
              "Wochen",
              "Monate",
              "Jahre"
            ]
          },
          "bezug": {
            "type": "string",
            "description": "Bezugspunkt aus der konfigurierten CPM-Werteliste, etwa Rollierend."
          }
        },
        "required": [
          "wert",
          "einheit",
          "bezug"
        ]
      },
      "Preisgarantie": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "wert": {
            "type": "integer",
            "minimum": 0
          },
          "einheit": {
            "type": "string",
            "enum": [
              "Tage",
              "Wochen",
              "Monate",
              "Jahre"
            ]
          },
          "bis": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date",
            "nullable": true
          },
          "typ": {
            "type": "string",
            "description": "CPM-Preisgarantietyp.",
            "nullable": true
          }
        },
        "description": "Entweder wert/einheit oder bis. Keine automatische Vertragsbeendigung."
      },
      "Preise": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "arbeitspreis_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit. Negative Arbeitspreise sind wie im CSV-Massenimport zulässig; die gemeinsame Anlageprüfung verlangt einen Wert unter 1 EUR/kWh."
          },
          "arbeitspreis_nt_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit. Negative Arbeitspreise sind wie im CSV-Massenimport zulässig; die gemeinsame Anlageprüfung verlangt einen Wert unter 1 EUR/kWh.",
            "nullable": true
          },
          "grundpreis_pauschale_eur_monat": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit."
          },
          "foerderbeitrag_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "strukturierungskosten_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "ausgleichsenergiepauschale_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "ap_basis_ht_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "ap_basis_nt_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "ap_aufschlag_ht_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "ap_aufschlag_nt_eur_kwh": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "gp_basis_eur_monat": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "gp_aufschlag_eur_monat": {
            "type": "number",
            "description": "Nettopreis in der im Feldnamen genannten Einheit.",
            "nullable": true
          },
          "ust_satz": {
            "type": "number",
            "description": "Anteil, beispielsweise 0.19 für 19 Prozent.",
            "minimum": 0,
            "maximum": 1,
            "nullable": true
          },
          "vorlaeufig": {
            "type": "boolean"
          },
          "gewichtung": {
            "type": "string",
            "nullable": true,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "preisgarantie": {
            "$ref": "#/components/schemas/Preisgarantie"
          }
        },
        "required": [
          "arbeitspreis_eur_kwh",
          "grundpreis_pauschale_eur_monat",
          "preisgarantie"
        ]
      },
      "Laufzeit": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "mindestlaufzeit": {
            "type": "object",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/Zeitraum"
              }
            ]
          },
          "bindung_bis": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date",
            "nullable": true
          },
          "anschlusslaufzeit": {
            "$ref": "#/components/schemas/Zeitraum"
          },
          "kuendigungsfrist": {
            "$ref": "#/components/schemas/Kuendigungsfrist"
          },
          "kuendigungsfrist_anschluss": {
            "$ref": "#/components/schemas/Kuendigungsfrist"
          }
        },
        "required": [
          "anschlusslaufzeit",
          "kuendigungsfrist",
          "kuendigungsfrist_anschluss"
        ],
        "description": "Mindestlaufzeit oder bindung_bis ist erforderlich. bindung_bis ist eine Vertragsbindung und kein Lieferende."
      },
      "Produkt": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "tarif": {
            "type": "string",
            "maxLength": 255
          },
          "tariftyp": {
            "type": "string",
            "nullable": true
          },
          "vertragstyp": {
            "type": "string",
            "description": "CPM-Kundenart, z. B. RLMKunde oder Sondervertragskunde. Bei eindeutiger mandantenspezifischer Tarifzuordnung darf sie entfallen."
          },
          "waermestromoption": {
            "type": "string",
            "default": "KEINE"
          },
          "rabattcode": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "tarif"
        ]
      },
      "Energiemix": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "anteil_fix_prozent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "nullable": true
          },
          "anteil_flex_prozent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "nullable": true
          },
          "anteil_solar_prozent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "nullable": true
          },
          "anteil_wind_prozent": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "nullable": true
          },
          "spot_hkn_eur_kwh": {
            "type": "number",
            "nullable": true
          },
          "referenzpreis_eur_kwh": {
            "type": "number",
            "nullable": true
          }
        }
      },
      "Dokumentverweis": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "dokument_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "typ": {
            "type": "string",
            "maxLength": 100
          },
          "dateiname": {
            "type": "string",
            "description": "Ein Dateiname ohne Verzeichnisbestandteile.",
            "maxLength": 255
          }
        },
        "required": [
          "dokument_id",
          "typ",
          "dateiname"
        ]
      },
      "Vertrag": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "schema_version": {
            "type": "string",
            "enum": [
              "1.0"
            ]
          },
          "vertrag_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "vertrag_version": {
            "type": "integer",
            "minimum": 1
          },
          "externe_vertragsnummer": {
            "type": "string",
            "maxLength": 100,
            "nullable": true
          },
          "starqhub_vertragsnummer": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "vertragsart": {
            "type": "string",
            "enum": [
              "Lieferantenwechsel",
              "Einzug",
              "Neubezug"
            ]
          },
          "versorgungsart": {
            "type": "string",
            "enum": [
              "Strom",
              "Gas"
            ]
          },
          "eingangskanal": {
            "type": "string",
            "description": "CPM-Eingangskanal, z. B. Schriftlich."
          },
          "auftragseingang": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date"
          },
          "unterzeichnet_kunde_am": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD. Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "format": "date",
            "nullable": true,
            "x-bereitstellungsstand": "spezifiziert"
          },
          "gegengezeichnet_am": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD. Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "format": "date",
            "nullable": true,
            "x-bereitstellungsstand": "spezifiziert"
          },
          "kunde": {
            "$ref": "#/components/schemas/Kunde"
          },
          "produkt": {
            "$ref": "#/components/schemas/Produkt"
          },
          "preise": {
            "$ref": "#/components/schemas/Preise"
          },
          "energiemix": {
            "$ref": "#/components/schemas/Energiemix"
          },
          "laufzeit": {
            "$ref": "#/components/schemas/Laufzeit"
          },
          "vertriebspartner": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "nullable": true
              },
              "kundennummer": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "uebergaben": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "uebergabe_id": {
                  "type": "string",
                  "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
                  "format": "uuid"
                },
                "lieferstelle_id": {
                  "type": "string",
                  "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
                  "format": "uuid"
                }
              },
              "required": [
                "uebergabe_id",
                "lieferstelle_id"
              ]
            },
            "minItems": 1,
            "maxItems": 50
          },
          "dokumente": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dokumentverweis"
            },
            "maxItems": 20,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          }
        },
        "required": [
          "schema_version",
          "vertrag_id",
          "vertrag_version",
          "vertragsart",
          "versorgungsart",
          "eingangskanal",
          "auftragseingang",
          "kunde",
          "produkt",
          "preise",
          "laufzeit",
          "uebergaben"
        ]
      },
      "Vorversorger": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "marktpartner_id": {
            "type": "string",
            "nullable": true,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "kundennummer": {
            "type": "string",
            "nullable": true,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "kuendigung_durch_kunde": {
            "type": "boolean"
          }
        }
      },
      "Lieferstelle": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "lieferstelle_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "malo_id": {
            "type": "string",
            "pattern": "^[0-9]{11}$",
            "nullable": true
          },
          "lieferbeginn": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date"
          },
          "bezeichnung": {
            "type": "string",
            "maxLength": 255,
            "nullable": true
          },
          "adresse": {
            "$ref": "#/components/schemas/Adresse"
          },
          "selbstzahler_msb": {
            "type": "boolean"
          },
          "selbstzahler_nne": {
            "type": "boolean"
          },
          "vorversorger": {
            "type": "object",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/Vorversorger"
              }
            ]
          },
          "netzbetreiber_id": {
            "type": "string",
            "nullable": true,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          },
          "netzfrequenz": {
            "type": "string",
            "description": "Hz; 16.7 bezeichnet Bahnstrom.",
            "enum": [
              "50",
              "16.7"
            ]
          },
          "rueckspeise_malo_id": {
            "type": "string",
            "pattern": "^[0-9]{11}$",
            "nullable": true
          },
          "virtuelle_entnahmestelle": {
            "type": "string",
            "nullable": true
          },
          "bilanzkreis": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "lieferstelle_id",
          "lieferbeginn",
          "adresse"
        ],
        "description": "Bahnstrom wird mit den bestehenden CPM-Regeln validiert; keine eigene vereinfachte Marktprüfung."
      },
      "Zaehler": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "melo_id": {
            "type": "string",
            "maxLength": 33,
            "nullable": true
          },
          "zaehlernummer": {
            "type": "string",
            "maxLength": 100,
            "nullable": true
          },
          "zaehlertyp": {
            "type": "string",
            "enum": [
              "KME",
              "MME",
              "IMS"
            ]
          },
          "prognoseverbrauch_kwh": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "prognoseverbrauch_kwh"
        ],
        "description": "Mindestens MaLo, MeLo oder Zählernummer muss die Lieferstelle identifizieren. Der vorhandene Anlageweg verarbeitet einen Zähler je Lieferstellenvertrag; mehrere gleichzeitige Zähler werden als Klärbedarf zurückgewiesen, niemals zusammengefügt."
      },
      "SepaMandat": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "mandatstyp": {
            "type": "string",
            "enum": [
              "basis"
            ]
          },
          "erteilt_am": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date"
          },
          "nachweis_dokument_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "mandatsreferenz": {
            "type": "string",
            "description": "Wird durch solvit vergeben.",
            "nullable": true
          }
        },
        "required": [
          "mandatstyp",
          "erteilt_am",
          "nachweis_dokument_id"
        ]
      },
      "Zahlung": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "kontoinhaber": {
            "type": "string",
            "nullable": true
          },
          "iban": {
            "type": "string",
            "maxLength": 34,
            "nullable": true
          },
          "lastschrifteinzug": {
            "type": "boolean"
          },
          "sepa_mandat": {
            "type": "object",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/SepaMandat"
              }
            ],
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          }
        },
        "required": [
          "lastschrifteinzug"
        ]
      },
      "Uebergabe": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "schema_version": {
            "type": "string",
            "enum": [
              "1.0"
            ]
          },
          "uebergabe_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "paket_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "erstellt_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "ersetzt_uebergabe_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid",
            "nullable": true
          },
          "vertrag_ref": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "vertrag_id": {
                "type": "string",
                "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
                "format": "uuid"
              },
              "vertrag_version": {
                "type": "integer",
                "minimum": 1
              },
              "starqhub_vertragsnummer": {
                "type": "string",
                "nullable": true,
                "description": "Ausbau: derzeit nicht befüllen; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
                "x-bereitstellungsstand": "spezifiziert"
              }
            },
            "required": [
              "vertrag_id",
              "vertrag_version"
            ]
          },
          "abrechnungsbasis": {
            "type": "string",
            "enum": [
              "lastgang",
              "ablesung"
            ]
          },
          "abrechnungsrhythmus": {
            "type": "string",
            "enum": [
              "monatlich",
              "jaehrlich_mit_abschlaegen"
            ]
          },
          "lieferstelle": {
            "$ref": "#/components/schemas/Lieferstelle"
          },
          "rechnungsadresse": {
            "$ref": "#/components/schemas/Rechnungsadresse"
          },
          "zaehler": {
            "$ref": "#/components/schemas/Zaehler"
          },
          "zahlung": {
            "$ref": "#/components/schemas/Zahlung"
          },
          "abschlag": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "monatlich_eur": {
                "type": "number",
                "minimum": 0
              },
              "erste_faelligkeit": {
                "type": "string",
                "description": "Ausbau: derzeit nicht befüllen; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
                "format": "date",
                "x-bereitstellungsstand": "spezifiziert"
              }
            },
            "required": [
              "monatlich_eur"
            ],
            "nullable": true
          },
          "importmodus": {
            "type": "string",
            "description": "Bestandsmigration ist standardmäßig gesperrt und erfordert die separate Freigabe des Mandanten und technischen Clients.",
            "enum": [
              "Anmeldung",
              "Bestandsmigration"
            ]
          },
          "leitweg_id": {
            "type": "string",
            "nullable": true
          },
          "bestellnummer": {
            "type": "string",
            "nullable": true
          },
          "angebotszusammenfassung_erzeugen": {
            "type": "boolean"
          },
          "bestaetigungsmail": {
            "type": "boolean"
          },
          "abschlagsplan": {
            "type": "boolean"
          },
          "entgelte": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "nne_gp": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "nne_ap": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "nne_ap_nt": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "konzessionsabgabe": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "konzessionsabgabe_nt": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "messstellenbetrieb": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "messdienstleistung": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "abrechnungspreis": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "eeg_umlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "kwk_umlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "par19_umlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "offshore_umlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "abschalt_umlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "stromsteuer": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "erdgassteuer": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "co2_abgabe": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "bilanzierungsumlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "konvertierungsentgelt": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              },
              "speicherumlage": {
                "type": "number",
                "description": "Euro in der Einheit des bestehenden CPM-Entgeltfelds.",
                "nullable": true
              }
            }
          }
        },
        "required": [
          "schema_version",
          "uebergabe_id",
          "paket_id",
          "erstellt_am",
          "vertrag_ref",
          "lieferstelle",
          "zaehler",
          "rechnungsadresse",
          "zahlung"
        ]
      },
      "Dokument": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "dokument_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "dateiname": {
            "type": "string",
            "maxLength": 255
          },
          "media_type": {
            "type": "string",
            "enum": [
              "application/pdf"
            ]
          },
          "groesse_bytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10485760
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "inhalt_base64": {
            "type": "string",
            "format": "byte"
          }
        },
        "required": [
          "dokument_id",
          "dateiname",
          "media_type",
          "groesse_bytes",
          "sha256",
          "inhalt_base64"
        ]
      },
      "AuftragEingang": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "vertrag": {
            "$ref": "#/components/schemas/Vertrag"
          },
          "uebergaben": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Uebergabe"
            },
            "minItems": 1,
            "maxItems": 50
          },
          "dokumente": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dokument"
            },
            "maxItems": 20,
            "description": "Ausbau: derzeit nur leer bzw. nicht befüllt zulässig; sonst 422 FELD_NOCH_NICHT_UNTERSTUETZT.",
            "x-bereitstellungsstand": "spezifiziert"
          }
        },
        "required": [
          "vertrag",
          "uebergaben"
        ],
        "description": "Ein Vertrag mit 1..50 Lieferstellenübergaben. Verweise, Versionen und Dokumentprüfsummen müssen zusammenpassen. REST überträgt das vollständige Paket in einem Request; ein Datei-Manifest ist hier nicht das Fertigsignal. Der SFTP-Transport behält seine Manifestregeln."
      },
      "Feldfehler": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "feld": {
            "type": "string",
            "description": "JSON-Pfad des betroffenen Felds."
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "feld",
          "text"
        ]
      },
      "Fehler": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "fehler": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Feldfehler"
            }
          }
        },
        "required": [
          "code",
          "text",
          "request_id"
        ]
      },
      "Quittung": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "auftrag_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "quittung_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "paket_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "kunde_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "vertrag_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "vertrag_version": {
            "type": "integer",
            "minimum": 1
          },
          "lieferstelle_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "uebergabe_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "ergebnis": {
            "type": "string",
            "enum": [
              "eingegangen",
              "uebernommen",
              "abgelehnt",
              "klaerung_erforderlich",
              "storniert"
            ]
          },
          "zeitpunkt": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "solvit_kundennummer": {
            "type": "string",
            "nullable": true
          },
          "solvit_vertragsnummer": {
            "type": "string",
            "nullable": true
          },
          "fehler": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Feldfehler"
            }
          }
        },
        "required": [
          "auftrag_id",
          "quittung_id",
          "paket_id",
          "kunde_id",
          "vertrag_id",
          "vertrag_version",
          "lieferstelle_id",
          "uebergabe_id",
          "ergebnis",
          "zeitpunkt"
        ]
      },
      "Auftrag": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "auftrag_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "angelegt_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "quittungen": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Quittung"
            }
          },
          "abgeschlossen": {
            "type": "boolean"
          }
        },
        "required": [
          "auftrag_id",
          "angelegt_am",
          "quittungen",
          "abgeschlossen"
        ]
      },
      "StapelEingang": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "stapel_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "auftraege": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuftragEingang"
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": [
          "stapel_id",
          "auftraege"
        ]
      },
      "Stapel": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "stapel_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "angenommen_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "anzahl": {
            "type": "integer",
            "minimum": 1
          },
          "bearbeitet": {
            "type": "integer",
            "minimum": 0
          },
          "abgeschlossen": {
            "type": "boolean"
          },
          "auftraege": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Auftrag"
            }
          },
          "manifest": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "sha256": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "normalisierung": {
                "type": "string",
                "enum": [
                  "cpmhub-canonical-json-v1"
                ]
              },
              "positionen": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "position": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "sha256": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$"
                    }
                  },
                  "required": [
                    "position",
                    "sha256"
                  ]
                }
              }
            },
            "required": [
              "sha256",
              "normalisierung",
              "positionen"
            ]
          },
          "positionen": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "position": {
                  "type": "integer",
                  "minimum": 1
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "ausstehend",
                    "angenommen",
                    "abgelehnt",
                    "klaerung_erforderlich"
                  ]
                },
                "auftrag_id": {
                  "type": "string",
                  "description": "Interne, von der API vergebene Kennung.",
                  "format": "uuid",
                  "nullable": true
                },
                "fehlercode": {
                  "type": "string",
                  "nullable": true
                },
                "fehlertext": {
                  "type": "string",
                  "nullable": true
                }
              },
              "required": [
                "position",
                "status"
              ]
            }
          }
        },
        "required": [
          "stapel_id",
          "angenommen_am",
          "anzahl",
          "bearbeitet",
          "abgeschlossen"
        ]
      },
      "Ereignis": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "ereignis_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "status_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "ereignis_typ": {
            "type": "string",
            "enum": [
              "ANMELDUNG_VERSENDET",
              "ANMELDUNG_BESTAETIGT",
              "ANMELDUNG_ABGELEHNT",
              "LIEFERBEGINN_BESTAETIGT",
              "ABMELDUNG_VERSENDET",
              "ABMELDUNG_BESTAETIGT",
              "LIEFERENDE_BESTAETIGT",
              "MALO_ERMITTLUNG_ANGEFRAGT",
              "MALO_ERMITTELT",
              "MALO_DATEN_ABWEICHEND",
              "MALO_NICHT_ERMITTELBAR",
              "KUENDIGUNG_ALTLIEFERANT_VERSENDET",
              "KUENDIGUNG_ALTLIEFERANT_BESTAETIGT",
              "KUENDIGUNG_ALTLIEFERANT_ABGELEHNT",
              "ABMELDUNG_ABGELEHNT",
              "KUENDIGUNG_EINGEGANGEN",
              "ZUORDNUNG_BEENDET",
              "KLAERUNG_ERFORDERLICH",
              "KLAERUNG_UEBERNOMMEN",
              "ZAEHLERSTAND_UEBERNOMMEN",
              "ZAEHLERSTAND_UNPLAUSIBEL",
              "ZAEHLERSTAND_KORRIGIERT"
            ]
          },
          "zeitpunkt": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "aufgezeichnet_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "vertrag_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid",
            "nullable": true
          },
          "lieferstelle_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid",
            "nullable": true
          },
          "uebergabe_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid",
            "nullable": true
          },
          "solvit_vertragsnummer": {
            "type": "string",
            "nullable": true
          },
          "vorgang_id": {
            "type": "string",
            "nullable": true
          },
          "code": {
            "type": "string",
            "description": "Originalcode; unbekannte Codes bleiben erhalten.",
            "nullable": true
          },
          "klartext": {
            "type": "string",
            "nullable": true
          },
          "originalhinweis": {
            "type": "string",
            "nullable": true
          },
          "antwortfrist": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "frist_grundlage": {
            "type": "string",
            "nullable": true
          },
          "fachdatum": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date",
            "nullable": true
          },
          "zaehlerstand_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid",
            "nullable": true
          },
          "ersetzt_zaehlerstand_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid",
            "nullable": true
          },
          "kontext": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "sparte": {
                "type": "string",
                "nullable": true
              },
              "pruefidentifikator": {
                "type": "string",
                "nullable": true
              },
              "formatversion": {
                "type": "string",
                "nullable": true
              }
            }
          }
        },
        "required": [
          "ereignis_id",
          "ereignis_typ",
          "zeitpunkt",
          "aufgezeichnet_am",
          "vertrag_id",
          "lieferstelle_id"
        ],
        "description": "Nur tatsächliche Marktantworten erzeugen Markt-Ablehnungsereignisse. Technische Fehler sind separat."
      },
      "Prozessschritt": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "schritt": {
            "type": "string",
            "enum": [
              "import",
              "malo_ident",
              "kuendigung_altlieferant",
              "anmeldung",
              "abmeldung",
              "kuendigung_eingang",
              "abgeschlossen",
              "unbekannt"
            ]
          },
          "seit": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "versuche": {
            "type": "integer",
            "minimum": 0,
            "nullable": true
          },
          "rueckmeldung_code": {
            "type": "string",
            "nullable": true
          },
          "rueckmeldung_klartext": {
            "type": "string",
            "nullable": true
          },
          "technischer_fehler": {
            "type": "string",
            "nullable": true
          },
          "contrl_positiv_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "contrl_negativ_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "anerkennung_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "naechste_bearbeitung_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "naechste_bearbeitung_quelle": {
            "type": "string",
            "nullable": true
          },
          "antwortfrist": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "frist_grundlage": {
            "type": "string",
            "nullable": true
          },
          "liegt_bei": {
            "type": "string",
            "enum": [
              "solvit",
              "trawa",
              "marktpartner",
              "unbekannt"
            ]
          },
          "empfehlung": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "schritt",
          "liegt_bei"
        ],
        "description": "Unbekannte Werte sind null, nicht geschätzt. Empfehlungen sind Hinweise, keine automatischen Marktentscheidungen."
      },
      "Vertragsstatus": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "vertrag_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid",
            "nullable": true
          },
          "lieferstelle_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid",
            "nullable": true
          },
          "solvit_vertragsnummer": {
            "type": "string",
            "nullable": true
          },
          "geaendert_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "letztes_ereignis": {
            "type": "object",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/Ereignis"
              }
            ]
          },
          "prozess": {
            "$ref": "#/components/schemas/Prozessschritt"
          },
          "ereignisse": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Ereignis"
            },
            "description": "Alle in dieser Statusversion neu aufgezeichneten Ereignisse. Alle Versionen aus GET /status abarbeiten und anhand ereignis_id deduplizieren. Ältere Versionen vor 0.4 können das Feld noch nicht enthalten."
          },
          "version": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "status_id",
          "vertrag_id",
          "lieferstelle_id",
          "geaendert_am",
          "prozess",
          "version"
        ],
        "description": "status_id ist eine interne API-Kennung. Externe UUIDs bleiben bei Altverträgen ohne belegte Zuordnung null. geaendert_am bezeichnet die Erfassung einer geänderten Sicht durch den cpmhub, nicht ein erfundenes historisches Quelldatum."
      },
      "StatusSeite": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "daten": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Vertragsstatus"
            }
          },
          "naechster_cursor": {
            "type": "string",
            "nullable": true
          },
          "fortsetzungs_cursor": {
            "type": "string"
          },
          "snapshot_bis": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "initialisierung_abgeschlossen": {
            "type": "boolean"
          }
        },
        "required": [
          "daten",
          "snapshot_bis",
          "fortsetzungs_cursor",
          "initialisierung_abgeschlossen"
        ]
      },
      "Klaerung": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "entscheidung": {
            "type": "string",
            "enum": [
              "weiterfuehren",
              "lieferbeginn_verschieben",
              "beenden"
            ]
          },
          "korrekturen": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "malo_id": {
                "type": "string",
                "pattern": "^[0-9]{11}$",
                "nullable": true
              },
              "zaehlernummer": {
                "type": "string",
                "nullable": true
              },
              "lieferadresse": {
                "$ref": "#/components/schemas/Adresse"
              },
              "name": {
                "type": "string"
              },
              "netzbetreiber_id": {
                "type": "string"
              },
              "lieferbeginn": {
                "type": "string",
                "description": "Fachliches Datum, YYYY-MM-DD.",
                "format": "date"
              }
            }
          },
          "begruendung": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "entscheidung"
        ],
        "description": "Nur zulässige Korrekturen im aktuellen Zustand. Höchstens zwei automatische Neustarts je Lieferstelle und Prozessphase; weitere Korrekturen setzen den Zähler nicht zurück. Vor erfolgreicher MaLo-Identifikation sind die benannten Korrekturen möglich. Nach erfolgreicher Vorphase ist die MaLo-/Netzbetreiberänderung operativ zu klären; in der Anmeldung ist automatisch nur ein späterer Lieferbeginn erlaubt. Keine Rücksetzung laufender Anfragen oder bereits erfolgreicher Phasen."
      },
      "Lieferende": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "zum": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date"
          },
          "grund": {
            "type": "string",
            "enum": [
              "Auszug",
              "Wechsel",
              "Stilllegung"
            ]
          },
          "begruendung": {
            "type": "string",
            "maxLength": 2000,
            "nullable": true
          }
        },
        "required": [
          "zum",
          "grund"
        ],
        "description": "Startet nach Prüfung den regulären Abmeldeprozess. Das Datum ist gewünscht, bis die Marktantwort es bestätigt."
      },
      "Kuendigungsantwort": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "vorgang_id": {
            "type": "string"
          },
          "entscheidung": {
            "type": "string",
            "enum": [
              "bestaetigen",
              "ablehnen"
            ]
          },
          "begruendung": {
            "type": "string",
            "maxLength": 2000
          },
          "bindungsende": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date",
            "nullable": true
          },
          "ablehnung_code": {
            "type": "string",
            "enum": [
              "A01",
              "A04",
              "A05",
              "A06",
              "A08",
              "A10",
              "A13",
              "A14",
              "A15",
              "A16",
              "A18",
              "A99"
            ]
          }
        },
        "required": [
          "vorgang_id",
          "entscheidung"
        ],
        "description": "Antwort auf einen konkreten eingegangenen Vorgang, unter Beachtung seiner Frist. Ablehnung benötigt eine Begründung."
      },
      "Storno": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "begruendung": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "Bearbeitungsauftrag": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "eingegangen_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "eingegangen",
              "in_bearbeitung",
              "klaerung_erforderlich",
              "ausgefuehrt",
              "abgelehnt"
            ]
          },
          "code": {
            "type": "string",
            "nullable": true
          },
          "hinweis": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "eingegangen_am",
          "status"
        ]
      },
      "Messwert": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "obis": {
            "type": "string",
            "maxLength": 40
          },
          "wert": {
            "type": "number"
          },
          "einheit": {
            "type": "string",
            "enum": [
              "kWh",
              "m3"
            ]
          }
        },
        "required": [
          "obis",
          "wert",
          "einheit"
        ]
      },
      "ZaehlerstandEingang": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "uebermittlung_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "malo": {
            "type": "string",
            "pattern": "^[0-9]{11}$",
            "nullable": true
          },
          "melo": {
            "type": "string",
            "maxLength": 33,
            "nullable": true
          },
          "zaehlernummer": {
            "type": "string",
            "maxLength": 100,
            "nullable": true
          },
          "ablesedatum": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date"
          },
          "herkunft": {
            "type": "string",
            "enum": [
              "trawa",
              "kunde",
              "ersatzwert"
            ]
          },
          "ablesegrund": {
            "type": "string",
            "description": "Fachlicher Ablesegrund."
          },
          "messwerte": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Messwert"
            },
            "minItems": 1,
            "maxItems": 10
          }
        },
        "required": [
          "uebermittlung_id",
          "ablesedatum",
          "herkunft",
          "ablesegrund",
          "messwerte"
        ],
        "description": "Mindestens ein Identifikator erforderlich; mehrere Angaben müssen dasselbe Gerät identifizieren. MSB-Herkunft wird ausschließlich aus authentisierten Markteingängen übernommen, nicht frei behauptet."
      },
      "ZaehlerstandQuittung": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "uebermittlung_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "eingegangen_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "eingegangen",
              "in_pruefung",
              "uebernommen",
              "klaerung_erforderlich",
              "abgelehnt"
            ]
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "ersetzt_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid",
            "nullable": true
          },
          "freigegebener_wert_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid",
            "nullable": true
          }
        },
        "required": [
          "id",
          "uebermittlung_id",
          "eingegangen_am",
          "status",
          "version"
        ],
        "description": "Eingang bestätigt keine Plausibilität und keine Übernahme nach XAP."
      },
      "Zaehlerstand": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "malo": {
            "type": "string",
            "nullable": true
          },
          "melo": {
            "type": "string",
            "nullable": true
          },
          "zaehlernummer": {
            "type": "string",
            "nullable": true
          },
          "ablesedatum": {
            "type": "string",
            "description": "Fachliches Datum, YYYY-MM-DD.",
            "format": "date"
          },
          "herkunft": {
            "type": "string",
            "enum": [
              "msb",
              "kunde",
              "trawa",
              "ersatzwert",
              "unbekannt"
            ]
          },
          "ablesegrund": {
            "type": "string",
            "nullable": true
          },
          "messwerte": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Messwert"
            }
          },
          "plausibilitaetsstatus": {
            "type": "string",
            "enum": [
              "plausibel",
              "unplausibel_freigegeben",
              "ungeprueft_freigegeben"
            ]
          },
          "freigegeben_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time",
            "nullable": true
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "ersetzt_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid",
            "nullable": true
          },
          "versionsbasis": {
            "type": "string",
            "enum": [
              "beobachtung_seit_api"
            ]
          },
          "wertarten": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "enum": [
                "zaehlerstand",
                "rueckstellwert",
                "verbrauch"
              ]
            },
            "description": "Einordnung je OBIS aus explizitem Verbrauchskennzeichen bzw. XAP-Rückstellkennzeichen. Bei älteren archivierten Versionen eventuell nicht vorhanden."
          },
          "wandlerfaktoren": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "nullable": true
            },
            "description": "Hinterlegter Faktor je OBIS. Die API multipliziert oder glättet die unveränderten XAP-Rohwerte nicht."
          },
          "quellreferenzen": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "nullable": true
            },
            "description": "Stabile Referenz auf den ursprünglichen XAP-Ablesesatz je OBIS zur Prüfung durch solvit."
          }
        },
        "required": [
          "id",
          "ablesedatum",
          "herkunft",
          "messwerte",
          "plausibilitaetsstatus",
          "version"
        ],
        "description": "Nur fachlich freigegebene Werte. Unplausible Eingänge vor Entscheidung fehlen auch in GET-Antworten. Versionen zählen Beobachtungen seit Einführung der API; die erste Beobachtung ist Version 1. Historische Herkunft ist ohne Beleg unbekannt."
      },
      "ZaehlerstandSeite": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "daten": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Zaehlerstand"
            }
          },
          "naechster_cursor": {
            "type": "string",
            "nullable": true
          },
          "mengen_und_rueckstellwerte": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Zaehlerstand"
            },
            "description": "Messwertsätze mit wenigstens einem Verbrauchs- oder Rückstellkanal; nicht als fortlaufende Zählerstände behandeln. Auch bei gemischten Geräten bleiben alle Kanäle erhalten, ihre Einordnung steht in wertarten. Ohne belegten Zeitraum wird kein Verbrauchszeitraum erfunden."
          }
        },
        "required": [
          "daten",
          "mengen_und_rueckstellwerte"
        ]
      },
      "ZaehlerstandKorrektur": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "uebermittlung_id": {
            "type": "string",
            "description": "Vom Absender vergebene UUID in kanonischer Kleinschreibung; unverändert und vollständig gespeichert.",
            "format": "uuid"
          },
          "messwerte": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Messwert"
            },
            "minItems": 1,
            "maxItems": 10
          },
          "begruendung": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          }
        },
        "required": [
          "uebermittlung_id",
          "messwerte",
          "begruendung"
        ],
        "description": "id bezeichnet die freigegebene Version aus GET /zaehlerstaende/werte/{id}, nicht die Eingangsquittung. Idempotency-Key entspricht uebermittlung_id; If-Match übernimmt ETag dieses Einzelabrufs. Eine neue Version entsteht erst nach fachlicher Freigabe. Alte Versionen bleiben abrufbar. MSB-/Altdatenwerte benötigen solvit-Prüfung; Abrechnungs- und Plausibilitätsprüfungen bleiben wirksam."
      },
      "Webhook": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "zustellung_id": {
            "type": "string",
            "description": "Interne, von der API vergebene Kennung.",
            "format": "uuid"
          },
          "typ": {
            "type": "string",
            "enum": [
              "status.geaendert"
            ]
          },
          "erstellt_am": {
            "type": "string",
            "description": "Zeitpunkt nach RFC 3339 mit Zeitzone.",
            "format": "date-time"
          },
          "ereignis": {
            "type": "object",
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/Ereignis"
              }
            ]
          },
          "status": {
            "$ref": "#/components/schemas/Vertragsstatus"
          }
        },
        "required": [
          "zustellung_id",
          "typ",
          "erstellt_am",
          "ereignis",
          "status"
        ]
      }
    }
  }
}
