Zum Inhalt springen

Daten schreiben

Kurzantwort: POST /create legt an, PUT /update/{id} ersetzt das ganze Objekt, PATCH /update/{id} ändert nur die genannten Felder, DELETE /delete/{id} löscht. Der Unterschied zwischen PUT und PATCH ist die mit Abstand häufigste Fehlerquelle: Was in einem PUT fehlt, wird geleert.


POST /crm/customer/create
{
"data": { "name": "Muster GmbH", "email": "info@muster.de" },
"response": ["id", "name"]
}
  • Keine id mitschicken — die vergibt der Server.
  • Die Antwort enthält genau die Felder aus response; nehmen Sie mindestens id auf, sonst kennen Sie das angelegte Objekt nicht.
PUT /crm/customer/update/{id}
{
"data": {
"id": "5a2b…",
"name": "Muster GmbH",
"email": "neu@muster.de",
"phone": "+49 …"
},
"response": ["+"]
}

id ist Pflicht. Der Payload beschreibt den vollständigen Zielzustand:

Feldartfehlt im PayloadWert im Payload
einfaches Feldwird geleertwird gesetzt
Referenzwird gelöst (bei abhängigen Kindern: gelöscht)wird gesetzt
Listealle Mitglieder werden entferntwird zum Zielzustand

PUT unterscheidet nicht zwischen „Feld weggelassen” und „Feld auf null” — beides bedeutet leeren.

PATCH /crm/customer/update/{id}
{
"data": { "id": "5a2b…", "email": "neu@muster.de" },
"response": ["+"]
}
Feldartfehltist nullhat einen Wert
einfaches Feldunverändertwird geleertwird gesetzt
Referenzunverändertwird gelöst bzw. das abhängige Kind gelöschtwird gesetzt
Listeunverändertalle Mitglieder entferntwird zum Zielzustand, [] leert
// FALSCH — leert alles, was das Formular nicht gesetzt hat
const payload = { ...leeresFormularmodell, id, email: 'neu@muster.de' };
await patch(payload);

Ein Objekt mit lauter undefined-Feldern wird beim Serialisieren zu lauter null-Feldern — und null bedeutet in PATCH leeren. Das trifft jedes generierte Modell, jedes Formularobjekt, jede Klasse mit Standardwerten.

// RICHTIG — nur nennen, was sich ändert
await patch({ id, email: 'neu@muster.de' });

Faustregel: Bauen Sie den PATCH-Körper aus den tatsächlich geänderten Feldern, nie aus einem vollständigen Objekt. Wollen Sie ein ganzes Formular speichern, nehmen Sie PUT — dort ist das vollständige Objekt die richtige Aussage.

flowchart TB
    A["Was wollen Sie tun?"] --> B{"Beschreibt Ihr Payload<br/>das ganze Objekt?"}
    B -->|ja, Formular vollständig| PUT["PUT /update/{id}"]
    B -->|"nein, einzelne Felder"| PATCH["PATCH /update/{id}"]
    A --> C{"Objekt existiert schon?"}
    C -->|nein| CREATE["POST /create"]
    C -->|"unbekannt"| D["im Client entscheiden:<br/>id vorhanden? → PUT/PATCH<br/>sonst → create"]

Einen save-Endpunkt, der beides erledigt, gibt es nicht.

Verbso geht es
PUTFeld weglassen oder auf null setzen
PATCHFeld ausdrücklich auf null setzen

Bei PATCH ist das Weglassen genau das Gegenteil — es lässt das Feld in Ruhe.

DELETE /crm/customer/delete/{id}

Kein Körper, keine Antwortdaten. Was dabei zusätzlich passiert:

  • Abhängige Kinder werden mitgelöscht (wenn das Modell sie so verknüpft).
  • Nicht abhängige Beziehungen werden nur gelöst.
  • Dateien des Objekts werden im Speicher entfernt, samt aufbewahrter Versionen.
  • Ist das Modell auditiert, bleibt die Historie lesbar — die Löschung selbst ist eine Revision mit Urheber und Zeitpunkt.

Verstöße kommen gesammelt als 422 mit Feldpfaden:

{
"error": "ApiValidationException",
"code": "422",
"violations": [
{ "field": "name", "rule": "cannot-be-null" },
{ "field": "orders.0.total", "rule": "min-number" }
]
}

Sie können die Liste direkt auf Ihre Formularfelder abbilden — der Pfad enthält auch die Verschachtelung. Mögliche Regeln: cannot-be-null, cannot-be-empty, too-long, pattern-mismatch, min-number, max-number.

Geprüft wird immer nur, was die Operation auch schreibt: Ein PATCH validiert ausschließlich die gesendeten Felder.

Es gibt weder ETag noch Versionsfeld. Zwei Clients, die dasselbe Objekt lesen, ändern und zurückschreiben, überschreiben einander — der letzte gewinnt.

Was hilft:

  • PATCH statt PUT, wenn Sie nur einzelne Felder ändern. Dann kollidieren Sie nur mit jemandem, der dasselbe Feld anfasst.
  • Fachliche Prüfungen im Backend, wenn das Risiko real ist.