Zum Inhalt springen

OBS/Kostenpflichtige Module/RESTServer/Endpunkte: Unterschied zwischen den Versionen

Aus OBS Wiki
Rademacker (Diskussion | Beiträge)
Die Seite wurde neu angelegt: „{{Kostenpflichtige Module}} =Endpunkte= Ein '''Endpunkt''' definiert eine Adresse, ueber die der REST-Server eine konkrete Funktion anbietet. Hinter jedem Endpunkt steht entweder ein OBS-Skript (Standardfall) oder ein WebHook (Einmal-Antwort fuer asynchrone Rueckrufe). ==Aufruf== '''Stammdaten -> Z Weitere Stammdaten -> REST-Server -> Endpunkte''' ==Felder== {| class="wikitable" ! Feld !! Beschreibung |- | Endpunkt || Hauptname, erster Pfad-Best…“
Rademacker (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
 
(9 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
{{Kostenpflichtige Module}}
{{Kostenpflichtige Module}}


=Endpunkte=
= Endpunkte =


Ein '''Endpunkt''' definiert eine Adresse, ueber die der REST-Server eine konkrete Funktion anbietet. Hinter jedem Endpunkt steht entweder ein OBS-Skript (Standardfall) oder ein WebHook (Einmal-Antwort fuer asynchrone Rueckrufe).
Ein '''Endpunkt''' stellt eine Adresse bereit, über die der REST-Server konkrete
Funktionen anbietet. Jeder Endpunkt wird durch ein OBS-Skript oder einen WebHook
realisiert und ist genau einem Server-Profil zugeordnet.


==Aufruf==
== Routing über Pfad-Templates ==


'''Stammdaten -> Z Weitere Stammdaten -> REST-Server -> Endpunkte'''
Das Routing erfolgt über die Spalte '''Pfad-Template''' (<code>re_pathtemplate</code>).
Ein Template beschreibt den vollständigen Pfad nach dem Host und kann
'''Platzhalter''' enthalten:


==Felder==
* '''Statische Segmente''' müssen exakt übereinstimmen (Groß-/Kleinschreibung wird ignoriert).
* '''Platzhalter''' in geschweiften Klammern – z.&nbsp;B. <code>{uid}</code> – passen auf einen beliebigen Wert und werden als [[#Pfad-Parameter im Skript|Pfad-Parameter]] erfasst.
 
Beispiele für gültige Templates:
 
{| class="wikitable"
! Template !! Passt auf !! Pfad-Parameter
|-
| <code>/orders</code> || <code>/orders</code> || –
|-
| <code>/orders/{uid}</code> || <code>/orders/4711</code> || <code>uid = 4711</code>
|-
| <code>/orders/{uid}/modules/{code}</code> || <code>/orders/4711/modules/A1</code> || <code>uid = 4711</code>, <code>code = A1</code>
|-
| <code>/kalender/v1</code> || <code>/kalender/v1</code> || –
|}
 
=== Präzedenz bei mehreren Treffern ===
 
Passen mehrere Templates auf denselben Pfad, '''gewinnt das spezifischste''' –
also das mit den meisten statischen Segmenten. So schlägt <code>/orders/summary</code>
das Template <code>/orders/{uid}</code>, während <code>/orders/4711</code> auf
<code>/orders/{uid}</code> matcht.
 
== Hauptfelder eines Endpunkts ==


{| class="wikitable"
{| class="wikitable"
! Feld     !! Beschreibung
! Feld !! Spalte !! Zweck
|-
|-
| Endpunkt || Hauptname, erster Pfad-Bestandteil nach der Hostadresse (Pflichtfeld)
| '''Pfad-Template''' || <code>re_pathtemplate</code> || '''Maßgeblich fürs Routing.''' Vollständiger Pfad mit Platzhaltern, z.&nbsp;B. <code>/orders/{uid}/modules/{code}</code>
|-
|-
| Sub-URL  || Optionaler zweiter Pfad-Bestandteil, z.B. ''mobile'', ''office''
| '''Server''' || <code>re_server</code> || Zuordnung zum Server-Profil (erforderlich)
|-
|-
| Version  || Versionsbezeichner, z.B. ''v1'', ''v1.0'', ''v2''
| '''Aktiv''' || <code>re_aktiv</code> || Statusflag; inaktive Endpunkte liefern 404
|-
|-
| Server  || Zuordnung zu einem Server-Profil. Der Endpunkt ist nur ueber dieses Profil erreichbar (Pflichtfeld)
| '''Skript''' || <code>re_script</code> || DwScript-Quelltext des Handlers (siehe [[/OBS/Kostenpflichtige_Module/RESTServer/Scripting|Scripting]])
|-
|-
| Aktiv    || Inaktive Endpunkte sind nicht ansprechbar (404)
| '''WebHook''' || <code>re_webhook</code> || optional: Verweis auf einen Einmal-Endpunkt statt Skript
|-
|-
| Info     || Freitext zur Dokumentation
| '''Info''' || – || Dokumentations-Freitext
|-
| '''Datei-Upload''' || <code>re_upload</code> || Erlaubt Datei-Uploads an diesem Endpunkt (<code>0</code> = aus, <code>1</code> = an). Ohne Freigabe werden Upload-Anfragen mit 415 abgelehnt.
|-
| '''Max. Upload-Grösse''' || <code>re_upload_size</code> || Maximale Dateigrösse in MB. Leer/0 = Standard 25&nbsp;MB. Überschreitung wird mit 413 abgelehnt.
|}
|}


==Adressbildung==
== Pfad-Parameter im Skript ==


Die Adresse setzt sich aus Endpunkt, Sub-URL und Version zusammen:
Die aus den Platzhaltern erfassten Werte stehen im Endpunkt-Skript als
reservierte Parameter mit Präfix <code>_OBS_PATH_</code> zur Verfügung:


http://[Hostadresse][:Port]/[Endpunkt][/Sub-URL]/[Version]
<syntaxhighlight lang="pascal">
function Get(oParams: TStrings; oBody: TJSONObject): string;
var cUid: string;
begin
    cUid := oParams.Values['_OBS_PATH_uid'];  // aus /orders/{uid}
    // ...
end;
</syntaxhighlight>


Beispiele:
Da der Präfix <code>_OBS_</code> für von außen gelieferte Header/Query-Parameter
gesperrt ist, können diese Werte nicht durch den Client überschrieben werden.


https://api.meinserver.de/kalender/v1
== Datei-Uploads ==
https://api.meinserver.de/email/mein_konto/v1.0


Wird die Sub-URL leer gelassen, verkuerzt sich die Adresse auf ''/Endpunkt/Version''.
Ein Endpunkt nimmt Datei-Uploads nur entgegen, wenn er dafür freigeschaltet ist
(<code>re_upload = 1</code>). Andernfalls werden Upload-Anfragen mit
'''415 Unsupported Media Type''' abgelehnt und das Skript wird nicht ausgeführt.


==Versionierung==
Die maximal zulässige Dateigrösse wird pro Endpunkt über <code>re_upload_size</code>
(in MB) festgelegt; ohne Angabe gilt der Standard von '''25&nbsp;MB'''. Wird das
Limit überschritten, antwortet der Server mit '''413 Payload Too Large'''. Für
Uploads gilt nicht das JSON-Body-Limit (10&nbsp;MB), sondern dieses Endpunkt-Limit.
Der Originalname (beim resumable Upload über den Header <code>Upload-Metadata</code>) ist '''Pflicht'''; fehlt er, wird der Upload mit 413/400 abgelehnt. Dem Skript stehen Pfad, Name und Content-Type als <code>_OBS_UPLOAD_*</code>-Parameter zur Verfügung (Details: [[OBS/Kostenpflichtige Module/RESTServer/Scripting|Scripting]]).


Die Versionierung erlaubt es, eine Endpunkt-Funktionalitaet zu aendern, ohne bestehende Konsumenten zu brechen. Das Vorgehen:
Unterstützt werden zwei Übertragungsarten:


# Den vorhandenen Endpunkt unveraendert lassen, weiterhin aktiv halten.
* '''Einfacher Upload''' per <code>multipart/form-data</code> (eine Datei pro Request).
# Einen neuen Endpunkt mit gleicher Endpunkt-/Sub-URL, aber neuer Version anlegen.
* '''Resumable/Chunked Upload''' per <code>Content-Range</code> (grosse Dateien, fortsetzbar nach Abbruch).
# Berechtigungen fuer die neuen Konsumenten setzen.
# Wenn alle Konsumenten umgestellt sind, den alten Endpunkt deaktivieren.


==Zuordnung zum Server-Profil==
Der Server legt die hochgeladene Datei in einem temporären Verzeichnis ab und
übergibt dem Endpunkt-Skript den Pfad. Was mit der Datei geschieht (Ablage,
DMS-Verknüpfung, Weiterverarbeitung), entscheidet allein das Skript. Details und
Beispiele: [[OBS/Kostenpflichtige Module/RESTServer/Scripting|Scripting]].


Ein Endpunkt ist immer genau einem Server-Profil zugeordnet. Damit lassen sich z.B. der gleiche Endpunkt-Name auf einem Public-Server (Standard-TLS) und einem Internal-Server (mTLS) parallel betreiben - die jeweils dem Server zugeordneten Endpunkte werden voneinander getrennt. Ein Konsument, der ueber das Public-Profil zugreift, kann nicht versehentlich die mTLS-Variante ansprechen.
== HTTP-Methode ==


==Berechtigungen==
Welche Funktion aufgerufen wird, ergibt sich aus dem HTTP-Verb: Der Server ruft
die gleichnamige Skript-Methode auf (<code>Get</code>/<code>Post</code>/<code>Put</code>/<code>Delete</code>/<code>Patch</code>).
Ein Template entspricht damit '''einem''' Endpunkt-Skript; unterschiedliche
Pfad-Formen (z.&nbsp;B. <code>/orders</code> vs. <code>/orders/{uid}</code>) sind
'''eigene Endpunkt-Einträge''' mit eigenem Skript und eigener Berechtigung.


Damit ein Zugang einen Endpunkt aufrufen darf, muss er fuer diesen Endpunkt freigeschaltet sein. Aus der Endpunkt-Liste den Endpunkt markieren und '''F6''' druecken. Es oeffnet sich die Berechtigungs-Liste.
== URL-Struktur ==


In der Berechtigungs-Liste:
<pre>
http://[Host][:Port][Pfad-Template]
</pre>


* '''Einfg''' - oeffnet die Zugaenge-Liste.
Beispiele:
* In der Zugaenge-Liste mit '''F5''' einen oder mehrere Zugaenge markieren.
* <code>https://api.meinserver.de/orders</code>
* '''F2''' uebernimmt die markierten Zugaenge als Berechtigungen.
* <code>https://api.meinserver.de/orders/4711</code>
* <code>https://api.meinserver.de/orders/4711/modules/A1</code>


Ohne Markierung wird nur der aktuelle Zugang uebernommen.
== Versionierung ==


==Endpunkt-Skript==
Da es kein eigenes Versions-Feld mehr gibt, wird die Version als statisches
Segment ins Template aufgenommen, z.&nbsp;B. <code>/orders/v1</code> oder
<code>/v1/orders/{uid}</code>. Änderung ohne Breaking Change:


Aus der Endpunkt-Liste den Endpunkt markieren und '''F7''' druecken. Es oeffnet sich der Skript-Editor. Im Skript werden GET-, POST-, PUT-, DELETE- bzw. PATCH-Funktionen implementiert, die der Server bei Aufruf der entsprechenden HTTP-Methode aufruft.
# Bestehenden Endpunkt unverändert lassen.
# Neuen Endpunkt mit gleichem Ressourcennamen, aber neuem Versions-Segment im Template anlegen.
# Berechtigungen für neue Konsumenten setzen.
# Alten Endpunkt deaktivieren, wenn die Migration abgeschlossen ist.


Die genaue Skript-Syntax und alle verfuegbaren Parameter sind unter [[OBS/Kostenpflichtige Module/RESTServer/Scripting|Scripting]] beschrieben.
== Zugriffskontrolle ==


==WebHooks==
Endpunkte sind Server-Profilen zugeordnet; ein Zugang benötigt eine explizite
Berechtigung (Tabelle <code>RESTSRV_ACCESS</code>), um einen Endpunkt nutzen zu
dürfen. Weil jede Pfad-Form ein eigener Endpunkt-Eintrag ist, lässt sich der
Zugriff '''pro Pfad-Form''' granular vergeben (z.&nbsp;B. Lesen von
<code>/orders/{uid}</code> erlauben, aber das ändernde
<code>PUT /orders/{uid}/modules/{code}</code> nicht).


Ein Endpunkt kann alternativ als WebHook konfiguriert werden. WebHooks sind '''Einmal-Endpunkte''' - sie werden in der Regel von OBS aus dynamisch fuer externe Dienste angelegt (z.B. Bezahl-Callbacks). Beim ersten erfolgreichen Aufruf:
== Caching ==


# Die uebergebenen Daten (Query-String oder Request-Body) werden in der Tabelle '''REMOTE_HOOK_URL''' im Feld ''hu_response'' gespeichert.
Die Endpunkt-Definitionen werden pro Server-Profil zwischengespeichert
# Der Endpunkt wird automatisch aus '''RESTSRV_ENDPOINTS''' geloescht.
(TTL, Standard 60&nbsp;s). Neue oder geänderte Endpunkte/Templates werden daher
# Der Server antwortet mit ''{"status": "ok"}''.
erst nach Ablauf des Caches (bzw. nach einer Cache-Invalidierung) wirksam – nicht
zwingend sofort.


Damit lassen sich asynchrone Rueckrufe sauber konsumieren, ohne dass dauerhaft offene Endpunkte zurueckbleiben. Die Anlage und Auswertung eines WebHooks erfolgt typischerweise programmgesteuert ueber die zugehoerigen Helper-Funktionen, nicht ueber die Endpunkt-Maske.
== HTTP-Fehlercodes ==


==Listen-Funktionen==
{| class="wikitable"
! Code !! Ursache
|-
| '''404''' || Kein Template passt zum Pfad, Endpunkt inaktiv oder falsches Server-Profil
|-
| '''403''' || Zugang fehlt in der Berechtigungsliste
|-
| '''401''' || API-Key ungültig/fehlend, JWT abgelaufen oder Sitzung gesperrt (''AUTH_EXPIRED'')
|-
| '''500''' || Skript- oder Syntax-Fehler (Details in <code>RESTSRV_PROTO</code>)
|-
| '''415''' || Datei-Upload an einen Endpunkt, der dafür nicht freigeschaltet ist (<code>re_upload = 0</code>)
|-
| '''413''' || Hochgeladene Datei überschreitet die zulässige Maximalgrösse (<code>re_upload_size</code>)
|-
| '''429''' || Rate-Limit überschritten; die Antwort enthält den Header <code>Retry-After</code>
|-
| '''503''' || Eine Anfrage mit demselben <code>Idempotency-Key</code> wird gerade verarbeitet; die Antwort enthält <code>Retry-After</code>
|-
| '''409''' || Ein früherer Aufruf mit demselben <code>Idempotency-Key</code> ist ohne Ergebnis geblieben (<code>IDEMPOTENCY_UNRESOLVED</code>)
|-
| '''422''' || Derselbe <code>Idempotency-Key</code> wurde mit '''anderem''' Inhalt gesendet (<code>IDEMPOTENCY_KEY_REUSED</code>)
|-
| '''400''' || Die Anfrage wurde unverschlüsselt an einen TLS-Port geschickt (<code>http</code> statt <code>https</code>). Die Abweisung erfolgt vor Authentifizierung und Endpunkt-Skript
|}


In der Endpunkt-Liste:
Jede Fehlerantwort besteht aus einem <code>error</code>-Objekt mit
maschinenlesbarem Code - Aufbau siehe
[[OBS/Kostenpflichtige Module/RESTServer|Übersicht]].


* '''Einfg''' - neuer Endpunkt
Daneben kann ein Endpunkt-Skript den Statuscode selbst setzen (z.B. <code>201</code>, <code>204</code>, <code>409</code>, <code>422</code>) sowie Response-Header wie <code>ETag</code> oder <code>Location</code> - siehe [[OBS/Kostenpflichtige Module/RESTServer/Scripting|Scripting]].
* '''Return''' - Endpunkt bearbeiten
* '''F4''' - Sortierung
* '''F6''' - Berechtigungen verwalten (Zugaenge dem Endpunkt zuordnen)
* '''F7''' - Endpunkt-Skript bearbeiten
* '''F8''' - Statistik fuer den Endpunkt


==Cache==
== Idempotenz ==


Der REST-Server cached das kompilierte Skript pro Endpunkt. Wird das Skript ueber F7 geaendert, ist die neue Version sofort wirksam - der Server erkennt die Aenderung am ''sys_date'' und compiliert neu.
Schickt ein Konsument bei <code>POST</code>, <code>PUT</code>, <code>PATCH</code>
 
oder <code>DELETE</code> den Header <code>Idempotency-Key</code>, sorgt der Server
==Typische Fehlermeldungen==
selbst dafür, dass eine wiederholte Sendung '''keine Zweitwirkung''' hat. Das gilt
für '''jeden''' Endpunkt - es muss weder am Endpunkt etwas eingestellt noch im
Skript etwas programmiert werden.


{| class="wikitable"
{| class="wikitable"
! Code  !! Bedeutung
! Situation !! Antwort des Servers
|-
| Erster Aufruf || Endpunkt läuft normal, das Ergebnis wird zum Schlüssel gespeichert
|-
|-
| 404  || Endpunkt nicht vorhanden / inaktiv / falsches Server-Profil
| Wiederholung, gleicher Inhalt || '''Gespeicherte Antwort''' (gleicher Statuscode, gleicher Body, gleiche Header) plus Header <code>Idempotent-Replay: true</code>. Das Skript läuft '''nicht'''
|-
|-
| 403  || Keine Berechtigung fuer die Endpunkt-Nutzung (Zugang fehlt in der Berechtigungs-Liste)
| Wiederholung, anderer Inhalt || '''422''' <code>IDEMPOTENCY_KEY_REUSED</code> - derselbe Schlüssel für einen anderen Inhalt ist ein Client-Fehler
|-
|-
| 401  || API-Key fehlt, ungueltig, JWT fehlt oder ist abgelaufen
| Erster Aufruf läuft noch || '''503''' <code>IDEMPOTENCY_IN_PROGRESS</code> mit <code>Retry-After</code>. Beim nächsten Versuch liegt die gespeicherte Antwort vor
|-
|-
| 500  || Skript-Fehler oder Syntax-Fehler im Endpunkt-Skript - Detail siehe RESTSRV_PROTO
| Früherer Aufruf ohne Ergebnis || '''409''' <code>IDEMPOTENCY_UNRESOLVED</code>. Der Dienst wurde zwischen Verarbeitung und Festschreiben unterbrochen; ob die Buchung stattgefunden hat, ist unbekannt und von Hand zu klären
|}
|}
Wichtig für die Auslegung eines Endpunkts:
* Antwortet das Skript mit '''2xx''', wird die Antwort gespeichert und bei einer Wiederholung erneut ausgeliefert.
* Antwortet das Skript mit '''4xx''' (fachliche Ablehnung), wird der Schlüssel wieder '''freigegeben''' - der Konsument darf ihn nach Korrektur erneut verwenden. Sonst würde ein einziger Validierungsfehler den Schlüssel dauerhaft blockieren.
* Endet die Verarbeitung mit '''5xx''' oder einem Skript-Fehler, bleibt der Schlüssel belegt und der Fall wird protokolliert. Das ist Absicht: lieber ein Fall für den Support als eine mögliche Doppelbuchung.
Der Schlüssel gilt je '''Zugang, Methode und Pfad'''. Derselbe
<code>Idempotency-Key</code> an einem anderen Endpunkt ist damit ein eigener
Vorgang - der Konsument muss ihn nicht global eindeutig vergeben, aber pro Vorgang
'''stabil wiederverwenden''' (also nicht bei jedem Wiederholversuch neu erzeugen).
Die Einträge stehen in <code>RESTSRV_IDEMPOTENCY</code> und werden nach 30 Tagen
automatisch aufgeräumt. Einträge ohne Ergebnis werden '''nicht''' automatisch
gelöscht, sondern im Protokoll gemeldet.
== WebHooks ==
WebHooks sind '''Einmal-Endpunkte''' für asynchrone Callbacks. Beim ersten
erfolgreichen Aufruf wird die Antwort in der Tabelle <code>REMOTE_HOOK_URL</code>
gespeichert und der Endpunkt anschließend automatisch gelöscht.
Typischer Einsatz: OBS stösst einen Vorgang bei einem Fremdsystem an (Bezahldienst,
Versanddienstleister) und gibt diesem eine Rückruf-Adresse mit, die nur '''ein
einziges Mal''' gültig ist. Damit kann die Adresse nicht später erneut - oder von
jemand anderem - benutzt werden.
Ablauf:
# OBS legt einen Eintrag in <code>REMOTE_HOOK_URL</code> an und dazu einen Endpunkt, dessen Feld '''WebHook''' (<code>re_webhook</code>) auf diesen Eintrag zeigt. Ein Skript wird für diesen Endpunkt nicht gepflegt.
# Die Adresse dieses Endpunkts wird dem Fremdsystem als Callback-URL übergeben.
# Das Fremdsystem ruft die Adresse auf. Der Server legt den übergebenen Inhalt in <code>REMOTE_HOOK_URL.hu_response</code> ab, antwortet mit <code>{"status": "ok"}</code> und '''löscht den Endpunkt'''.
# Der weiterverarbeitende OBS-Prozess findet die Rückmeldung in <code>hu_response</code>.
{{Hinweis|Ein zweiter Aufruf derselben Adresse läuft ins Leere: Der Endpunkt
existiert nicht mehr, die Antwort ist 404. Das ist gewollt - ein WebHook ist keine
dauerhafte Schnittstelle. Für eine dauerhaft erreichbare Rückmelde-Adresse einen
normalen Endpunkt mit Skript anlegen.}}

Aktuelle Version vom 19. August 2026, 11:15 Uhr

Kostenpflichtige Module

Internet-Shop
UPS
IMS Professional
SMS
Mehrlager-Verwaltung
Mehrsprachen Modul
Multilanguage Modul
EVA Marketing Tool
Termin-Projekte
Edifact-Schnittstelle
Backup Überwachung Email
OBS Geo Daten
DeliSprint / DPD
Filialen
Cashback
Moebelschnittstelle
Dokumenten Manager
DocuWare-Schnittstelle
OFML-Kalkulation
Versicherungsschaden
Gutschriftsanzeigen
Kameraverwaltung
DataInOut
OpenMasterData / IDS
Sammelpositionen



Endpunkte

Ein Endpunkt stellt eine Adresse bereit, über die der REST-Server konkrete Funktionen anbietet. Jeder Endpunkt wird durch ein OBS-Skript oder einen WebHook realisiert und ist genau einem Server-Profil zugeordnet.

Routing über Pfad-Templates

Das Routing erfolgt über die Spalte Pfad-Template (re_pathtemplate). Ein Template beschreibt den vollständigen Pfad nach dem Host und kann Platzhalter enthalten:

  • Statische Segmente müssen exakt übereinstimmen (Groß-/Kleinschreibung wird ignoriert).
  • Platzhalter in geschweiften Klammern – z. B. {uid} – passen auf einen beliebigen Wert und werden als Pfad-Parameter erfasst.

Beispiele für gültige Templates:

Template Passt auf Pfad-Parameter
/orders /orders
/orders/{uid} /orders/4711 uid = 4711
/orders/{uid}/modules/{code} /orders/4711/modules/A1 uid = 4711, code = A1
/kalender/v1 /kalender/v1

Präzedenz bei mehreren Treffern

Passen mehrere Templates auf denselben Pfad, gewinnt das spezifischste – also das mit den meisten statischen Segmenten. So schlägt /orders/summary das Template /orders/{uid}, während /orders/4711 auf /orders/{uid} matcht.

Hauptfelder eines Endpunkts

Feld Spalte Zweck
Pfad-Template re_pathtemplate Maßgeblich fürs Routing. Vollständiger Pfad mit Platzhaltern, z. B. /orders/{uid}/modules/{code}
Server re_server Zuordnung zum Server-Profil (erforderlich)
Aktiv re_aktiv Statusflag; inaktive Endpunkte liefern 404
Skript re_script DwScript-Quelltext des Handlers (siehe Scripting)
WebHook re_webhook optional: Verweis auf einen Einmal-Endpunkt statt Skript
Info Dokumentations-Freitext
Datei-Upload re_upload Erlaubt Datei-Uploads an diesem Endpunkt (0 = aus, 1 = an). Ohne Freigabe werden Upload-Anfragen mit 415 abgelehnt.
Max. Upload-Grösse re_upload_size Maximale Dateigrösse in MB. Leer/0 = Standard 25 MB. Überschreitung wird mit 413 abgelehnt.

Pfad-Parameter im Skript

Die aus den Platzhaltern erfassten Werte stehen im Endpunkt-Skript als reservierte Parameter mit Präfix _OBS_PATH_ zur Verfügung:

function Get(oParams: TStrings; oBody: TJSONObject): string;
var cUid: string;
begin
    cUid := oParams.Values['_OBS_PATH_uid'];   // aus /orders/{uid}
    // ...
end;

Da der Präfix _OBS_ für von außen gelieferte Header/Query-Parameter gesperrt ist, können diese Werte nicht durch den Client überschrieben werden.

Datei-Uploads

Ein Endpunkt nimmt Datei-Uploads nur entgegen, wenn er dafür freigeschaltet ist (re_upload = 1). Andernfalls werden Upload-Anfragen mit 415 Unsupported Media Type abgelehnt und das Skript wird nicht ausgeführt.

Die maximal zulässige Dateigrösse wird pro Endpunkt über re_upload_size (in MB) festgelegt; ohne Angabe gilt der Standard von 25 MB. Wird das Limit überschritten, antwortet der Server mit 413 Payload Too Large. Für Uploads gilt nicht das JSON-Body-Limit (10 MB), sondern dieses Endpunkt-Limit. Der Originalname (beim resumable Upload über den Header Upload-Metadata) ist Pflicht; fehlt er, wird der Upload mit 413/400 abgelehnt. Dem Skript stehen Pfad, Name und Content-Type als _OBS_UPLOAD_*-Parameter zur Verfügung (Details: Scripting).

Unterstützt werden zwei Übertragungsarten:

  • Einfacher Upload per multipart/form-data (eine Datei pro Request).
  • Resumable/Chunked Upload per Content-Range (grosse Dateien, fortsetzbar nach Abbruch).

Der Server legt die hochgeladene Datei in einem temporären Verzeichnis ab und übergibt dem Endpunkt-Skript den Pfad. Was mit der Datei geschieht (Ablage, DMS-Verknüpfung, Weiterverarbeitung), entscheidet allein das Skript. Details und Beispiele: Scripting.

HTTP-Methode

Welche Funktion aufgerufen wird, ergibt sich aus dem HTTP-Verb: Der Server ruft die gleichnamige Skript-Methode auf (Get/Post/Put/Delete/Patch). Ein Template entspricht damit einem Endpunkt-Skript; unterschiedliche Pfad-Formen (z. B. /orders vs. /orders/{uid}) sind eigene Endpunkt-Einträge mit eigenem Skript und eigener Berechtigung.

URL-Struktur

http://[Host][:Port][Pfad-Template]

Beispiele:

Versionierung

Da es kein eigenes Versions-Feld mehr gibt, wird die Version als statisches Segment ins Template aufgenommen, z. B. /orders/v1 oder /v1/orders/{uid}. Änderung ohne Breaking Change:

  1. Bestehenden Endpunkt unverändert lassen.
  2. Neuen Endpunkt mit gleichem Ressourcennamen, aber neuem Versions-Segment im Template anlegen.
  3. Berechtigungen für neue Konsumenten setzen.
  4. Alten Endpunkt deaktivieren, wenn die Migration abgeschlossen ist.

Zugriffskontrolle

Endpunkte sind Server-Profilen zugeordnet; ein Zugang benötigt eine explizite Berechtigung (Tabelle RESTSRV_ACCESS), um einen Endpunkt nutzen zu dürfen. Weil jede Pfad-Form ein eigener Endpunkt-Eintrag ist, lässt sich der Zugriff pro Pfad-Form granular vergeben (z. B. Lesen von /orders/{uid} erlauben, aber das ändernde PUT /orders/{uid}/modules/{code} nicht).

Caching

Die Endpunkt-Definitionen werden pro Server-Profil zwischengespeichert (TTL, Standard 60 s). Neue oder geänderte Endpunkte/Templates werden daher erst nach Ablauf des Caches (bzw. nach einer Cache-Invalidierung) wirksam – nicht zwingend sofort.

HTTP-Fehlercodes

Code Ursache
404 Kein Template passt zum Pfad, Endpunkt inaktiv oder falsches Server-Profil
403 Zugang fehlt in der Berechtigungsliste
401 API-Key ungültig/fehlend, JWT abgelaufen oder Sitzung gesperrt (AUTH_EXPIRED)
500 Skript- oder Syntax-Fehler (Details in RESTSRV_PROTO)
415 Datei-Upload an einen Endpunkt, der dafür nicht freigeschaltet ist (re_upload = 0)
413 Hochgeladene Datei überschreitet die zulässige Maximalgrösse (re_upload_size)
429 Rate-Limit überschritten; die Antwort enthält den Header Retry-After
503 Eine Anfrage mit demselben Idempotency-Key wird gerade verarbeitet; die Antwort enthält Retry-After
409 Ein früherer Aufruf mit demselben Idempotency-Key ist ohne Ergebnis geblieben (IDEMPOTENCY_UNRESOLVED)
422 Derselbe Idempotency-Key wurde mit anderem Inhalt gesendet (IDEMPOTENCY_KEY_REUSED)
400 Die Anfrage wurde unverschlüsselt an einen TLS-Port geschickt (http statt https). Die Abweisung erfolgt vor Authentifizierung und Endpunkt-Skript

Jede Fehlerantwort besteht aus einem error-Objekt mit maschinenlesbarem Code - Aufbau siehe Übersicht.

Daneben kann ein Endpunkt-Skript den Statuscode selbst setzen (z.B. 201, 204, 409, 422) sowie Response-Header wie ETag oder Location - siehe Scripting.

Idempotenz

Schickt ein Konsument bei POST, PUT, PATCH oder DELETE den Header Idempotency-Key, sorgt der Server selbst dafür, dass eine wiederholte Sendung keine Zweitwirkung hat. Das gilt für jeden Endpunkt - es muss weder am Endpunkt etwas eingestellt noch im Skript etwas programmiert werden.

Situation Antwort des Servers
Erster Aufruf Endpunkt läuft normal, das Ergebnis wird zum Schlüssel gespeichert
Wiederholung, gleicher Inhalt Gespeicherte Antwort (gleicher Statuscode, gleicher Body, gleiche Header) plus Header Idempotent-Replay: true. Das Skript läuft nicht
Wiederholung, anderer Inhalt 422 IDEMPOTENCY_KEY_REUSED - derselbe Schlüssel für einen anderen Inhalt ist ein Client-Fehler
Erster Aufruf läuft noch 503 IDEMPOTENCY_IN_PROGRESS mit Retry-After. Beim nächsten Versuch liegt die gespeicherte Antwort vor
Früherer Aufruf ohne Ergebnis 409 IDEMPOTENCY_UNRESOLVED. Der Dienst wurde zwischen Verarbeitung und Festschreiben unterbrochen; ob die Buchung stattgefunden hat, ist unbekannt und von Hand zu klären

Wichtig für die Auslegung eines Endpunkts:

  • Antwortet das Skript mit 2xx, wird die Antwort gespeichert und bei einer Wiederholung erneut ausgeliefert.
  • Antwortet das Skript mit 4xx (fachliche Ablehnung), wird der Schlüssel wieder freigegeben - der Konsument darf ihn nach Korrektur erneut verwenden. Sonst würde ein einziger Validierungsfehler den Schlüssel dauerhaft blockieren.
  • Endet die Verarbeitung mit 5xx oder einem Skript-Fehler, bleibt der Schlüssel belegt und der Fall wird protokolliert. Das ist Absicht: lieber ein Fall für den Support als eine mögliche Doppelbuchung.

Der Schlüssel gilt je Zugang, Methode und Pfad. Derselbe Idempotency-Key an einem anderen Endpunkt ist damit ein eigener Vorgang - der Konsument muss ihn nicht global eindeutig vergeben, aber pro Vorgang stabil wiederverwenden (also nicht bei jedem Wiederholversuch neu erzeugen).

Die Einträge stehen in RESTSRV_IDEMPOTENCY und werden nach 30 Tagen automatisch aufgeräumt. Einträge ohne Ergebnis werden nicht automatisch gelöscht, sondern im Protokoll gemeldet.

WebHooks

WebHooks sind Einmal-Endpunkte für asynchrone Callbacks. Beim ersten erfolgreichen Aufruf wird die Antwort in der Tabelle REMOTE_HOOK_URL gespeichert und der Endpunkt anschließend automatisch gelöscht.

Typischer Einsatz: OBS stösst einen Vorgang bei einem Fremdsystem an (Bezahldienst, Versanddienstleister) und gibt diesem eine Rückruf-Adresse mit, die nur ein einziges Mal gültig ist. Damit kann die Adresse nicht später erneut - oder von jemand anderem - benutzt werden.

Ablauf:

  1. OBS legt einen Eintrag in REMOTE_HOOK_URL an und dazu einen Endpunkt, dessen Feld WebHook (re_webhook) auf diesen Eintrag zeigt. Ein Skript wird für diesen Endpunkt nicht gepflegt.
  2. Die Adresse dieses Endpunkts wird dem Fremdsystem als Callback-URL übergeben.
  3. Das Fremdsystem ruft die Adresse auf. Der Server legt den übergebenen Inhalt in REMOTE_HOOK_URL.hu_response ab, antwortet mit {"status": "ok"} und löscht den Endpunkt.
  4. Der weiterverarbeitende OBS-Prozess findet die Rückmeldung in hu_response.
HINWEIS: Ein zweiter Aufruf derselben Adresse läuft ins Leere: Der Endpunkt

existiert nicht mehr, die Antwort ist 404. Das ist gewollt - ein WebHook ist keine dauerhafte Schnittstelle. Für eine dauerhaft erreichbare Rückmelde-Adresse einen

normalen Endpunkt mit Skript anlegen.