Zum Inhalt

Schnittstelle (API)

Andere Programme – ein Scanner, ein Skript, eine Haushalts-App – greifen über die Schnittstelle unter /api/v1 auf das DMS zu. Sie können Mappen anlegen, lesen, ändern und löschen und Dokumente hoch- und herunterladen.

API-Beschreibung

Die vollständige Beschreibung im OpenAPI-Format (Version 3.1):

  • Lesbar in jeder Installation unter Profil → Sicherheit → API-Schlüssel über den Link API-Dokumentation – passend zur installierten Version.
  • Maschinenlesbar unter /api/openapi.json oder /api/v1/openapi.json der eigenen Installation, z. B. http://<NAS>:8080/api/openapi.json. Das lässt sich in Werkzeuge wie Swagger UI, Postman oder einen Code-Generator laden.
  • Die Beschreibung der aktuellen Version liegt auch hier: openapi.json.

API-Dokumentation im DMS

API-Schlüssel

Jeder Benutzer erzeugt seine Schlüssel selbst unter Profil → Sicherheit → API-Schlüssel, höchstens 50 je Benutzer – außer Administratoren (ab 0.26): Über die Schnittstelle arbeitet immer ein normaler Benutzer. Lege für ein Programm am besten einen eigenen Benutzer an (z. B. „Scanner“), melde dich als dieser an und erzeuge den Schlüssel dort. Schlüssel, die Administratoren schon vorher hatten, funktionieren weiter; die Werkbank-Übersicht erinnert daran, sie so zu ersetzen.

  • Name – wofür der Schlüssel ist, z. B. „Scanner Arbeitszimmer“.
  • Recht (Stufe) – eine von dreien:
    • nur lesen – liest alles, was der Benutzer lesen darf (nur GET).
    • lesen und schreiben – liest und ändert alles, was der Benutzer darf.
    • nur Zähler (ab #625) – ruft nur die Zahlen ab (GET /api/v1/ich/zaehler): neue Post, Zu erledigen, anstehende und überfällige Fristen. Jeder andere Aufruf, auch das Laufwerk, bekommt 403. Gedacht für Hausautomatisierung, Wand-Tablets und Anzeigen: Geht der Schlüssel verloren, erfährt jemand höchstens, wie viel Post und Aufgaben der Benutzer hat – keine Titel, Namen oder Inhalte. „Passwörter lesen“ gibt es für diese Stufe nicht.
  • Ablaufdatum – optional.
  • Passwörter lesen – eigenes Recht für Passwortfelder: Nur damit liefert GET /api/v1/mappen…?passwoerter=anzeigen sie im Klartext; jeder Abruf steht im Protokoll. Ohne den Parameter steht dort immer nur {"gesetzt": true, "lesbar": true}.

Der Schlüssel ist nur einmal vollständig sichtbar, direkt nach dem Erzeugen; danach zeigt das DMS nur noch seinen Anfang. Gespeichert wird nur ein Prüfwert. Wer ihn verliert, erzeugt einen neuen und löscht den alten.

Ein Schlüssel hat höchstens die Rechte seines Benutzers. Ist der Benutzer deaktiviert, gilt auch sein Schlüssel nicht mehr.

Die Endpunkte der Gruppe Werkbank (Mappentypen anlegen, ändern und löschen; Benutzer und Rollen) brauchen Administratorrechte. Mit dem Schlüssel eines Mitglieds antworten sie mit 403. Da Administratoren keine neuen Schlüssel bekommen, gehen sie nur mit einem Schlüssel, der einem Administrator schon vor 0.26 gehörte.

Erster Aufruf

curl -H "Authorization: Bearer dms_…" http://<NAS>:8080/api/v1/ich

Antwortet mit dem Benutzer und dem Recht des Schlüssels.

Eine Mappe anlegen:

curl -X POST -H "Authorization: Bearer dms_…" -H "Content-Type: application/json" \
  -d '{"typId": "<Id des Mappentyps>", "werte": {"rechnungsnummer": "R-17", "rechnungsdatum": "2026-10-01", "betrag": {"betrag": 49.9, "waehrung": "EUR"}}}' \
  http://<NAS>:8080/api/v1/mappen

Die Ids der Mappentypen und die Kennungen ihrer Felder (key) liefert GET /api/v1/typen.

Zähler: nur Zahlen, für Hausautomatisierung und Anzeigen

GET /api/v1/ich/zaehler liefert nur Zahlen für den Benutzer des Schlüssels, in dessen Berechtigungen – ohne Titel, Namen, Absender oder Inhalte. Dafür genügt ein Schlüssel der Stufe nur Zähler; nur lesen und lesen und schreiben dürfen ihn ebenfalls. Ein Administrator ruft ihn mit seiner Anmeldung im Browser ab (Administratoren bekommen keine Schlüssel).

curl -i -H "Authorization: Bearer dms_…" https://dms.example.org/api/v1/ich/zaehler
HTTP/1.1 200 OK
ETag: "z42-mJ3x0Qe7Kq9VZ1aB2cD3eF"
Cache-Control: private, no-cache
Content-Type: application/json; charset=utf-8

{"neuePost":2,"zuErledigen":5,"anstehend":3,"ueberfaellig":1,"stand":42,"geaendert":"2026-11-03T07:15:00.000Z"}
Feld Bedeutung
neuePost Post im Stand Neu, deren Für der Benutzer ist oder leer ist – nur Post, die er lesen darf
zuErledigen wie Zu erledigen in der Ablage: Mappen mit offenen Aufgaben für ihn
anstehend Fristen, Erinnerungen und Aufgaben mit Datum von heute bis in 7 Tagen (wie Anstehend)
ueberfaellig offene Fristen, Erinnerungen und Aufgaben mit Datum vor heute
stand zählt um eins hoch, sobald sich eine der Zahlen gegenüber dem letzten Abruf geändert hat
geaendert wann das DMS diese Änderung bemerkt hat (beim Abruf)

Nichts Neues kostet nichts: Schicke das ETag des letzten Abrufs als If-None-Match mit. Hat sich nichts geändert, antwortet das DMS mit 304 Not Modified ohne Inhalt:

curl -i -H "Authorization: Bearer dms_…" -H 'If-None-Match: "z42-mJ3x0Qe7Kq9VZ1aB2cD3eF"' \
  https://dms.example.org/api/v1/ich/zaehler
# HTTP/1.1 304 Not Modified
  • Die Zahlen kommen aus demselben Zwischenspeicher wie die Zahlen der Ablage: Auch bei 50.000 Mappen ist ein Abruf meist in wenigen Millisekunden beantwortet. Alle paar Minuten abzufragen (z. B. alle 5 Minuten) ist unbedenklich.
  • Der Stand liegt in der Datenbank: Er übersteht einen Neustart. Nach einer Wiederherstellung kann er auf den Stand der Sicherung zurückgehen – vergleiche ihn deshalb nur auf „anders“, nicht auf „größer“.
  • Andere Aufrufe mit einem Schlüssel nur Zähler bekommen 403 mit dem Hinweis, dass dieser Schlüssel nur die Zahlen abruft.

Sofort statt abfragen: Webhooks

Statt den Zähler regelmäßig abzufragen, kann sich das DMS auch selbst melden: Ein Webhook schickt dieselben Zahlen per POST an eine Adresse, wenige Sekunden nachdem sie sich geändert haben – signiert mit HMAC-SHA256, ohne Inhalte, mit Ereignis-Id gegen Doppeltes. Benutzer legen Webhooks im Profil an, nur an Ziele, die ein Administrator freigegeben hat. Einrichten, Zustellung und Köpfe: Webhooks; Prüfen der Signatur mit Beispielcode im Entwicklerhandbuch. Den Zähler-Endpunkt braucht es weiterhin: zum Start, nach längerer Pause und als Rückfall, falls eine Meldung verloren ging.

Mappe ändern, auch gleichzeitig mit anderen

PUT /api/v1/mappen/{id} ändert nur die Felder, die in werte stehen; alle anderen bleiben, wie sie gerade gespeichert sind. Schicke deshalb nur, was du ändern willst – nicht die ganze Mappe, die du vorher gelesen hast. Sonst setzt du Felder zurück, die inzwischen jemand anderes geändert hat.

Mit stand prüft das DMS zusätzlich, ob seit deinem Lesen jemand dasselbe Feld geändert hat (#609). stand ist der Wert geaendert der Mappe aus GET /api/v1/mappen/{id}:

curl -X PUT -H "Authorization: Bearer dms_…" -H "Content-Type: application/json" \
  -d '{"werte": {"betrag": {"betrag": 398, "waehrung": "EUR"}}, "stand": "2026-11-02T16:58:12.345Z"}' \
  http://<NAS>:8080/api/v1/mappen/<Id>
  • Hat seitdem niemand eines der übergebenen Felder anders geändert, speichert das DMS – auch wenn andere Felder inzwischen geändert wurden; die bleiben.
  • Sonst kommt 409 und nichts wird gespeichert. In details stehen stand (der aktuelle) und konflikte: je Feld feld, label, deins, aktuell (lesbar), wert (der jetzige Wert wie in werte; nicht bei Passwörtern), von, name und zeit der letzten Änderung.
  • Deinen Wert trotzdem übernehmen: dieselbe Anfrage mit stand aus der 409-Antwort. Den anderen Wert behalten: das Feld weglassen.

Ohne stand prüft das DMS nichts – wie bis 0.143.0 gilt, was du schickst. Bestehende Skripte laufen unverändert weiter; nicht übergebene Felder setzt das DMS nie zurück. „Zuletzt geändert“ (geaendert) ist auf die Millisekunde genau und wird bei jedem Speichern größer – vergleiche es als Text, rechne nicht damit.

Namen in der API

Die Schnittstelle behält ihre Namen, auch wo die Oberfläche seit 0.73 andere Wörter verwendet: sicht ist die Ansicht, sicht=eingang die Liste Zu erledigen, key die Kennung eines Felds, Registers oder Mappentyps, die Feldart referenz der Verweis, das Register der Art protokoll die Historie und mandant bzw. haushalt_id der Haushalt.

Die Mappen einer Ansicht liefert GET /api/v1/mappen?sicht=<Id der Ansicht> – mit allen Bedingungen der Ansicht. Alle Mappen eines Mappentyps, ohne Bedingungen, gibt es mit sicht=typ:<Id des Mappentyps>. Mit sicht=link&link=… geht es über einen Link über Mappentyp und Feldwerte. Die Ansichten selbst (Baum, Mappentypen, Bedingungen, gewählte Trefferliste) liefert GET /api/v1/sichten/definitionen. Die eigene Abwesenheit liest und setzt GET/PUT /api/v1/konto/abwesenheit, die eigene tägliche Zusammenfassung (Uhrzeit, Wochentage, Feiertage) GET/PUT /api/v1/konto/zusammenfassung. Die eigenen Favoriten gibt es mit sicht=favoriten; markieren und entfernen mit PUT bzw. DELETE /api/v1/mappen/{id}/favorit.

Mappentypen haben seit 0.14 mehrere Trefferlisten (trefferlisten, eine mit standard: true). Das Feld trefferliste gibt es weiter: Es enthält die Spalten der Standardliste, und wer es beim Ändern angibt, ersetzt damit deren Spalten.

Mit suche=…&volltext=true sucht GET /api/v1/mappen auch im Volltext der Dokumente; die Fundstellen stehen in ausschnitte (Treffer zwischen den Steuerzeichen U+0002 und U+0003). Den ganzen Text eines Dokuments liefert GET /api/v1/dokumente/<Id>/volltext.

Weitere Endpunkte

Die API-Dokumentation beschreibt alle Endpunkte mit ihren Parametern. Ein Überblick:

Wofür Endpunkte
Erweiterte Suche GET /api/v1/mappen?sicht=suche&link=… mit den Parametern der erweiterten Suche als ein kodierter Wert, z. B. typ%3Drechnung%26volltext%3DBackofen
Aufgaben GET /api/v1/aufgaben (eigene offene), POST /api/v1/mappen/{id}/aufgaben (vergeben), POST /api/v1/aufgaben/{id}/erledigt und …/delegieren, mehrere auf einmal mit POST /api/v1/aufgaben/weitergeben bzw. …/aufgaben/erledigt (#415); Fristen und Erinnerungen über GET /api/v1/anstehend und …/erinnerungen
Anstehend als Kalender (#528) GET /api/v1/anstehend?von=2027-01-01&bis=2027-12-31 liefert Fristen, Erinnerungen und Aufgaben mit Datum des Schlüssel-Benutzers für einen Zeitraum (höchstens 400 Tage) in einer Anfrage – mit den berechneten künftigen Terminen wiederkehrender Fristen (folgetermin: true), allem Überfälligen (faellig und datum vor heute) und den Feiertagen (feiertage). Ohne von/bis wie die Liste: ?tage=30 ab heute
Notizen GET/POST /api/v1/mappen/{id}/notizen, PUT/DELETE /api/v1/notizen/{id}
Historie einer Mappe GET /api/v1/mappen/{id}/historie
E-Mail POST /api/v1/mappen/{id}/email versendet eine Mappe mit Dokumenten (zusammen höchstens 50 MB)
Dokumente und Versionen POST /api/v1/mappen/{id}/dokumente (hochladen), POST /api/v1/dokumente/{id}/ersetzen (neue Version), GET /api/v1/dokumente/{id}/versionen, ältere Version herunterladen und …/zurueckholen
Texterkennung POST /api/v1/dokumente/{id}/texterkennung stößt sie für ein Dokument (erneut) an; GET /api/v1/dokumente/{id}/volltext liefert den Text
Volltext setzen PUT /api/v1/dokumente/{id}/volltext mit { "text": "…" } (Recht U auf die Mappe) ersetzt den Volltext, z. B. aus einer eigenen Texterkennung; GET /api/v1/dokumente/{id}/seiten/{nr}/scan?dpi=300 liefert eine Seite als Graustufenbild (PGM)
Umgewandelte Fassung GET /api/v1/dokumente/{id}/fassung liefert die Fassung (PDF, PNG oder JPEG), die ein Paket aus einer Datei gemacht hat, die das DMS nicht selbst liest (z. B. TIFF); setzen dürfen sie nur Pakete mit dem Recht Dateien umwandeln

Post anlegen und zuordnen

Ein Skript, ein Scanner oder Home Assistant legt neue Post an und lädt die Datei dazu hoch:

curl -X POST -H "Authorization: Bearer dms_…" -H "Content-Type: application/json" \
  -d '{"betreff": "Scan vom Drucker", "fuer": "<Id eines Benutzers>"}' \
  http://<NAS>:8080/api/v1/post
curl -X POST -H "Authorization: Bearer dms_…" -H "Content-Type: application/octet-stream" \
  --data-binary @scan.pdf "http://<NAS>:8080/api/v1/mappen/<Id der Post>/dokumente?register=dokumente&name=scan.pdf"

Die Post steht dann mit Kanal API und Stand Neu in Neue Post. POST /api/v1/post/<Id>/zuordnen mit {"ziel": "<Id einer Mappe>"} ordnet sie zu; die Dokumente wandern ins erste Dokumentenregister der Mappe (oder in register, mit kopieren: true bleiben sie auch in der Post). Bei Post, die vor 0.41 als E-Mail angelegt wurde, heißt das Dokumentenregister anhaenge.

Gelöschte Mappen liegen im Papierkorb: GET /api/v1/papierkorb (eigener), POST /api/v1/papierkorb/<Id>/wiederherstellen, DELETE /api/v1/papierkorb/<Id> und DELETE /api/v1/papierkorb (leeren).

Regeln

  • Schlüssel gelten nur unter /api/v1, nicht an den internen Adressen der Oberfläche. Ein Schlüssel nur Zähler gilt nur für GET /api/v1/ich/zaehler.
  • Es gelten dieselben Prüfungen wie in der Oberfläche: Pflichtfelder, eindeutige Werte, geschützte Felder der Benutzer-Mappen – und die Berechtigungen des Benutzers, dem der Schlüssel gehört. Mappen, die er nicht lesen darf, liefert die Schnittstelle nicht; Passwörter nur mit dem Recht „Passwörter sehen“.
  • Benutzer wählt man auch über die Schnittstelle nur aus denen, deren Benutzer-Mappe man sehen darf (Verantwortlich, Aufgaben, Vertreter). Wie man so ein Programm sauber abgrenzt, zeigt das Beispiel Ein Programm, das nur Rechnungen sieht.
  • Im aktiven Wartungsmodus antwortet die Schnittstelle mit 503 und Retry-After (Sekunden bis zum erwarteten Ende).
  • Fehler kommen als JSON mit einer deutschen Meldung in fehler; bei ungültigen Eingaben (422) steht in details das Prüfergebnis je Feld.
  • Passwortfelder setzt man mit einem Text oder {"neu": "…"}, entfernt sie mit null und lässt sie unverändert, indem man sie weglässt.
  • Die Kennungen der Felder ändern sich nie (siehe Mappentypen) – Skripte, die mit ihnen arbeiten, bleiben gültig, auch wenn Bezeichnungen umbenannt werden.