Ein durchgängiger Ablauf für Systeme von Kostenträgern. Versicherte reichen Rechnungen bei ihrem Kostenträger ein; im aktuellen Stand geschieht das außerhalb des Fachdienstes, per Post mit DataMatrix-Code oder digital über die App der Versicherten. Der Fachdienst dient dem Kostenträger dazu, zu einem Token die Rechnungsdaten abzurufen
Alle folgenden Aufrufe auf die einzelnen APIs benötigen von den ZETA-Komponenten des Fachdienstes ausgestellte Access Tokens. Damit diese ausgestellt, werden muss sich das rechnungserstellende System beim Fachdienst registrieren:
Unter ZETA-Client ist am Beispiel der Java-Plattform ein vollständiger Zugriff auf den Fachdienst über ZETA gezeigt.
Für den Abruf per Token benötigt der Kostenträger ein Konto im Fachdienst. Durch das Anlegen stimmt die Kostenträger-Institution der Verwendung von Telematik-ID und Name des Kostenträgers durch den Fachdienst zu. (Dadurch können versicherte Personen sehen, welche Kostenträger-Institution Rechnungsdaten vom Fachdienst abgerufen hat). Telematik-ID und Anzeigename entnimmt der Fachdienst dem Zertifikat/Token, es wird nicht im HTTP Body übergeben.
POST https://dev.digitale-patientenrechnung.de/api/InsuranceAccount HTTP/1.1 { |
Antwort bei Erfolg: HTTP-Status 201 Created.
Existiert das Konto schon: HTTP-Status 409.
Ohne Konto ist kein Abruf von Rechnungsdaten möglich.
Weitere Details zu diesem Aufruf finden sich in OpenAPI-Beschreibung unter Entwicklungs-Tools
Benötigte Scopes für das Anlegen eines Kostenträger-Accounts: "dipag insuranceAccount.crud" |
Ein Token identifiziert genau ein Dokument (Rechnung oder Anhang). Das Token ist ein zufälliger, 64-stelliger Hex-Wert ohne personenbezogene Daten. Kostenträger erhalten es auf einem von 2 Wegen:
urn:dipag:rechnung:v1:988b8d318ba20bfa7da4a19a91a184e7b32fcb73f0c052478e6797b84ed8ab01
Das Kostenträger-System ruft mit dem Token die Operation $retrieve auf. Im Body des POST - Request kann über drei Flags das gewünschte Format gewählt werden, was direkt zurückgegeben werden soll:
| Flag | Ergebnis |
|---|---|
| angereichertes PDF/A-3 | |
| strukturierterRechnungsinhalt | strukturierte Rechnungsdaten (FHIR-Bundle als Binary) |
| originaleRechnung | Original-PDF |
POST https://dev.digitale-patientenrechnung.de/fhir/DocumentReference/$retrieve HTTP/1.1 { |
Bei Erfolg: Antwort HTTP-Status 200 OK. In der Antwort sind neben dem angeforderten Format auch einige strukturierte Daten aus der Rechnung enthalten:
Dazu sind unabhängig vom gesetzten Parameter die FHIR-Binary-URLs enthalten, unter denen jedes Rechnungsformat einzeln abgerufen werden kann.
Beispiel-Antwort (gekürzt), wenn nur das angereicherte PDF angefordert wird. Die URLs zu allen drei Rechnungsformaten sind in der Antwort enthalten, aber das angereicherte PDF ist zusätzlich direkt eingebettet.
{ |
Nach erfolgreichem Aufruf der $retrieve-Operation wird die Rechnung im Fachdienst markiert. Die versicherte Person kann dann, je nach Ausgestaltung ihrer App, einen Hinweis auf der Rechnung sehen: "abgerufen durch <Kostenträger>".
Benötigte Scopes für das Abrufen von Rechnungsobjekten mit einem Token: "dipag invoiceDoc.r" |
Die strukturierten Daten sind ein FHIR-Bundle (collection) mit einer Rechnung (Invoice), den Positionen (ChargeItem), Patient, behandelnder Person und Rechnungsersteller.
Details zum Rechnungsformat: Das Rechnungsformat - MVP.
Es ist sichergestellt, dass die auf diesem Weg bezogenen Rechnungsdaten nicht manipuliert wurden und auch wirklich vom Rechnungs-Fachdienst stammen. Das wird durch die zentrale "Vertrauenswürdige Ausführungsumgebung" im Fachdienst erreicht und durch den vertrauenswürdigen Kanal, den das Kostenträger-System über ZETA zu dieser Ausführungsumgebung aufbaut. Für nähere Detail siehe: https://gemspec.gematik.de/docs/gemSpec/gemSpec_DiPag_FD/latest/#5.1.3 und auch https://gemspec.gematik.de/docs/gemSpec/gemSpec_ZETA/latest/ |
Eine Institution kann ihr Konto löschen. Der Aufruf braucht die eigene Telematik-ID im Pfad, sie muss zu der im Token übereinstimmen.
| DELETE https://dev.digitale-patientenrechnung.de/api/PractitionerAccount/> HTTP/1.1 |
Antwort bei Erfolg: 204: No Content;
Antwort 404, wenn es kein Konto gibt.
Das Löschen des Institutskontos führt nicht zum Löschen der Markierungen (siehe Schritt 5)
Weitere Details zu diesem Aufruf finden sich in OpenAPI-Beschreibung unter Entwicklungs-Tools
Benötigte Scopes für das Löschen eines Kostenträger-Accounts: "dipag insuranceAccount.crud" |
Kostenträger müssen im MVP der Digitalen Patientenrechnung nicht zwingend am Fachdienst "angeschlossen" sein, um strukturierte und validierte Rechnungsdaten verarbeiten zu können. Rechnungen, die Versicherte über ihre Apps aus dem Fachdienst herunterladen, können auch auf anderen Wegen zum Kostenträger gelangen. ("Teilen"-Funktion in einer App, Upload in einem existierenden Webportal beim Kostenträger, ....)
Der Fachdienst Digitale Patientenrechnung bettet daher die vom Rechnungsersteller übermittelten strukturierten Daten in das angereicherte PDF ein. Dadurch können Kostenträger-Systeme, die nur das angereicherte PDF erhalten, dennoch automatisiert auf die vom Fachdienst validierten Rechnungsdaten zugreifen.

Die Rechnungsinhalte im PDF sind in "Das Rechnungsformat - MVP" beschrieben. Der Mime-Type der Strukturierten Daten wird an dieser Stelle immer `application/fhir+json` sein.
Der Anhang im PDF heißt "strukturierterRechnungsinhalt.json".
Am Beispiel der Java-Libraries "gson" und "pdfbox" könnte das Auslesen der Strukturierten Rechnungsdaten (hier: Rechnungsdatum und Betrag) so implementiert werden (kompletter Source Code unter Entwicklungs-Tools):
static final String ANHANG = "strukturierterRechnungsinhalt.json";
String json = leseAnhang(new File("angereicherteRechnung.pdf));
JsonObject invoice = findeInvoice(JsonParser.parseString(json).getAsJsonObject());
LocalDate datum = LocalDate.parse(invoice.get("date").getAsString());
// Gesamtbetrag: Invoice.totalGross
JsonObject total = invoice.getAsJsonObject("totalGross");
BigDecimal betrag = total.get("value").getAsBigDecimal();
System.out.println("Rechnungsdatum: " + datum.format(DateTimeFormatter.ofPattern("dd.MM.yyyy")));
System.out.println("Gesamtbetrag: " + betrag.setScale(2) + " " + total.get("currency").getAsString());
static String leseAnhang(File pdf) throws Exception {
try (PDDocument doc = PDDocument.load(pdf)) {
PDEmbeddedFilesNameTreeNode anhaenge = doc.getDocumentCatalog().getNames().getEmbeddedFiles();
PDComplexFileSpecification datei = (PDComplexFileSpecification) anhaenge.getValue(ANHANG);
return new String(datei.getEmbeddedFile().getByteArray(), StandardCharsets.UTF_8);
}
}
static JsonObject findeInvoice(JsonObject bundle) {
for (JsonElement entry : bundle.getAsJsonArray("entry")) {
JsonObject res = entry.getAsJsonObject().getAsJsonObject("resource");
if ("Invoice".equals(res.get("resourceType").getAsString())) {
return res;
}
}
throw new IllegalArgumentException("Keine Invoice-Ressource im Bundle gefunden");
}
}
|
Rechnungen, die nicht direkt vom Fachdienst bezogen werden, könnten auf dem Weg zum Kostenträger manipuliert werden. Aus diesem Grund sind alle Rechnungen, die aus dem Fachdienst Digitale Patientenrechnung stammen, mit einer Signatur versehen. Kostenträger können somit die Integrität und Authentizität der erhaltenen Rechnungsobjekte selbst verifizieren.
Das Signatur-Feature befindet sich derzeit noch in Entwicklung, es wird in den kommenden Wochen in den Testumgebungen zur Verfügung gestellt. Nach Abschluss der Implementierung wird hier ein Beispiel für die Signaturprüfung zur Verfügung gestellt. |