Zum Inhalt

Plattform-Architektur

Die ZEDAL-Plattform exponiert ihre Funktionalität als Familie von gRPC-Services. Integratoren erreichen sie auf drei Wegen: SDK, REST/JSON und gRPC direkt. Alle drei führen auf dieselbe Funktionalität zusammen, weil die .proto-Definitionen die einzige Wahrheitsquelle sind, aus der sich SDK, REST-Fassade und OpenAPI-Dokument ableiten.

Überblick

flowchart TB
    subgraph integ["Integrator-Seite"]
        APP["Anwendung<br/>Backend / Mobile / Web"]
    end

    subgraph edge["ZEDAL-Edge"]
        SDK[".NET SDK<br/>Zedal.Sdk"]
        REST["REST / JSON + gRPC-Web<br/>openapi.*.zedal.de"]
        GRPC[("gRPC-Endpunkt<br/>api.*.zedal.de")]
    end

    subgraph backend["Backend-Services"]
        CORE["Core<br/>Auth, Dokumente, Akten"]
        BXA["BxA-Dokumente<br/>Company / Authority"]
        DiWaSS["DiWaSS-Anbindung<br/>Retrieval, Attachment,<br/>Operator, Authority"]
        SIGNER["Signer<br/>VerifyApi"]
        DISC["DiscoveryApi"]
        TRANS["TransformApi"]
    end

    subgraph ext["Externe Systeme"]
        EU["EU DiWaSS<br/>Zentralsystem"]
    end

    APP --> SDK
    APP --> REST
    APP --> GRPC
    SDK --> GRPC
    REST --> GRPC
    GRPC --> CORE
    GRPC --> BXA
    GRPC --> SIGNER
    GRPC --> DiWaSS
    GRPC --> DISC
    GRPC --> TRANS
    DiWaSS -.->|serverseitig vermittelt| EU

Drei Zugriffswege

Welcher Weg passt, hängt von Sprache, Integrationsstil und davon ab, ob du Streaming brauchst.

1. Offizielles SDK

Wann: wenn deine Anwendung in einer Sprache mit verfügbarem SDK gebaut ist. Aktuell: .NET / C# — NuGet-Paket Zedal.Sdk, versioniert nach Semantic Versioning.

Das SDK kapselt gRPC, übernimmt Authentifizierung samt Token-Erneuerung und bietet für die DiWaSS-Dokumente eigene Document-Handler statt roher Request-Messages. Empfehlung für die meisten Integrationen.

Über die reine Protokoll-Kapselung hinaus gibt es Bausteine, die es auf dem gRPC- oder REST-Pfad nicht gibt und die du sonst selbst bauen müsstest:

Baustein Was er leistet
Document-Handler (client.DocumentHandler) Notifizierung, Movement, Annex VII und die Behördensicht als Objekte mit Stage-Methoden und Followup-Intents
Inbox-Importer (CreateInboxImporter()) Übernahme eingehender Dokumentversionen in den lokalen Bestand — siehe Aufrufe und Synchronisation
Token-Erneuerung Der mitgelieferte DefaultTokenRefresher erneuert das Access-Token, sobald weniger als 5 Minuten Restlaufzeit bleiben. Er prüft nur die Ablaufzeit — entzogene oder gesperrte Zugänge behandelt er nicht; dafür brauchst du eine eigene IJwtTokenRefresh-Implementierung
client.MyAccount Die eigenen DiWaSS-Operator-IDs und BMU-ZKS-Nummern des angemeldeten Nutzers

2. REST / JSON

Wann: wenn du in einer Sprache ohne offizielles SDK arbeitest oder REST-Tooling bevorzugst. Status: produktiv. Details, Aufrufform und Codegenerierung: API-Referenz → REST.

Die REST-Routen und das OpenAPI-Dokument werden zur Laufzeit aus den gRPC-Definitionen abgeleitet. Daraus folgt:

  • Kein Codegen-Schritt, kein Versionsversatz. Das OpenAPI-Dokument beschreibt exakt das, was der laufende Service kann. Deshalb ist die Referenz immer aktuell.
  • Die Pfade sind RPC-förmig, nicht ressourcenorientiert: <VERB> /<service.FullName>/<Methode>.
  • Das Verb kommt aus der google.api.http-Annotation. Es ist nicht immer POST; auch GET, PATCH, DELETE und PUT kommen vor.
  • Eine Methode ohne HTTP-Annotation hat keine REST-Route. Es gibt gRPC-Methoden, die über REST nicht erreichbar sind — siehe die Spalte „REST” in der Tabelle unten.
  • Die Referenz-Oberfläche ist Scalar, das Dokument ist OpenAPI 3.0.3.

REST/JSON ist unary — kein Server-Streaming

Eine Anfrage, eine Antwort. Server-Streaming steht über REST nicht zur Verfügung, auch nicht als Server-Sent Events. Wer Streaming braucht, nimmt natives gRPC oder gRPC-Web über denselben openapi.*-Host; dort werden Streaming-Antworten inkrementell ausgeliefert.

3. gRPC direkt

Wann: wenn du Streaming brauchst, geringe Latenz willst oder in deiner Sprache aus den Protos selbst generieren möchtest.

Der native gRPC-Endpunkt liegt auf dem api.*-Host und bietet die vollständige Oberfläche — einschließlich der Methoden ohne REST-Route. Siehe API-Referenz → gRPC.

Umgebungen

Die beiden Hosts pro Umgebung sind getrennt: natives gRPC auf api.*, REST/JSON und gRPC-Web auf openapi.*.

Umgebung nativ gRPC REST/JSON + gRPC-Web
Production api.live.zedal.de openapi.live.zedal.de
Preview api.preview.zedal.de openapi.preview.zedal.de
Test api.test.zedal.de openapi.test.zedal.de

Provider-IDs sind umgebungsspezifisch

Eine Provider-ID aus der Produktion gilt nicht auf Test und umgekehrt. Auf dem REST-Pfad ist der Header provider_id bei jedem Aufruf Pflicht — auch beim Login. Eine falsche oder fehlende ID gibt dieselbe, irreführende 501-Antwort. Details in REST / JSON und Erste Schritte.

Services

Hinter dem gRPC-Endpunkt liegen mehrere thematische Services. Das SDK bündelt sie unter der IZedalClient-Fassade; über REST und gRPC sprichst du sie unter ihrem vollqualifizierten Namen an.

Die Spalte REST nennt, wie viele Methoden des Service über REST/JSON erreichbar sind. Der Zähler stammt aus dem OpenAPI-Dokument des laufenden Systems, der Nenner aus den Proto-Definitionen.

SDK-Pfad gRPC-Service REST Zuständigkeit
CoreApi.Auth core.v1.api.AuthApi 8 / 8 Refresh-/Access-Token, Sessions, Passwortwechsel
CoreApi.Documents core.v1.api.DocumentApi 20 / 32 Dokumente und Parameter lesen, Inbox, Import aus der Inbox, Versand und Quittierung
CoreApi.File core.v1.api.FileApi 13 / 23 Akten und Einreichungen im Nachweis-Bereich
CoreApi.Templates core.v1.api.DocumentTemplateApi 4 / 6 Muster für Versandpapiere und Akten
CoreApi.MasterData core.v1.api.MasterdataApi 1 / 2 Adressstammdaten
CoreApi.Common core.v1.api.CommonApi 2 / 3 Globale Parameter
CoreApi.Query core.preview.api.PreviewApi 2 / 8 Übersichtslisten über Dokumente, Akten und Muster. Experimentell — Namen und Zuschnitt können sich ändern
— core.v1.api.QueryApi 3 / 5 Übersichtslisten über Transportdokumente, Eingang, Akten-Dokumente, Akten und Muster. Ohne REST-Route: ListFileAreaDocuments, ListFiles
BxaApi.CompanyDocumentApi bxa.diwass.v1.api.CompanyDocumentApi 23 / 23 Unternehmensseite der DiWaSS-Dokumente: Notifizierung, Movement, Annex VII anlegen und Stages setzen
BxaApi.AuthorityDocumentApi bxa.diwass.v1.api.AuthorityDocumentApi 9 / 9 Behördenseite: Entscheidung, Nachforderung, Signale, Rücknahme
BxaApi.BmuDocumentApi bxa.bmu.v1.api.BmuDocumentApi 6 / 6 BMU-Begleit- und Übernahmescheine: anlegen, Layer anhängen, Felder setzen, Signaturstellen; siehe BMU-Anleitung
DiwassApi.RetrievalApi diwass.v1.api.RetrievalApi 4 / 4 Ereignisliste und Abgleich — siehe Aufrufe und Synchronisation
DiwassApi.AttachmentApi diwass.v1.api.AttachmentApi 2 / 2 Anhänge einreichen und abrufen
DiwassApi.OperatorApi diwass.v1.api.OperatorApi 2 / 2 Operator-Verzeichnis: Suche und Einzelabruf
DiwassApi.AuthorityDirectoryApi diwass.v1.api.AuthorityApi 4 / 4 Behördenverzeichnis: Suche nach Tätigkeit, Einzelabruf, Änderungsstand
DiwassApi.SoapProxyApi — keine Durchreichen eines rohen SOAP-Bodys an DiWaSS
DiscoveryApi provider_discovery.v1.api.DiscoveryApi 1 / 1 Provider-Verzeichnis. ListProvider ist die einzige Operation ohne Token und ohne provider_id — damit Schritt 0 jeder Integration
TransformApi — keine Erzeugt aus der nativen Dokumentdarstellung eine grafische, insbesondere PDF (ToPdf)
SignerApi.VerifyApi signer.v2.api.VerifyApi 4 / 4 Prüfung von Zertifikaten und Signaturen (VerifyCert, VerifyP7, VerifyPdf, VerifyXml)

Wo REST hinter gRPC zurückbleibt

Eine gRPC-Methode ohne google.api.http-Annotation bekommt keine REST-Route. Das trifft nicht nur Randfälle:

Fehlt über REST Warum es weh tut
DocumentApi.ImportTransportDocumentFromInbox, ImportDocumentToFileAreaFromInbox Genau der Schritt, mit dem eingehende Dokumentversionen in den lokalen Bestand gelangen — siehe Aufrufe und Synchronisation
DocumentApi.SendDocument, DeliverDocument Versand im ZEDAL-Verteilweg
FileApi.CreateNewFile, GrantAccessToFile, MergeFiles, MoveDocumentToFile Aktenverwaltung im Nachweis-Bereich
PreviewApi.ListTransportDocuments, ListFiles, ListFileAreaDocuments, ListInboxDocuments; QueryApi.ListFiles, ListFileAreaDocuments Akten und Nachweis-Bereich lassen sich über REST nicht auflisten. Bestand, Eingang und Muster listet über REST die QueryApi (ListTransportDocuments, ListInboxDocuments, ListTransportTemplates)

Wenn du eine reine REST-Integration planst, prüfe früh, ob dein Ablauf ohne diese Operationen auskommt — das ist eine Architekturentscheidung, keine Detailfrage. Verbindlich ist immer das OpenAPI-Dokument des laufenden Systems: Was dort steht, ist über REST erreichbar; was fehlt, nicht.

Externe Anbindungen

Die DiWaSS-Services vermitteln serverseitig an das EU-DiWaSS-Zentralsystem und kapseln dabei Transport und Format-Konvertierung. Aus Integrator-Sicht ist diese Vermittlung Implementierungsdetail — du arbeitest gegen die ZEDAL-API.

Was nicht gekapselt ist: Betriebsregeln und Laufzeit

Zwei Dinge dringen durch die Kapselung durch, und beide muss deine Anwendung tragen:

  • Die Europäische Kommission verlangt sequenzielle Aufrufe gegen DiWaSS und behält sich bei fortgesetztem Verstoß die Sperrung des API-Zugangs vor.
  • Antworten kommen asynchron und langsam. Fremd-Updates erscheinen erst nach etwa zwei bis drei Minuten im ZEDAL-Bestand; der Client-Default-Timeout des SDK von 30 Sekunden reicht für DiWaSS-Pfade nicht.

Beides steht ausführlich unter Aufrufe und Synchronisation.

Single Source of Truth

Die .proto-Definitionen sind der Ausgangspunkt für alles: Änderungen an der API erfolgen auf Proto-Ebene. Für Integratoren heißt das:

  • gRPC ist die vollständige Oberfläche. REST ist eine Projektion darauf und deckt sie fast, aber nicht vollständig ab.
  • Das OpenAPI-Dokument entsteht zur Laufzeit aus den gRPC-Definitionen und beschreibt damit immer den laufenden Stand.
  • Versionierung des .NET-SDK folgt Semantic Versioning (Zedal.Sdk).

Deprecations schlagen nicht in jeden Zugriffsweg durch

Veraltete Operationen sind in den Protos mit deprecated markiert und im SDK als [Obsolete] sichtbar. Im laufenden OpenAPI-Dokument ist derzeit keine Operation als deprecated gekennzeichnet — verlass dich für die Abkündigung also nicht auf die REST-Referenz allein. Maßgeblich sind die Release-Notes des SDK und die Proto-Definitionen.

Wo es weitergeht