Änderungen in der Codenica API

Um Änderungen über die Codenica API zu bearbeiten, erstellen Sie zuerst einen Schlüssel in den Codenica-Einstellungen. Wenn Sie noch keinen Schlüssel erstellt haben, öffnen Sie Codenica API - Einführung in einem neuen Tab. Dort werden die Schlüsselerstellung, die sichere Aufbewahrung des Secrets und die gemeinsamen Authentifizierungsregeln erklärt.

Der technische Modulname lautet changes, der Typ eines einzelnen Objekts ist change. Eine Änderung dient dazu, eine geplante Anpassung an einem Service, der Infrastruktur oder einer Konfiguration zu planen und zu steuern. Neben den Grunddaten enthält sie Planungsfelder wie Termine, Risiko, Auswirkung, Rollout-Plan, Backout-Plan und Änderungsgrund.

Die folgenden Abschnitte zeigen den vollständigen Ablauf: Schema und Wörterbücher prüfen, Listen abrufen, filtern, erstellen, mit ETag aktualisieren, Batch-Operationen, Beziehungen, Benutzer, Dateien, Workflow-Aktionen, Genehmigungen und Löschen.

Die Beispiele verwenden das Präfix PUBLIC-API-CHANGE-20260905130127. Ersetzen Sie es in Ihrer Integration durch eine eigene Kennung und passen Sie E-Mail-Adressen, IDs und Feldwerte an Ihre Datenbank an.


Änderungen - API-Adresse und Auswahl der Installation

Alle Routen für Änderungen beginnen mit:

{BASE_URL}/api/v1/changes

Verwenden Sie in Codenica Cloud die öffentliche Domain Ihrer Installation:

export BASE_URL="https://ihr-unternehmen.codenica.com"

In der standardmäßigen On-Premise-Installation registriert Codenica Discovery den lokalen Dienst unter:

export BASE_URL="http://codenica.local:5150"

Wenn der Administrator die On-Premise-Installation unter einer Firmendomain, über einen Reverse Proxy, mit HTTPS oder an einem anderen Port veröffentlicht hat, verwenden Sie die für diese Installation mitgeteilte genaue Adresse:

export BASE_URL="https://api.ihr-unternehmen.example"

Verwenden Sie localhost nicht, wenn das integrierte Programm auf einem anderen Computer als die API läuft. Senden Sie tenantId weder im Body noch in der Query-Zeichenfolge. Die richtige Datenbank wird anhand der Hostadresse ausgewählt, mit der die Integration eine Verbindung herstellt.


Änderungen - API-Schlüssel und Lizenzgrenzen

Erstellen Sie den API-Schlüssel in Codenica unter Einstellungen - API - API Keys. Das Secret wird nur einmal direkt nach der Erstellung oder Rotation des Schlüssels angezeigt. Speichern Sie dann Client ID und Client Secret im sicheren Secret-Speicher Ihrer Integration.

Codenica API ist mit den Lizenzen Plus und Enterprise verfügbar. Plus erlaubt bis zu 50 aktive Schlüssel, Enterprise bis zu 100. Starter enthält keine Codenica API. Erstellen Sie für jede Anwendung und jede Umgebung einen eigenen Schlüssel. So können Sie Berechtigungsbereiche, Secret-Rotation und Zugriff unabhängig voneinander verwalten.

Wählen Sie nur die Berechtigungen aus, die für die Arbeit mit Änderungen erforderlich sind. Eine Integration, die ausschließlich liest, kann changes:read verwenden. Für das Erstellen von Genehmigungen und das Verarbeiten von Entscheidungen sind zusätzlich Bereiche des Moduls approvals erforderlich.


Änderungen - Authentifizierung und sichere Anfragen

Authentifizieren Sie jede Anfrage an die öffentliche API mit den beiden Schlüssel-Headern:

export CLIENT_ID="cna_ihre_client_id"
export CLIENT_SECRET="cns_ihr_client_secret"

curl --request GET "$BASE_URL/api/v1/changes?page=1&pageSize=25" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Eine externe Integration benötigt weder das JWT eines Administrators noch Cookies des Codenica-Panels. Speichern Sie den Schlüssel nicht in einem Repository, in an den Browser ausgeliefertem Code, in einer URL, in der Befehlschronik oder in Logs. Außerhalb lokaler Tests sollte HTTPS verwendet werden.

Übernehmen Sie meta.requestId aus jeder Antwort. Diese Kennung hilft bei der Diagnose einer konkreten Anfrage, ersetzt aber nicht die ID der Änderung und darf nicht als Secret verwendet werden.


Änderungen - Verbindungskontext prüfen

Lesen Sie vor dem ersten Schreibvorgang den Kontext. Damit prüfen Sie, ob die Adresse zur richtigen Datenbank führt und der ausgewählte Schlüssel die benötigten Berechtigungsbereiche besitzt:

curl --request GET "$BASE_URL/api/v1/context" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Prüfen Sie:

  • data.apiVersion und data.contractVersion;
  • data.tenant.id und data.tenant.resolvedDomain;
  • data.caller.authentication mit dem Wert api_key;
  • changes in data.capabilities.resources;
  • die dem Schlüssel zugewiesenen Bereiche;
  • Seiten-, Batch-, Datei- und Anfragegrenzen.

Wenn der Kontext eine andere Datenbank ausweist oder ein benötigter Bereich fehlt, stoppen Sie die Integration und korrigieren Sie Adresse oder Schlüssel. Bereiche können nicht mit einer einzelnen Anfrage erteilt werden.


Änderungen - Berechtigungsbereiche

Für die vollständige Arbeit mit Änderungen werden die Bereiche benötigt, die den verwendeten Operationen entsprechen:

changes:read
changes:write
changes:delete
changes:schema
changes:stats
changes:relationships:read
changes:relationships:write
changes:users:read
changes:users:write
changes:files:read
changes:files:write
changes:technical:read
changes:technical:write
changes:pin:write
changes:spam:write
changes:reopen:write
changes:rating:write
changes:escalation:write
changes:approval:write

Für das reine Lesen genügt changes:read. Schema und Statistiken benötigen changes:schema beziehungsweise changes:stats. Für das Lesen von Beziehungen, Benutzern und Dateien sind die entsprechenden Bereiche :relationships:read, :users:read und :files:read erforderlich. Schreibvorgänge verwenden die passenden :write-Bereiche.

Wenn die Integration Genehmigungen erstellt, liest, ändert oder löscht, ergänzen Sie:

approvals:read
approvals:write
approvals:delete
approvals:relationships:read
approvals:relationships:write
approvals:technical:read
approvals:technical:write

Beziehungen zu anderen Modulen erfordern außerdem den Lesezugriff auf das Zielmodul, zum Beispiel assets:read, documents:read, tickets:read, problems:read oder releases:read. Vergeben Sie Bereiche nach dem Prinzip der geringsten Berechtigung.


Änderungen - Schema und Planungsfelder

Das Schema zeigt, welche Felder in Ihrer Datenbank gelesen und geschrieben werden können. Rufen Sie es ab, bevor Sie den Request-Body erstellen:

curl --request GET "$BASE_URL/api/v1/changes/schema" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Prüfen Sie für jedes Feld unter anderem readable, writable, required, technical, unique, maxLength und die Regeln für die automatische Generierung. Das Schema liefert außerdem die verfügbaren Beziehungsziele.

Für die Erstellung einer Änderung sind aktuell mindestens subject und requesterEmail erforderlich. Die weiteren Felder hängen von Konfiguration und Prozess ab:

Gruppe
Beispielfelder
Verwendung
Grunddaten
subject, requesterEmail, description, comments
Beschreibung und Anfragender
Klassifikation
type, status, priority, impact, urgency, severity
Bearbeitung und Auswirkungsbewertung
Planung
datePlannedStart, datePlannedEnd, risk, impactInfo, rolloutPlan, backoutPlan, reasonForChange
Termine, Risiko und Umsetzung
Integration
source, externalNumber, referenceNumber, services, tags
Verknüpfung mit einem anderen System
Kosten
currency, estimatedCost, totalValue
Finanzwerte

Lesen Sie Werte aus Wörterbüchern wie Status, Priorität, Typ und Risiko aus dem Schema oder über den Endpoint values. Senden Sie Datumswerte im ISO-8601-Format und Zahlen als JSON-Zahlen. Gehen Sie nicht davon aus, dass die Wörterbücher in zwei Datenbanken identisch sind.

{
  "datePlannedStart": "2030-01-15T09:00:00Z",
  "datePlannedEnd": "2030-01-15T17:00:00Z",
  "risk": "Medium",
  "impactInfo": "Geplante Auswirkungsbewertung",
  "rolloutPlan": "Führen Sie die Bereitstellung aus und prüfen Sie die Zustandskontrollen.",
  "backoutPlan": "Stellen Sie die vorherige Version wieder her, wenn die Prüfung fehlschlägt.",
  "reasonForChange": "Für die aktuelle Plattformversion ist eine kontrollierte Aktualisierung erforderlich."
}

Änderungen - wichtigste Endpoints

Die am häufigsten verwendeten Routen für Änderungen sind:

  • GET /api/v1/changes - Liste der Änderungen;
  • GET /api/v1/changes/{id} - einzelne Änderung;
  • POST /api/v1/changes - Erstellung;
  • PATCH /api/v1/changes/{id} - teilweise Aktualisierung;
  • DELETE /api/v1/changes/{id} - Löschen;
  • GET /api/v1/changes/schema - Schema für Felder und Beziehungen;
  • GET /api/v1/changes/stats - Statistiken;
  • GET /api/v1/changes/values - Werte für Filter;
  • POST /api/v1/changes:batch - Erstellen, Aktualisieren und Löschen.

Beziehungen, Benutzer, Dateien, Workflow-Aktionen und Genehmigungen haben eigene Routen. Dadurch kann eine Integration genau die benötigten Berechtigungen erhalten.


Änderungen - Listen und Seitennavigation

Rufen Sie Listen seitenweise ab. Geben Sie auch bei einer kleinen Sammlung Seitennummer und Seitengröße ausdrücklich an:

curl --request GET "$BASE_URL/api/v1/changes?page=1&pageSize=25" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Die Antwort enthält data.items sowie page, pageSize, totalItems, totalPages und hasNextPage. Rufen Sie weitere Seiten ab, solange hasNextPage den Wert true hat:

curl --request GET "$BASE_URL/api/v1/changes?page=2&pageSize=25&sort=dateUpdated&direction=desc" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Für die Synchronisation ist es sinnvoll, nach dateUpdated zu sortieren und die zuletzt verarbeiteten Datensätze zu speichern. Setzen Sie pageSize nicht höher als das im Kontext zurückgegebene Limit.


Änderungen - Suche, Filter und Sortierung

Listenparameter können kombiniert werden. Dieses Beispiel sucht einen bestimmten Datensatz, begrenzt ihn auf den Typ change und das Risiko Medium und sortiert nach dem Aktualisierungsdatum:

curl --get "$BASE_URL/api/v1/changes" \
  --data-urlencode "itemType=change" \
  --data-urlencode "customId=PUBLIC-API-CHANGE-20260905130127-SOURCE" \
  --data-urlencode "risk=Medium" \
  --data-urlencode "sort=dateUpdated" \
  --data-urlencode "direction=desc" \
  --data-urlencode "page=1" \
  --data-urlencode "pageSize=25" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Für die regelmäßige Synchronisation können außerdem status, priority, subject, requesterEmail, source, externalNumber, referenceNumber, datePlannedStart, datePlannedEnd, createdAfter, createdBefore, updatedAfter und updatedBefore verwendet werden, sofern sie im aktuellen Vertrag verfügbar sind.

Kodieren Sie Textwerte und Datumswerte URL-gerecht. Verwenden Sie search für eine allgemeine Suche und den vom Schema unterstützten feldbezogenen Parameter für einen gezielten Filter. Nehmen Sie nicht an, dass jeder Wörterbuchwert einen englischen Namen hat.


Änderungen - Felder auswählen und Daten einbeziehen

Mit fields begrenzen Sie die Antwort auf die für die Integration benötigten Eigenschaften. Mit include fügen Sie verbundene Daten hinzu:

curl --get "$BASE_URL/api/v1/changes/PUBLIC_CHANGE_UUID" \
  --data-urlencode "fields=subject,requesterEmail,status,priority,risk,datePlannedStart,datePlannedEnd" \
  --data-urlencode "include=files,relationships,users" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Für das vollständige Modell können Sie fields=* verwenden. Das Einbeziehen von Dateien, Beziehungen und Benutzern erfordert die jeweiligen Lesebereiche. fields umgeht keine Zugriffskontrolle und macht keine technischen Felder sichtbar, für die der Schlüssel keine Berechtigung besitzt.

Achten Sie in der Antwort auf data.id, data.itemType, data.attributes und data.meta. Lesen Sie technische Felder wie pin oder isSpam, ändern Sie sie aber über die weiter unten beschriebenen eigenen Aktionen.


Änderungen - Statistiken und Wörterbuchwerte

Mit Statistiken können Sie zum Beispiel Änderungen nach Risiko zählen. Diese Leseoperation verändert keine Datensätze:

curl --get "$BASE_URL/api/v1/changes/stats" \
  --data-urlencode "field=risk" \
  --data-urlencode "limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Wenn Sie Filterauswahlfelder aufbauen, rufen Sie die Feldwerte separat ab:

curl --get "$BASE_URL/api/v1/changes/values" \
  --data-urlencode "field=risk" \
  --data-urlencode "search=Medium" \
  --data-urlencode "limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Lesen Sie zuerst das Wörterbuch und senden Sie den zurückgegebenen Wert erst danach im Body. Dies ist besonders für risk, status, priority und type wichtig, weil ihre Werte von Sprache und Einstellungen der jeweiligen Datenbank abhängen können.


Änderungen - Datensatz erstellen

Erstellen Sie eine Änderung mit POST /api/v1/changes. Legen Sie den technischen Typ change und die beschreibbaren Felder in attributes ab. Das folgende Beispiel enthält Grunddaten, Klassifikation, Integrationsinformationen und die vollständige Planungsgruppe:

export IDEMPOTENCY_KEY="public-api-change-create-20260905130127"

curl --request POST "$BASE_URL/api/v1/changes" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data-raw '{
    "itemType": "change",
    "attributes": {
      "customId": "PUBLIC-API-CHANGE-20260905130127-SOURCE",
      "subject": "PUBLIC-API-CHANGE-20260905130127 Integrationsanfrage",
      "requesterEmail": "[email protected]",
      "description": "Durch den Changes-Ablauf der öffentlichen API erstellt",
      "comments": "ITSM-Integrationsänderung",
      "source": "Public API",
      "type": "Standard",
      "status": "Closed",
      "priority": "High",
      "impact": "Medium",
      "urgency": "High",
      "severity": "High",
      "services": "Codenica Public API",
      "tags": "public-api,change",
      "externalNumber": "EXT-PUBLIC-API-CHANGE-20260905130127",
      "referenceNumber": "REF-PUBLIC-API-CHANGE-20260905130127",
      "currency": "PLN",
      "estimatedCost": 12.5,
      "totalValue": 12.5,
      "datePlannedStart": "2030-01-15T09:00:00Z",
      "datePlannedEnd": "2030-01-15T17:00:00Z",
      "risk": "Medium",
      "impactInfo": "Geplante Auswirkungsbewertung für die Integrationsanfrage",
      "rolloutPlan": "Führen Sie die genehmigte Änderung aus und prüfen Sie die Zustandskontrollen.",
      "backoutPlan": "Stellen Sie die vorherige Version wieder her, wenn die Prüfung fehlschlägt.",
      "reasonForChange": "Für die aktuelle Plattformversion ist eine kontrollierte Aktualisierung erforderlich."
    }
  }'

Eine erfolgreiche Anfrage liefert 201 Created. Speichern Sie data.id, den ETag aus dem HTTP-Header und data.meta.etag. Die optionale Eigenschaft customValues ist für benutzerdefinierte Felder vorgesehen, wenn die Integration deren Konfiguration kennt.

Wenn die Datenbank andere Wörterbuchwerte verlangt, übernehmen Sie die oben genannten Namen nicht ungeprüft, sondern kontrollieren Sie Schema und Endpoint values.


Änderungen - sichere Wiederholungen mit Idempotency-Key

Senden Sie bei jeder datenändernden Operation einen eindeutigen Idempotency-Key. Wenn die Antwort wegen einer Netzwerkunterbrechung verloren geht, wiederholen Sie exakt dieselbe Anfrage mit demselben Schlüssel:

curl --request POST "$BASE_URL/api/v1/changes" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-change-create-20260905130127" \
  --data-binary @change.json

Idempotenz sorgt dafür, dass eine identische Wiederholung das Ergebnis der ursprünglichen Operation zurückgibt, statt eine zweite Änderung zu erstellen. Derselbe Schlüssel darf nicht mit einem anderen Body verwendet werden. Erzeugen Sie für eine neue Änderung, Aktualisierung, Beziehung, Datei oder Aktion einen neuen Schlüssel.

Idempotenz ersetzt den ETag nicht. Bei Operationen mit Versionskontrolle senden Sie gleichzeitig den aktuellen If-Match-Wert.


Änderungen - Datensatz und ETag lesen

Lesen Sie nach der Erstellung oder dem Auffinden einer ID eine einzelne Änderung:

export CHANGE_ID="PUBLIC_CHANGE_UUID"

curl --get "$BASE_URL/api/v1/changes/$CHANGE_ID" \
  --data-urlencode "fields=*" \
  --data-urlencode "include=files,relationships,users" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Der ETag steht im HTTP-Header ETag und in data.meta.etag. Behandeln Sie ihn als Version dieser konkreten Änderung und speichern Sie ihn vor jeder weiteren Mutation.

Der ETag kann sich nach der Änderung von Feldern, Beziehungen, Benutzerzuweisungen, dem Upload oder Löschen einer Datei sowie nach einer Workflow-Aktion ändern. Lesen Sie nach jeder erfolgreichen Mutation den neuen Zustand oder übernehmen Sie den neuen ETag aus der Antwort.


Änderungen - Aktualisierung mit If-Match

Verwenden Sie PATCH für eine teilweise Aktualisierung. Senden Sie nur die zu ändernden Felder, den aktuellen ETag und einen neuen Idempotenzschlüssel:

curl --request PATCH "$BASE_URL/api/v1/changes/$CHANGE_ID" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-update-20260905130127" \
  --data-raw '{
    "attributes": {
      "description": "Aktualisierte Änderung PUBLIC-API-CHANGE-20260905130127",
      "status": "Closed",
      "priority": "High",
      "risk": "Low",
      "impactInfo": "Aktualisierte Auswirkungsbewertung",
      "rolloutPlan": "Führen Sie den überarbeiteten Bereitstellungsplan aus und prüfen Sie den Service.",
      "backoutPlan": "Stellen Sie die vorherige Version wieder her, wenn die überarbeitete Änderung fehlschlägt.",
      "reasonForChange": "Aktualisierte Begründung der Umsetzung."
    }
  }'

Ein aktueller ETag führt zu 200 OK und einer neuen Version. Technische Felder wie pin und isSpam werden über eigene Endpoints geändert. Versuchen Sie nicht, sie mit einem gewöhnlichen PATCH zu ändern, wenn das Schema sie als schreibgeschützt kennzeichnet.

Planungstermine sind normale Felder der Änderung und werden daher in attributes aktualisiert. Prüfen Sie vor dem Speichern, ob das Schema sie als writable markiert.


Änderungen - veralteter oder fehlender ETag

Wenn ein anderer Prozess den Datensatz nach Ihrem Lesen geändert hat, kann ein alter ETag die neuere Version nicht überschreiben. Für einen veralteten Wert gibt die API 412 Precondition Failed mit dem Code if_match_failed zurück:

{
  "status": 412,
  "code": "if_match_failed"
}

Fehlt bei einer erforderlichen Mutation der Header If-Match, erhalten Sie 428 Precondition Required mit dem Code if_match_required:

{
  "status": 428,
  "code": "if_match_required"
}

Lesen Sie die Änderung nach beiden Antworten erneut, prüfen Sie ihren aktuellen Zustand und entscheiden Sie, ob Ihre Aktualisierung noch erforderlich ist. Senden Sie sie danach mit dem neuen ETag und einem neuen Idempotenzschlüssel. Deaktivieren Sie die Nebenläufigkeitskontrolle nicht.


Änderungen - Batch-Operationen

Eine Batch-Operation verbindet mehrere unabhängige Vorgänge in einer Anfrage. Das folgende Beispiel erstellt zwei Änderungen:

curl --request POST "$BASE_URL/api/v1/changes:batch" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-change-batch-create-20260905130127" \
  --data-raw '{
    "items": [
      {
        "operation": "create",
        "create": {
          "itemType": "change",
          "attributes": {
            "customId": "PUBLIC-API-CHANGE-20260905130127-BATCH-A",
            "subject": "Batch-Änderung A",
            "requesterEmail": "[email protected]",
            "description": "Batch-Änderung A",
            "source": "Public API",
            "type": "Standard",
            "status": "Open",
            "priority": "Medium",
            "risk": "Low",
            "datePlannedStart": "2030-02-10T09:00:00Z",
            "datePlannedEnd": "2030-02-10T12:00:00Z"
          }
        }
      },
      {
        "operation": "create",
        "create": {
          "itemType": "change",
          "attributes": {
            "customId": "PUBLIC-API-CHANGE-20260905130127-BATCH-B",
            "subject": "Batch-Änderung B",
            "requesterEmail": "[email protected]",
            "description": "Batch-Änderung B",
            "source": "Public API",
            "type": "Standard",
            "status": "Open",
            "priority": "Low",
            "risk": "High",
            "datePlannedStart": "2030-02-11T09:00:00Z",
            "datePlannedEnd": "2030-02-11T12:00:00Z"
          }
        }
      }
    ]
  }'

Die Antwort enthält items, den Status jeder Operation sowie die Zähler succeeded und failed. Verarbeiten Sie jedes Element einzeln. Ein Batch ist keine Alles-oder-nichts-Transaktion, daher muss ein Fehler nicht alle erfolgreichen Elemente zurückrollen.

Aktualisierung und Löschen erfordern den ETag jedes Datensatzes. Der Body eines Batch mit Aktualisierung und Löschung kann so aussehen:

{
  "items": [
    {
      "operation": "update",
      "id": "CHANGE_A_UUID",
      "ifMatch": "\"CHANGE_A_ETAG\"",
      "update": {
        "attributes": {
          "description": "Batch-Aktualisierung A"
        }
      }
    },
    {
      "operation": "delete",
      "id": "CHANGE_B_UUID",
      "ifMatch": "\"CHANGE_B_ETAG\""
    }
  ]
}

Ein Idempotenzschlüssel identifiziert die gesamte Batch-Anfrage, nicht die einzelnen Elemente. Speichern Sie danach IDs und ETags nur für Datensätze, die erfolgreich erstellt oder geändert wurden.


Änderungen - Beziehungen zu Objekten

Die möglichen Beziehungsziele liefert changes/schema. Je nach Zugriff und Daten kann eine Änderung mit IT-Assets, Dokumenten, anderen Änderungen, Tickets, Problemen und Releases verbunden werden. Jedes Ziel muss für den Schlüssel sichtbar sein und targetItemType muss dem tatsächlichen Objekttyp entsprechen.

Eine einzelne Beziehung hinzufügen:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/relationships" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-relationship-asset-20260905130127" \
  --data-raw '{
    "targetId": "ASSET_UUID",
    "targetDataSet": "assets",
    "targetItemType": "computer",
    "relationshipType": "related"
  }'

Das Hinzufügen einer einzelnen Beziehung liefert 201 Created. Mehrere Beziehungen können in einer Anfrage angelegt werden:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/relationships:batch" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-relationship-batch-20260905130127" \
  --data-raw '{
    "add": [
      {
        "targetId": "ASSET_UUID",
        "targetDataSet": "assets",
        "targetItemType": "computer",
        "relationshipType": "related"
      },
      {
        "targetId": "DOCUMENT_UUID",
        "targetDataSet": "documents",
        "targetItemType": "document",
        "relationshipType": "related"
      }
    ],
    "remove": []
  }'

Beziehungen lesen:

curl --request GET "$BASE_URL/api/v1/changes/$CHANGE_ID/relationships?page=1&pageSize=100" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Die Batch-Antwort enthält die Zähler added, removed und skipped. Jede Änderung einer Beziehung ändert den ETag der Quelle. Lesen Sie daher vor der nächsten Mutation einen neuen Wert.


Änderungen - Beziehungen entfernen

Entfernen Sie eine Beziehung mit dem aktuellen ETag der Quelländerung. Geben Sie Zielkollektion und ID im Pfad an:

curl --request DELETE "$BASE_URL/api/v1/changes/$CHANGE_ID/relationships/changes/$TARGET_CHANGE_ID?relationshipType=related" \
  --header "Accept: application/json, application/problem+json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-relationship-delete-20260905130127"

Für ein IT-Asset verwenden Sie relationships/assets/{TARGET_ID}, für ein Dokument relationships/documents/{TARGET_ID}. Der Parameter relationshipType muss dem gespeicherten Beziehungstyp entsprechen.

Beziehungen können auch im Rahmen einer teilweisen Aktualisierung entfernt werden:

curl --request PATCH "$BASE_URL/api/v1/changes/$CHANGE_ID" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-relationship-patch-20260905130127" \
  --data-raw '{
    "relationshipsToRemove": [
      {
        "targetId": "TARGET_UUID",
        "targetDataSet": "changes",
        "targetItemType": "change",
        "relationshipType": "related"
      }
    ]
  }'

Lesen Sie die Liste nach dem Entfernen erneut und prüfen Sie, ob das richtige Ziel verschwunden ist. Das Entfernen einer Beziehung löscht nicht den Datensatz, der ihr Ziel war.


Änderungen - Benutzerbeziehungen

Benutzerbeziehungen sind ein eigener Mechanismus. Eine Änderung unterstützt drei Rollen: agent für die ausführende Person, watcher für einen Beobachter und appUserRequester für den Benutzer, der die Anfrage gestellt hat. Dieses Objekt unterstützt kein clientRequester.

Einen Agent zuweisen:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/user-relationships" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-agent-20260905130127" \
  --data-raw '{
    "targetId": "USER_UUID",
    "targetDataSet": "users",
    "relationshipType": "agent"
  }'

Einen Beobachter per Batch hinzufügen:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/user-relationships:batch" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-watcher-20260905130127" \
  --data-raw '{
    "add": [
      {
        "targetId": "WATCHER_USER_UUID",
        "targetDataSet": "users",
        "relationshipType": "watcher"
      }
    ],
    "remove": []
  }'

Benutzerbeziehungen lesen:

curl --request GET "$BASE_URL/api/v1/changes/$CHANGE_ID/user-relationships?page=1&pageSize=100" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Eine Zuweisung mit Angabe des Beziehungstyps entfernen:

curl --request DELETE "$BASE_URL/api/v1/changes/$CHANGE_ID/user-relationships/users/$USER_ID?relationshipType=appUserRequester" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-app-user-requester-delete-20260905130127"

Verwenden Sie dieselbe Route zum Entfernen eines Agents, Beobachters oder Anfragenden und ändern Sie relationshipType. Ein Beobachter kann auch per Batch mit einem leeren add-Array und einem Eintrag in remove entfernt werden.


Änderungen - Dateien

Eine zu einer Änderung hochgeladene Datei hat eine eigene ID und Metadaten. Der Upload benötigt den aktuellen ETag, einen neuen Idempotenzschlüssel und eine Anfrage mit multipart/form-data:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/files?relationshipType=documentation" \
  --header "Accept: application/json, application/problem+json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-file-one-20260905130127" \
  --form "[email protected];type=text/plain"

Ein erfolgreicher Upload liefert 201 Created mit Datei-ID und Metadaten. Die Dateiliste lesen Sie so:

curl --request GET "$BASE_URL/api/v1/changes/$CHANGE_ID/files?page=1&pageSize=100" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Laden Sie den Inhalt als Binärdaten herunter und speichern Sie ihn in einer Datei:

export FILE_ID="FILE_UUID"

curl --request GET "$BASE_URL/api/v1/changes/$CHANGE_ID/files/$FILE_ID/content" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --output downloaded-change-file.bin

Eine vorhandene Datei kann an eine andere Änderung angehängt werden. Der ETag gehört dann zur Zieländerung:

curl --request POST "$BASE_URL/api/v1/changes/OTHER_CHANGE_UUID/files/$FILE_ID?relationshipType=manual" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "OTHER_CHANGE_ETAG"' \
  --header "Idempotency-Key: public-api-change-file-attach-20260905130127"

Eine Datei löschen Sie mit DELETE /api/v1/changes/{id}/files/{fileId}. Bei Erfolg wird 200 OK zurückgegeben. Aktualisieren Sie nach Upload, Anhängen oder Löschen den ETag der Änderung und die Dateiliste.

curl --request DELETE "$BASE_URL/api/v1/changes/$CHANGE_ID/files/$FILE_ID" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-file-delete-20260905130127"

Änderungen - Anheften, Spam und erneutes Öffnen

Anheften, als Spam markieren und erneutes Öffnen sind getrennte Aktionen. Jede Aktion benötigt den aktuellen If-Match-Wert und einen neuen Idempotency-Key.

Eine Änderung anheften:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/pin" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-pin-20260905130127" \
  --data-raw '{"pin":2}'

Zum Aufheben verwenden Sie dieselbe Route mit null, sofern Schema und Berechtigungen dies zulassen:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/pin" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-unpin-20260905130127" \
  --data-raw '{"pin":null}'

Als Spam markieren und Markierung zurücknehmen:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/spam" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-spam-20260905130127" \
  --data-raw '{"isSpam":true}'

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/spam" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-spam-undo-20260905130127" \
  --data-raw '{"isSpam":false}'

Eine geschlossene Änderung erneut öffnen:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/reopen" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-reopen-20260905130127"

Lesen Sie die Änderung nach jeder Aktion erneut und speichern Sie den neuen ETag. Benötigt werden jeweils changes:pin:write, changes:spam:write und changes:reopen:write.


Änderungen - Bewertung und Eskalation

Speichern Sie eine Bewertung über einen eigenen Endpoint. Sie können dabei eine Eskalationsanfrage übergeben:

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/rating" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-rating-20260905130127" \
  --data-raw '{
    "rating": 4,
    "feedback": "Bewertung aus der Integration",
    "isEscalationRequested": true,
    "escalationRequestReason": "Eskalationsanfrage über die öffentliche API"
  }'

Zum Speichern der Bewertung ist changes:rating:write erforderlich, für eine Eskalationsanfrage zusätzlich changes:escalation:write. Verwenden Sie einen von der API unterstützten Bewertungswert. Lesen Sie nach dem Speichern unter anderem rating, feedback, Bewertungsdaten und escalationRequestReason.

Wenn keine Eskalation erforderlich ist, lassen Sie isEscalationRequested und escalationRequestReason weg. Senden Sie keine Eskalationsanfrage ohne Begründung.


Änderungen - Genehmigung und Entscheidung

Erstellen Sie eine Genehmigung als separates Objekt approval und verknüpfen Sie sie mit der Änderung. Dafür benötigen Sie die Bereiche des Genehmigungsmoduls und die ID der Person, die entscheiden soll:

export APPROVER_ID="USER_UUID"

curl --request POST "$BASE_URL/api/v1/approvals" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-change-approval-create-20260905130127" \
  --data-raw '{
    "itemType": "approval",
    "approverId": "USER_UUID",
    "attributes": {
      "customId": "PUBLIC-API-CHANGE-20260905130127-APPROVAL",
      "category": "Public API",
      "description": "Genehmigung der Änderung"
    },
    "relationships": [
      {
        "targetId": "CHANGE_UUID",
        "targetDataSet": "changes",
        "targetItemType": "change"
      }
    ]
  }'

Die in approverId angegebene Person kann die Entscheidung über die Änderungsroute treffen. APPROVAL_ID ist die ID der Genehmigung, nicht die ID eines Benutzers:

export APPROVAL_ID="APPROVAL_UUID"

curl --request POST "$BASE_URL/api/v1/changes/$CHANGE_ID/approvals/$APPROVAL_ID" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-approval-decision-20260905130127" \
  --data-raw '{
    "approve": true,
    "remark": "Über die öffentliche Changes API genehmigt."
  }'

Eine Ablehnung senden Sie mit approve gleich false und einer eigenen Bemerkung. Lesen Sie die Genehmigung danach und prüfen Sie Status und Entscheidungsdatum. Aktualisieren Sie anschließend die Änderung, weil die Entscheidung ihren ETag und Prozessstatus verändern kann.


Änderungen - Datensatz löschen

Lesen Sie die Änderung vor dem Löschen erneut und verwenden Sie den aktuellen ETag:

curl --request DELETE "$BASE_URL/api/v1/changes/$CHANGE_ID" \
  --header "Accept: application/json, application/problem+json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header 'If-Match: "CURRENT_ETAG"' \
  --header "Idempotency-Key: public-api-change-delete-20260905130127"

Senden Sie nach 200 OK ein GET für dieselbe UUID. Erwarten Sie 404 mit change_not_found oder dem passenden Datensatzcode. Für die Synchronisationskontrolle können Sie nach customId filtern und prüfen, dass totalItems null ist.

Verwenden Sie das Löschen nicht als Archivierung der Historie. Prüfen Sie vor einer produktiven Operation Aufbewahrungsregeln, Beziehungen und Audit-Anforderungen. Wenn der Datensatz in der Historie bleiben muss, ändern Sie seinen Status statt ihn zu löschen.


Änderungen - Fehler, Grenzen und Sicherheit

Fehler werden im Problem-Details-Format application/problem+json zurückgegeben. Beispiel:

{
  "type": "https://docs.codenica.com/errors/change_not_found",
  "title": "Änderung nicht gefunden.",
  "status": 404,
  "detail": "Die Änderung existiert nicht oder ist für diesen Aufrufer nicht sichtbar.",
  "instance": "/api/v1/changes/PUBLIC_CHANGE_UUID",
  "code": "change_not_found",
  "requestId": "request-id-from-response"
}

Verlassen Sie sich in der Integrationslogik vor allem auf status und code. Das Feld detail ist für Menschen bestimmt und kann anders formuliert werden.

HTTP
Bedeutung
401
Authentifizierung fehlt oder ist ungültig
403
benötigter Bereich oder Benutzerberechtigung fehlt
404
Datensatz, Datei oder Beziehungsziel fehlt oder ist nicht sichtbar
409
Daten- oder Idempotenzkonflikt
412
veralteter ETag
422
ungültiger Body oder ungültige Feldwerte
428
If-Match oder Idempotency-Key fehlt
429
Anfragelimit überschritten

Lesen Sie X-RateLimit-Limit und X-RateLimit-Remaining. Wenden Sie nach 429 Backoff an und beachten Sie Retry-After, falls vorhanden. Umgehen Sie die Grenzen nicht durch zusätzliche Schlüssel oder höhere Parallelität. Protokollieren Sie Methode, Endpoint, Status und requestId, aber niemals Client Secret oder vollständige Authentifizierungs-Header.


Änderungen - empfohlene Reihenfolge der Integration

  1. Setzen Sie BASE_URL für die richtige Cloud- oder On-Premise-Installation.
  2. Erstellen Sie unter Einstellungen - API - API Keys einen eigenen Schlüssel und wählen Sie die kleinsten erforderlichen Bereiche.
  3. Legen Sie Client ID und Client Secret in einem sicheren Speicher ab.
  4. Senden Sie GET /api/v1/context und prüfen Sie Datenbank, Bereiche und Limits.
  5. Rufen Sie GET /api/v1/changes/schema und die von der Integration verwendeten Feldwerte ab.
  6. Lesen Sie die Änderungsliste oder erstellen Sie eine Änderung mit POST und einem eindeutigen Idempotency-Key.
  7. Speichern Sie UUID und ETag der Änderung.
  8. Aktualisieren Sie den ETag vor jeder Mutation und verwenden Sie einen neuen Idempotenzschlüssel.
  9. Fügen Sie Beziehungen, Benutzer und Dateien erst hinzu, nachdem Sie den Zielkatalog im Schema geprüft haben.
  10. Führen Sie Workflow-Aktionen und Genehmigungsentscheidungen getrennt aus und lesen Sie danach jeweils den neuen Zustand.
  11. Lesen Sie bei 412 den Datensatz, lösen Sie den Konflikt und wiederholen Sie die Operation bewusst.
  12. Prüfen Sie bei Batch-Operationen jedes Element, weil ein Teilfehler erfolgreiche Elemente nicht zurückrollen muss.
  13. Behandeln Sie 429, speichern Sie requestId ohne Secrets und löschen Sie den Schlüssel, wenn die Integration nicht mehr verwendet wird.

Mit diesem Ablauf können Sie geplante Änderungen mit einem anderen System synchronisieren, ohne von der internen Datenbankstruktur abzuhängen. Wenn sich Feldkonfiguration, Installationsadresse oder Schlüsselbereiche ändern, lesen Sie Kontext und Schema erneut.