API
Übersicht
Die Web-Schnittstelle von docs365 documents basiert auf einer REST-Architektur über HTTP im JSON-Format. Das bedeutet, dass jeder einzelne Endpunkt (Resource) der API eine eigene URL hat und alle Anfragen bis auf ein Authentifizierungs-Cookie zustandslos sind.
Dabei bestimmt die HTTP-Methode, welche Aktion ausgeführt wird:
GETliest einen Datensatz, ohne ihn zu verändern.POSTerzeugt einen neuen Datensatz.PUTverändert einzelne Daten eines bestehenden Datensatzes.DELETElöscht einen Datensatz.
Je nach Resource wird nur ein Teil der Methoden unterstützt. So wird z.B. ein DELETE verweigert,
wenn Datensätze nicht gelöscht werden dürfen.
Als Zeichenkodierung wird sowohl bei Anfragen als auch Antworten UTF-8 vorausgesetzt.
Format
In der JSON-API werden oberster Ebene werden alle Daten in einem Dictionary übertragen und der
Haupt-Datensatz befindet sich unter dem Schlüssel data. Häufig enthält dieser weitere
verschaltete Listen und Dictionaries.
Eine komplexer JSON-Datensatz kann z.B. folgendermaßen aussehen:
{
"data": {
"active": true,
"admin": false,
"email": "max@example.com",
"fullname": "Max Mustermann",
"id": "00547d70-8009-3ea4-2f7c-3b8c78126ca9",
"permissions": [
{
"archive_id": "0053f461-3a8c-94cc-4838-2b944a76f459",
"permission": "write"
},
{
"archive_id": "005472d9-c7e0-f3a4-6fa4-e790612a30b8",
"permission": "read"
}
],
"roles": [
"Archivierer",
"Benutzer"
],
"username": "max"
}
}
multipart/form-data
Neben den JSON-Format versteht die API bei POST- und PUT-Request auch noch das von Browsern
verwendete Format multipart/form-data. Verschachtelte Datensätze sind hierbei nicht möglich.
Wenn Dateien hochgeladen werden, ist dieses Format aktuell notwending.
URL-Format und Versionierung
Ausgehend von der Basis-URL (in den Beispielen http://archiv.example.com/) ist die API unter dem
Pfad /api/v1/ zu erreichen, wobei v1 die Versionsnummer ist:
http://archiv.example.com/api/v1/
Die API unterstützt unterschiedliche Versionen (aktuell nur v1) und garantiert innerhalb einer
Version Rückwärtskompatibilität. Die vom Server unterstützten Version können über einen
info-Request abgefragt werden:
JSON-API:
/api/info
{
"data": {
"versions": [
{
"deprecated": false,
"num": 1
}
]
}
}
Der Client sollte zu Beginn einer Session die vom Server unterstützen Versionen abfragen. Wenn die
vom Client unterstüzte Version als deprecated markiert wurde, sollte eine Warnung ausgegeben
werden. Wird die Client-Version nicht mehr vom Server unterstüzt, muss eine Fehlermeldung ausgeben
werden.
Alternativ kann der Client den info-Request überspringen und sofort auf die URL der
unterstützten Version zugreifen.
Wenn der Client versucht, auf eine Version zuzugreifen, die vom Server nicht mehr unterstützt wird,
gibt es eine Antwort mit dem HTTP-Statuscode 410 Gone als Antwort. Auch in diesem Fall soll eine
eindeutige Fehlermeldung ausgegeben werden.
Alle in den folgenden Kapiteln angegeben URLs werden relativ zu den oben genannten versionierten
Basis-URLs angegeben, so bedeutet z.B. ein GET /login entweder
GET http://archiv.example.com/api/v1/login.
Allgemeine API-Struktur
Die meisten API-Endpunkte unterstützen die vier HTTP-Methoden GET, POST, PUT und
DELETE in folgendem Format (im nicht existierenden Beispiel-Endpunkt items):
GET /itemsGET /items/<item_id>POST /itemsPUT /items/<item_id>DELETE /items/<item_id>
Wenn der GET-Request ohne eine ID aufgerufen wird, wird eine Liste der Datensätze zurückgegeben,
die beliebig sortiert und gefiltert werden kann. Mit ID-Parameter werden die Daten zu einem
einzelnen Datensatz aufgerufen; diese Antwort ist meist detaillierter als der Listen-Datenssatz.
POST /items erzeugt einen neuen Datensatz.
Da PUT und DELETE einen bestehenden Datensatz verarbeiten, wird hier immer eine ID benötigt.
Listen
Bei Listenantworten enthält data immer eine Liste von Dictionaries:
{
"data": [
{
"key": "value"
},
{
"key": "value"
}
],
"total": 2
}
Limits
Standardmäßig wird die Anzahl der Elemente in der Liste auf 100 begrenzt, sodass die Antwort nicht
zu groß wird. Der total-Parameter gibt die Gesamtzahl (bis zu einem konfigurierbaren Limit,
aktuell 10000) an vorhandenen Datensätzen aus.
Das Limit kann durch die URL-Parameter start und limit verändert werden:
startgibt an, ab dem wievielten Datensatz die Liste beginnt (der ersten Datensatz hat den Index 0).limitgibt die Anzahl an zu übergeben Datensätzen an.
Beispiele
GET /items?start=0&limit=100ruft die ersten 100 Datensätze auf.GET /items?start=100&limit=50ruft die nächten 50 auf.
Sortierung
Die Liste kann durch die Parameter sort und direction nach jedem Feld sortiert werden. Wenn
man z.B. nach _rechnungsnummer sortieren möchte, muss GET /items?sort=_rechnungsnummer
aufgerufen werden. Der Parameter direction versteht die Werte ASC und DESC, wenn dieser
Parameter fehlt, wird ASC angenommen. Beispielsweise soriert
GET /items?sort=_rechnungsnummer&direction=DESC absteigend nach der Rechnungsnummer.
Alternativ kann die Sortierungsreihenfolge auch durch ein Leerzeichen getrennt direkt im
sort-Parameter übergeben werden, in diesem Fall sind durch Komma getrennt auch mehrere
Sortierungen möglich. Wenn z.B. zuerst absteigend nach _rechnungsnummer sortiert werden soll und
anschließend aufsteigend nach _name, hat der sort-Parameter folgenden Inhalt:
_rechnungsnummer DESC, _name ASC
Bzw. mit URL-Encoding:
/items?sort=_rechnungsnummer%20DESC%2C%20_name%20ASC
Filterung
Alle Felder, die sortiert werden können, können auch gefiltert werden. Dafür muss der Parameter
query mit dem kompletten Filter-Query übergeben werden.
Die Syntax des Filter-Querys ähnelt einem SQL-WHERE-Ausdruck. Einzelne Ausdrücke können mit
AND oder OR verknüfpt werden und Klammerungen werden unterstützt.
Unterstützte Operatoren sind:
=
!=
>
>=
<
<=
in_quarter
in_year
Beispiele:
-- Rechnungsnummer ist *123456* und der Kundenname beginnt mit "Muster"
_rechnungsnummer = 123456 AND _kunde = "Muster*"
-- Archivierungsdatum im Jahr 2014
creation_date in_year 2014
Einzelne Datensätze
Bei einzelnen Datensätzen, die durch die Angabe einer ID explizit angefragt werden, enthält data
direkt ein Dictionary:
{
"data": {
"key": "value"
}
}
Benutzer-Authentifizierung
Fast alle HTTP-Anfragen benötigen einen authentifizierten Benutzer. Wenn dieser nicht vorhanden ist,
wird die Anfrage mit dem HTTP-Status 401 Unauthorized abgebrochen. Der Client sollte in diesem
Fall möglichst transparent eine Anmeldung durchführen und die Anfrage wiederholen.
Die API kann entweder von Dienstbenutzern oder regulären Benutzer verwendet werden, deren Anmeldeprozess sich unterscheidet.
Dienstbenutzer können sich nicht in der Oberfläche anmelden, mit dem in der
Administrationsoberfläche angezeigten Token aber die API direkt verwenden. Dazu muss das Token bei
jedem Request in einem Cookie mit dem Namen t mitgeschickt werden.
Reguläre Benutzer haben eine Kombination von Benutzer und Passwort und müssen zunächst noch einen zusätzlichen Anmeldeschritt durchführen:
POST /login
Meldet einen Benutzer an.
Request-Parameter
usernameDer Benutzername.
passwordDas Passwort im Klartext.
Beispiel-Request
{
"username": "max",
"password": "mypassword"
}
Beispiel-Antwort
Bei einer erfolgreichen Anmeldung liefert der Server den Status 204 No Content zurück und setzt
ein Cookie, das bei allen weiteren Requests mitgesendet werden muss. Bei falschen Logindaten gibt es
den HTTP-Status 403 Forbidden als Antwort.
Zwei-Faktor-Authentifizierung
Wenn bei einem Benutzer Zwei-Faktor-Authentifizierung aktiviert ist, reichen Benutzername und Password alleine für die Anmeldung nicht aus, sondern es muss noch zusätzlich ein “one-time password” (OTP) übergeben werden, meistens in Form eines 6-stelligen Zahlencodes, der sich alle 30 Sekunden ändert.
Falls ein Benutzer noch einen zweiten Faktor für die Anmeldung benötigt, bricht der
/login-Request mit einem Status 400 Bad Request ab. Im Body der Antwort kann der Client im
"errors"-Array die Ursache ermitteln: Wenn das Feld "otp_code" die Fehlermeldung
"errorRequired" enthält, muss ein Einmalpasswort übermittelt werden:
{
"errors": [
{
"id": "otp_code",
"msg": "errorRequired"
}
]
}
Der Client muss anschließend den vollständigen Request mit dem zusätzlichen Feld "otp_code"
(dessen Wert vom Benutzer abgefragt wird) wiederholen:
{
"username": "max",
"password": "mypassword",
"otp_code": "123456"
}
Falls der eingegebene Code falsch ist, gibt es wiederum den Status 400 Bad Request mit der
Fehlermeldung "errorInvalidValue":
{
"errors": [
{
"id": "otp_code",
"msg": "errorInvalidValue"
}
]
}
Bei erfolgreicher Anmeldung antwortet der Server mit einem 200 OK und setzt nun zwei Cookies,
die bei allen weiteren Requests mitgesendet werden müssen.
Sofern im Benutzer die Option “Vertrauenswürdige Geräte zulassen” konfiguriert ist, gibt es in der
Antwort noch einen Wert "otp_token", den sich der Client auf vertrauenswürdigen Geräten
dauerhaft merken kann:
{
"data": {
"otp_token": "5gQugwcyvs-syH4UF5JbQAV1"
}
}
Bei zukünftigen Anmeldungen kann dann statt dem dynamisch erzeugten "otp_code" das gespeicherte
"otp_token" übermittelt werden:
{
"username": "max",
"password": "mypassword",
"otp_token": "5gQugwcyvs-syH4UF5JbQAV1"
}
Sollte dieses Token irgendwann einmal ungültig werden, wird in der Antwort des Servers wieder ein
"errorRequired" für "otp_code" als Fehlermeldung zurückgegeben, so als hätte man kein Token
übermittelt. In diesem Fall muss ein neuer Code beim Benutzer abgefragt werden.
Archive abfragen
GET /viewer_archives
Liefert eine Liste von allen Archiven und Views, auf die der aktuell angemeldete Benutzer zugreifen darf.
Beispiel-Antwort
Die folgende Antwort enthält ein reguläres Archiv und einen View.
{
"data": [
{
"archive_type": "archive",
"id": "00547da9-30f3-28c0-4402-24020c1fd8be",
"identifier": "dokumente",
"name": "Dokumente"
},
{
"archive_type": "view",
"id": "0053f47c-1d7d-bad0-5b5b-4f132863030b",
"identifier": "pdf",
"name": "PDF-Dokumente"
}
],
"total": 2
}
GET /viewer_archives/<archive_id>
Liefert Detailinformationen zu dem Archiv mit der ID <archive_id> (das Feld id aus
GET /viewer_archives, es kann alternativ auch der Kurzname identifier verwendet werden).
Neben dem konfigurierten Kurznamen (identifier) und Langnamen (name), die auch in der Liste
der Archiven vorhanden sind, ist die Liste der im Archiv vorhandenen Spalten (recordcolumns) die
wichtigste Information.
Die für die Anzeige als Datengitter wichtigsten Informationen der recordcolumns sind:
name: Der Langname der Spalte, z.B. als Spaltentitel im Datengitter benötigt.identifier: Der Kurzname, der insbesondere für die Übertragung der Metadaten eines Vorgangs benötigt wird.columntype: Der Datentyp der Spalte. Mögliche Werte sindstring,integer,float,datetime,dateundboolean.
Beispiel-Antwort
{
"data": {
"description": null,
"id": "00547da9-30f3-28c0-4402-24020c1fd8be",
"identifier": "dokumente",
"name": "Dokumente",
"recordcolumns": [
{
"columntype": "string",
"id": "00547da9-30f7-82e0-f132-b6219cd9bb90",
"identifier": "kunde",
"length": 0,
"lookup_restriction": false,
"lookup_type": "none",
"name": "Kundenname",
"required": false
},
{
"columntype": "integer",
"id": "00547da9-30fa-123c-cbb3-365cdfdcec3f",
"identifier": "rechnungsnummer",
"length": 0,
"lookup_restriction": false,
"lookup_type": "none",
"name": "Rechnungs-Nummer",
"required": false
}
]
}
}
Vorgänge abfragen
GET /records?archive_id=<archive_id>
Gibt es eine Liste von Vorgängen in dem Archiv mit der Archive-ID <archive_id> zurück. Der
URL-Parameter archive_id ist immer erforderlich.
Alle Felder, die mit einem Unterstrich _ beginnen, sind die selbst konfigurierten Spalten im
Archiv, dabei wird der Kurzname (identifier) der Spalte nach dem Unterstrich verwendet.
Die restlichen Felder sind immer vorhanden:
attachments_count: Die Anzahl der angehängten Dokumente.creation_date: Der Zeitpunkt der Archivierung (imdatetime-Format).creator: Der Benutzer, der die Archivierung durchgeführt hat.hash_id: Der unveränderliche Hash des Vorgangs.id: Die in der API verwendete eindeutige ID des Vorgangs.
Beispiel-Antwort
{
"data": [
{
"_kunde": "Musterfirma 1",
"_rechnungsnummer": 123456,
"attachments_count": 1,
"creation_date": "2014-12-02T12:08:01.138839+00:00",
"creator": "Max Mustermann",
"hash_id": "6c2bcd91549c0621d86f94c0b6761c86369e6ea603a5e0635a94be2fd4f6436e",
"id": "00547dab-a0cf-0d48-8a9d-3de79ba5fd09"
},
{
"_kunde": "Musterkunde 2",
"_rechnungsnummer": 654321,
"attachments_count": 2,
"creation_date": "2014-12-02T12:08:30.202461+00:00",
"creator": "Max Mustermann",
"hash_id": "fd105279ee06ed9cdae675af986e3812a56bd2be4b4601ab3239f6808fb7679c",
"id": "00547dab-bddf-56d0-7b9d-228f22a5e107"
}
],
"total": 2
}
GET /records/<record_id>
Ruft einen einzelnen Vorgang mit der ID <record_id> auf.
Die Liste attachments enthält nun genaue Informationen zu den Dokumenten, die an dem Vorgang
angehängt sind. Ansonsten sind die Daten identisch mit denen in der Vorgangs-Liste.
Beispiel-Antwort
{
"data": {
"_kunde": "Musterfirma 1",
"_rechnungsnummer": 123456,
"archive_id": "00547da9-30f3-28c0-4402-24020c1fd8be",
"attachments": [
{
"custom_date": "2014-10-31",
"custom_description": null,
"custom_name": "TIF",
"filename": "9pages.tif",
"hash_id": "67050b052824c51bf290fafbf92ec6d980fd245e5e095f49dda6f2d7fac0c638",
"id": "00547dab-a0d6-bb5c-55b5-f941a18f042b",
"page_count": 9,
"viewable": "9pages.pdf"
}
],
"creation_date": "2014-12-02T12:08:01.138839+00:00",
"creator": "Max Mustermann",
"hash_id": "6c2bcd91549c0621d86f94c0b6761c86369e6ea603a5e0635a94be2fd4f6436e",
"id": "00547dab-a0cf-0d48-8a9d-3de79ba5fd09"
}
}
Neueste Vorgangsversion ermitteln
Wenn eine neue Version eines Vorgangs erzeugt wird, bekommt die neue Version eine neue id und
die alte Version wird versteckt (und ist somit nur noch für Administratoren aufrufbar). Wenn
die id einer älteren Vorgangsversion bekannt ist, kann über den folgenden Endpunkt die id
der neuesten Version ermittelt werden:
GET /record_version/<record_id>
Gibt die id, release_id und release_version der neuesten Version zurück, sofern die neue
Version für den aufrufenden Benutzer sichtbar ist.
Beispiel-Antwort
{
"data": {
"id": "0065aa53-a0d9-6407-eb98-1d2d5bc010bb",
"release_id": "0065aa53-5373-8c30-ce99-88075066a658",
"release_version": 2
}
}
Wenn die id in der Antwort identisch mit der <record_id> in der URL ist, ist der Vorgang
weiterhin die neueste Version.
Dokumente herunterladen
GET /attachments/<attachment_id>
Lädt die Datei des Dokuments (attachment) mit der ID <attachment_id> herunter.
Vorgänge archvieren
Vorgänge bestehen im Wesentlichen aus zwei Komponenten:
Den angehängten Dokumenten (z.B. PDF- oder Word-Dateien).
Den Metadaten, die die Dokumente zusammen mit den Daten der Archivspalten zu einem Vorgang zusammenfassen.
Bei einem Archivierungsvorgang müssen immer zuerst die anzuhängenden Dateien hochgeladen werden, um sie dann anschließend bei der Archivierungsanfrage zu referenzieren. Große Dateien können vom Client in kleine Stücke (Chunks) zerteilt werden, diese werden dann beim Archvierungsvorgang wieder serverseitig zusammengesetzt. Damit sichergestellt werden kann, dass der Server die Dateien korrekt erhalten und zusammengesetzt hat, muss der Client beim Archvierungsvorgang die SHA-256-Prüfsumme der Datei mit übergeben.
POST /chunk
Lädt eine Datei hoch, die später archiviert werden soll. Dieser Endpunkt erwartet den Inhalt der Datei als Binär-Stream im Request-Body.
Beispiel-Antwort
Wichtig: Die Antworten dieses API-Endpunktes sind nicht noch einmal in data gekapselt,
sondern ein Dictionary auf oberster Ebene.
{
"id": "e5247f56-7555-472f-b5f6-5d0381be7371",
"success": true
}
POST /upload
Lädt eine Datei hoch, die später archiviert werden soll. Dieser Endpunkt unterstützt nur
multipart/form-data mit folgenden Parametern:
fileErforderlich. Die Datei oder der Chunk, der hochgeladen werden soll.
calculate_checksumOptional. Grundsätzlich sollte die Client die SHA-256-Prüfsumme selbst berechnen und dem Server beim Archvierungsvorgang zur Verifizierung mitteilen. Sollte dies nicht möglich sein (z.B. bei Webbrowsern), kann sich der Client den Hash auch vom Server berechnen lassen, indem
calculate_checksumauftruegesetzt wird.
Beispiel-Antwort
Wichtig: Die Antworten dieses API-Endpunktes sind nicht noch einmal in data gekapselt,
sondern ein Dictionary auf oberster Ebene.
{
"checksum": "e0eb20abe0f7f3affe92cb4c0d040dfcf7b3080477e978cb2eba42508ed929b3",
"filename": "archives.png",
"id": "e5247f56-7555-472f-b5f6-5d0381be7371",
"success": true
}
POST /records
Archiviert einen neuen Vorgang
Request-Parameter
archive_idErforderlich. Die ID des Archivs, in das der Vorgang hinzugefügt werden soll (das Feld
idausGET /viewer_archives).filesErforderlich. Eine Liste von Dokumenten, die angehängt werden sollen (siehe nächster Abschnitt). Die Liste kann leer sein, wenn keine Dokumente angehängt werden.
_<identifier>Wenn Metadaten hinzugefügt werden sollen, muss als Schlüssel im Dictionary jeweils der Kurzname (
identifier) mit einem vorangestellten Unterstrich verwenden werden (siehe Beispiel-Requests). Einige dieser Felder können Pflichtfelder sein.
Request-Parameter für die files-Liste
chunksErforderlich. Eine Liste von Chunks-IDs (das
id-Feld ausPOST /upload), die die Datei zusammensetzen. Diese Liste darf nicht leer sein. Wenn eine Datei im Ganzen hochgeladen wurde, ist in dieser Liste nur eine ID notwendig, ansonsten müssen die IDs in der richtigen Reihenfolge sein: Der Server setzt die hochgeladenen Chunks von links nach rechts wieder zu einer Datei zusammen.checksumErforderlich. Die SHA-256-Prüfsumme der Datei. Diese wird vom Server benutzt, um zu verifizieren, dass die Datei korrekt hochgeladen wurde und bei zerteilten Dateien die Chunks wieder korrekt zusammengesetzt sind.
filenameErforderlich. Der Dateiname des angehängten Dokumentes.
custom_nameOptional. Ein beliebig verwendbares String-Feld (maximale Länge 255).
custom_descriptionOptional. Ein beliebig verwendbares String-Feld (maximale Länge 2048).
custom_dateOptional. Ein beliebig verwendbares Datums-Feld.
Beispiel-Request
{
"archive_id": "00547da9-30f3-28c0-4402-24020c1fd8be",
"_kunde": "Musterfirma",
"_rechnungsnummer": 123,
"files": [{
"chunks": ["c9b67df8-d8de-4209-8e4b-485196048bd4"],
"checksum": "e0eb20abe0f7f3affe92cb4c0d040dfcf7b3080477e978cb2eba42508ed929b3",
"filename": "archives.png"
}]
}
Beispiel-Antwort
Die gleiche Antwort wie bei GET /records/<records_id>.
PUT /records/<record_id>
Verändert einen existierenden Vorgang. Es können hier sowohl die Metadaten als auch die angehängten Dokumente modifiziert werden, sofern das im Archiv erlaubt ist (beispielsweise muss ein Datenfeld als Änderbar konfiguriert sein, damit man es verändern darf). Nicht erlaubte Änderungen werden vom Server ignoriert.
Wenn revisionssicher gespeicherte Daten verändert werden, erzeugt dieser Request eine neue Version des Vorgangs.
Wenn angehängte Dokumente hinzugefügt, gelöscht oder umsortiert werden sollen, muss dafür die Liste
attachments übergeben werden:
Jedes bereits vorhandene Dokument muss in einem eigenen Dictionary über dessen
idreferenziert werden.Neu hochgeladene Dokumente müssen im gleichen Format wie in der
files-Liste inPOST /recordshinzugefügt werden.Die Reihenfolge in der
attachments-Liste bestimmt die Reihenfolge, in der die Dokumente später in der Oberfläche angezeigt werden.Alle bestehenden Dokumente, die in der
attachments-Liste nicht referenziert werden, werden aus der neuen Version des Vorgangs entfernt.
Beispiel-Request
{
"_kunde": "Musterfirma",
"_rechnungsnummer": 123,
"attachments": [{
"id": "005ba9e2-885b-99fc-a951-92db3a22e238"
},{
"chunks": ["181ba316-309d-4df8-8728-1090295743bf"],
"checksum": "ac4f0d97368365b30f0398d32783b7ca47c2ed6993cd1696ca8401d9d1fea31d",
"filename": "Rechnung.pdf"
}]
}
Beispiel-Antwort
Die gleiche Antwort wie bei GET /records/<records_id>. Wenn eine neue Version des Vorgangs
erzeugt wurde, enthält die Antwort eine neue id und der Wert in release_version wird
hochgezählt.
Öffentliche Links für Dokumente und Vorgänge
Bemerkung
Ein Statuswechsel kann dazu führen, dass ein erzeugter Link ungültig wird, wenn beispielsweise der Dienstbenutzer, der einen Dokumenten-Link erzeugt hat, im neuen Status keinen Zugriff auf den Vorgang des Dokuments mehr hat.
Öffentliche Links für Dokumente
Über den Endpunkt /shared_attachments können Links für einzelne Dokumente erzeugt werden, über
die das jeweilige Dokument ohne Benutzeranmeldung aufgerufen werden kann. Die Links sind intern
mit dem erzeugenden Benutzer verknüpft und die Dokumente können auch nur solange über den erstellten
Link aufgerufen werden, solange der Benutzer selbst noch Zugriff auf das Dokument hat.
Der Endpunkt unterstützt die Standard-Methoden GET /shared_attachments, GET /shared_attachments/<id>
und PUT /shared_attachments/<id>.
Öffentliche Links für Vorgänge
Über den Endpunkt /shared_records können Links für einzelne Vorgänge erzeugt werden, über die die
Informationen des Vorgangs mitsamt Dokumenten ohne Benutzeranmeldung aufgerufen werden können. Genau
wie bei den geteilten Dokumenten sind die Links intern mit dem erzeugenden Benutzer verknüpft, und
die Vorgänge können auch nur solange über den erstellten Link aufgerufen werden, wie der Benutzer
selbst noch Zugriff auf das Dokument hat.
Der Endpunkt unterstützt die Standard-Methoden GET /shared_records, GET /shared_records/<id>
und PUT /shared_records/<id>.