Ressourcen erstellen & aktualisieren
Diese Seite beschreibt das Schreibmodell der REST-API: wie sich Erstellungen, partielle Aktualisierungen, vollständige Ersetzungen, das Leeren von Feldern und die Nebenläufigkeitskontrolle verhalten. Es ist der Kontrakt, dem jeder Schreib-Endpoint folgt.
:::note Ziel-Kontrakt
Dies beschreibt den beabsichtigten Schreibkontrakt für /api/v2. Die meisten Ressourcen folgen
ihm bereits; einige ältere Endpoints werden noch angeglichen. Wenn das Verhalten eines Endpoints von
dem hier Beschriebenen abweicht, ist das hier Beschriebene die Zielrichtung — melden Sie es als Bug.
:::
Ressourcen erstellen (POST)
Erstellen Sie eine Ressource per POST an ihre Collection. Bei Erfolg liefert die API
201 Created mit der vollständigen erstellten Ressource im Body:
curl -X POST "https://api.tourfold.com/api/v2/areas" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Wien Nord",
"color": "#3366FF",
"description": "Gebiet von Alpine Facility Services nördlich der Donau"
}'
{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"name": "Wien Nord",
"color": "#3366FF",
"description": "Gebiet von Alpine Facility Services nördlich der Donau",
"lock_version": 0
}
Jede 201 Created-Antwort enthält außerdem einen absoluten Location-Header mit der kanonischen
URL der neu erstellten Ressource:
Location: https://api.tourfold.com/api/v2/areas/a1b2c3d4-e5f6-4a1b-8c9d-123456789abc
Bei einer Batch-Erstellung mehrerer Ressourcen verweist Location auf die Collection, da es keine
einzelne kanonische Ressourcen-URL gibt.
Partielle Aktualisierungen (PATCH)
Aktualisierungen erfolgen als PATCH mit partieller (Merge-)Semantik — Sie senden nur die Felder,
die Sie ändern möchten. Dies folgt RFC 7386 JSON Merge Patch:
- Ein aus dem Request-Body weggelassenes Feld bleibt unverändert.
- Für leerbare optionale Felder leert ein explizites
nullden gespeicherten Wert (siehe unten). - Validierungs- und Eindeutigkeitsprüfungen laufen nur für die von Ihnen gesendeten Felder.
Senden Sie Content-Type: application/merge-patch+json. Derselbe Body wird auch als
application/json akzeptiert (ein Alias mit identischer Weglassen/null-Semantik), damit
generische HTTP-Clients weiter funktionieren.
# Das Gebiet umbenennen, Farbe und Beschreibung unberührt lassen
curl -X PATCH "https://api.tourfold.com/api/v2/areas/a1b2c3d4-e5f6-4a1b-8c9d-123456789abc" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/merge-patch+json" \
-d '{ "name": "Wien Nord und Zentrum" }'
Ein optionales Feld leeren (null)
Für Felder, die optional und leerbar sind, senden Sie ein explizites null, um den gespeicherten
Wert zu entfernen. Das Weglassen des Felds lässt es unverändert; nur ein explizites null leert es.
# Die Beschreibung leeren, alles andere beibehalten
curl -X PATCH "https://api.tourfold.com/api/v2/areas/a1b2c3d4-e5f6-4a1b-8c9d-123456789abc" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/merge-patch+json" \
-d '{ "description": null }'
Felder, die erforderlich sind, können auf diese Weise nicht geleert werden. Das Senden von null
für ein erforderliches Feld (oder für ein Feld, das für eine abhängige Operation erforderlich ist, etwa
ein abrechnungsrelevantes Rechnungsfeld) liefert 422 Unprocessable Entity mit einem problem+json-Body,
statt es stillschweigend zu ignorieren.
Vollständige Ersetzung (PUT)
PUT wird nur dort verwendet, wo die deklarative Ersetzung einer ganzen Menge der Kontrakt ist —
nicht als allgemeines Aktualisierungs-Verb. Wo ein PUT-Endpoint existiert, ersetzt er die gesamte
Zielmenge: Der von Ihnen gesendete Body wird zum neuen Zustand, und alles, was im Body fehlt, wird
entfernt. Ein leeres Array leert die Menge.
# Die Fähigkeiten eines Benutzers vollständig ersetzen — [] entfernt alle Fähigkeiten
curl -X PUT "https://api.tourfold.com/api/v2/users/{user_id}/skills" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"skill_ids": [
"00000000-0000-4000-8000-000000005101",
"00000000-0000-4000-8000-000000005102"
]
}'
Um Jonas' gesamte Fähigkeitsmenge zu leeren, ersetzen Sie sie durch eine leere Menge:
curl -X PUT "https://api.tourfold.com/api/v2/users/{user_id}/skills" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "skill_ids": [] }'
Wenn Sie ein einzelnes Attribut einer Ressource ändern möchten, verwenden Sie PATCH auf der Ressource.
Greifen Sie nur dann zu PUT, wenn der Endpoint explizit eine Mengen-Ersetzung (z. B. Tags, Fähigkeiten)
oder eine deklarative Schema-Ersetzung ist.
Unveränderliche Felder
Einige Felder werden bei der Erstellung festgelegt und können bei einer Aktualisierung nicht geändert
werden (zum Beispiel der type eines SMS-Gateways). Das Senden eines Werts, der dem gespeicherten
widerspricht, wird mit 422 abgelehnt, statt stillschweigend ignoriert zu werden, damit Sie nie
glauben, eine Änderung sei wirksam geworden, obwohl sie es nicht ist.
Optimistische Nebenläufigkeit (lock_version)
Jede beschreibbare Ressource stellt eine lock_version-Ganzzahl bereit, die bei jedem erfolgreichen
Schreibvorgang hochgezählt wird. Um verlorene Aktualisierungen zu verhindern, wenn mehrere Clients
dieselbe Ressource bearbeiten, fügen Sie die zuletzt gelesene lock_version in Ihren Schreib-Body ein:
curl -X PATCH "https://api.tourfold.com/api/v2/areas/a1b2c3d4-e5f6-4a1b-8c9d-123456789abc" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Wien Nord und Zentrum", "lock_version": 3 }'
- Wenn die übergebene
lock_versionmit der gespeicherten Version übereinstimmt, wird der Schreibvorgang ausgeführt und die Version erhöht. - Wenn sie nicht übereinstimmt (jemand hat zwischenzeitlich geschrieben), liefert die API
409 Conflictmit dem Problemtypresource-conflict. Lesen Sie die Ressource erneut, führen Sie die Änderungen zusammen und versuchen Sie es erneut. lock_versionist optional: Lassen Sie es weg (oder senden Sienull), um die Prüfung zu überspringen und ein Last-Write-Wins-Update durchzuführen.- Löschungen nehmen niemals eine
lock_versionentgegen.DELETE-Anfragen haben keinen Body; eine Löschung wird immer bedingungslos auf die aktuell gespeicherte Version angewendet. - Ausnahme — Workspace-Einstellungs-Singletons: einige kleine Konfigurations-Endpoints
(
/document-management/settings,/mcp/settings,/ai-assistant/settingsund/geoservices/settings) haben keinelock_versionund wenden immer Last-Write-Wins an. Jeder davon ist eine einzelne Zeile pro Workspace, die von einem Administrator über einen dedizierten Schalter bearbeitet wird — es gibt also kein Szenario konkurrierender verlorener Updates./tenantund/billing/profilesind ebenfalls Singletons, haben aber sehr wohl einelock_version, weil sie zusammengesetzte Datensätze sind, die von mehreren Admins bearbeitet werden.
Erfolgsstatus und Form der Antwort
Erstellungs- und Aktualisierungs-Endpoints geben nach dem Schreibvorgang die vollständige Ressource
zurück, sodass Sie den resultierenden Zustand (einschließlich der neuen lock_version) stets ohne
ein nachfolgendes GET sehen. Eine synchrone Operation, die eine Repräsentation zurückgibt,
verwendet 200 OK (beziehungsweise 201 Created bei einer Erstellung).
Eine Operation, die erfolgreich abgeschlossen wird und absichtlich keine
Antwortrepräsentation besitzt, liefert 204 No Content mit leerem Body. Dies ist der übliche
Kontrakt für Löschungen und bodylose Aktionen wie Zuordnungen aufheben, entfernen oder
deaktivieren. Gibt eine Löschung dagegen bewusst die gelöschte Ressource oder ein aktualisiertes
Aggregat zurück, verwendet sie 200 OK; 204 wird nicht mechanisch auf jedes DELETE angewendet.
Zur asynchronen Verarbeitung angenommene Arbeit verwendet 202 Accepted. Eingehende
Webhook-Endpoints folgen dem Bestätigungs-Kontrakt des Absenders — üblicherweise einem
ausdrücklichen 200 oder 202 — und werden nicht allein aus Gründen der Einheitlichkeit auf 204
geändert.
Antworten lassen Felder ohne Wert weg — ein soeben mit null geleertes Feld kommt also
fehlend zurück, nicht als "field": null. Behandeln Sie einen fehlenden Schlüssel als „nicht
gesetzt". Die vollständige Konvention finden Sie unter
Grundlagen → Optionale Felder und null, die gemeinsamen
JSON-Konventionen (snake_case-Schlüssel, RFC-3339-Zeitstempel, UUID-Bezeichner) unter
Grundlagen und das problem+json-Fehlerformat unter Fehler.
Feldtyp-Konflikte
Ein Anfragefeld, dessen Wert den falschen JSON-Typ oder die falsche Struktur hat — ein String, wo
eine Zahl erwartet wird, 1.5 für ein Integer-Feld, ein Objekt, wo ein Array erwartet wird — wird
mit 422 Unprocessable Content abgelehnt, Problemtyp field-type-invalid, samt einem
errors[].pointer, der das betroffene Feld benennt (z. B. #/lock_version, #/tag_ids/0). Dies ist
dieselbe errors[]-Struktur wie bei jeder anderen Feldvalidierung, sodass Sie die Meldung ohne
Sonderbehandlung an das Eingabefeld binden können. Ein Body, der überhaupt kein gültiges JSON ist
(ein Syntaxfehler, eine abgeschnittene Nutzlast), ergibt stattdessen 400 Bad Request.