Lösungen in der Codenica API

Beginnen Sie die Arbeit mit Lösungen über die Codenica API, indem Sie in den Codenica-Einstellungen einen Schlüssel erstellen. Falls noch kein Schlüssel vorhanden ist, öffnen Sie den Artikel Codenica API - Einführung in einem neuen Tab. Dort werden die gemeinsamen Regeln für die Ausstellung von Schlüsseln, die Aufbewahrung des Geheimnisses und die Authentifizierung erklärt.

Der technische Modulname lautet solutions, der Typ eines einzelnen Objekts solution. Eine Lösung ist ein Eintrag der Wissensdatenbank. Sie kann eine Anleitung, eine Beschreibung des Vorgehens, Verweise und unterstützende Dateien enthalten. Sie ist kein Workflow-Objekt wie Ticket, Änderung, Problem oder Release. Übernehmen Sie daher nicht deren Status-, Prioritäts- oder Eskalationsfelder in eine Lösung.

Die folgenden Abschnitte behandeln API-Adresse, Scopes, context, Schema, Felder, Listen, Filter, Erstellung, Idempotenz, ETag, Bearbeitung, Batch-Vorgänge, Beziehungen zu Problemen, Angaben zu Autoren und Bearbeitern, Dateien, Bewertungen und Löschung.

Die Beispiele verwenden den Präfix PUBLIC-API-SOLUTION-20260905134845. Ersetzen Sie ihn in Ihrer Integration durch einen eigenen Bezeichner und passen Sie E-Mail-Adressen, IDs und Feldwerte an die Daten Ihrer Datenbank an.


Lösungen - API-Adresse und Installationswahl

Alle Routen für Lösungen beginnen mit:

{BASE_URL}/api/v1/solutions

BASE_URL ist die Adresse des Codenica-Servers ohne den abschließenden Teil /api/v1. Verwenden Sie bei Codenica Cloud die öffentliche Domain, die der betreffenden Firma zugewiesen ist:

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

Bei einer standardmäßigen On-Premise-Installation lautet die lokal von Codenica Discovery registrierte Adresse:

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

Wenn der Administrator die Installation unter einer Firmendomain, über einen Reverse Proxy, mit HTTPS oder auf einem anderen Port veröffentlicht hat, verwenden Sie genau die dafür mitgeteilte Adresse:

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

Verwenden Sie localhost nicht, wenn das integrierende Programm auf einem anderen Rechner als die API läuft. Die richtige Datenbank wird anhand der von der Integration verwendeten Adresse ausgewählt. Senden Sie tenantId weder im Body noch in der Query-Zeichenkette.


Lösungen - API-Schlüssel und Lizenzgrenzen

Erstellen Sie einen API-Schlüssel in Codenica unter Einstellungen - API - API Keys. Das Geheimnis wird nur einmal angezeigt, unmittelbar nach der Erstellung oder Rotation des Schlüssels. Speichern Sie in diesem Moment Client ID und Client Secret im sicheren Speicher der Integration.

Die 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, damit Sie Scopes verwalten, das Geheimnis rotieren oder den Zugriff unabhängig entfernen können.

Lizenz
API-Zugriff
Maximale Anzahl aktiver Schlüssel
Starter
Nicht verfügbar
0
Plus
Verfügbar
50
Enterprise
Verfügbar
100

Beim Löschen eines Schlüssels wird sein Datensatz entfernt und ein Platz im Limit frei. Nach Ablauf der Gültigkeit authentifiziert der Schlüssel keine Anfragen mehr, bleibt aber in der Liste, bis er gelöscht wird. Wenn Sie beim Erstellen kein Enddatum festlegen, beträgt die Standardgültigkeit 90 Tage. Die maximale Gültigkeitsdauer eines Schlüssels beträgt 5 Jahre.


Lösungen - Authentifizierung und sichere Anfragen

Authentifizieren Sie jede Anfrage an die Codenica API mit den beiden Headern des Schlüssels:

export CLIENT_ID="cna_ihr_client_id"
export CLIENT_SECRET="cns_ihr_client_secret"

curl --request GET --url "$BASE_URL/api/v1/solutions?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 des Administrators noch Cookies aus dem Codenica-Panel. Legen Sie den Schlüssel nicht in einem Repository, in an den Browser ausgeliefertem Code, in einer URL, in der Shell-Historie oder in Logs ab. Verwenden Sie außerhalb lokaler Tests HTTPS.

Bewahren Sie meta.requestId aus der Antwort auf. Damit lässt sich eine konkrete Anfrage bei der Fehlersuche zuordnen. Es ist jedoch nicht die ID der Lösung und darf nicht als Geheimnis behandelt werden.


Lösungen - Verbindungs-Context prüfen

Lesen Sie vor dem ersten Schreibvorgang den Context. So prüfen Sie, ob die Adresse auf die gewünschte Datenbank zeigt und der ausgewählte Schlüssel die erforderlichen Scopes besitzt:

curl --request GET --url "$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 in der Antwort:

  • data.apiVersion und data.contractVersion;
  • data.tenant.id, data.tenant.name und data.tenant.resolvedDomain;
  • data.caller.authentication mit dem Wert api_key;
  • das Vorhandensein von solutions in data.capabilities.resources;
  • die dem Schlüssel zugewiesenen Scopes;
  • die Limits für Seiten, Batch-Vorgänge, Dateien und Anfragen.

Wenn der Context auf eine andere Datenbank zeigt oder ein benötigter Scope fehlt, halten Sie die Integration an und korrigieren Sie Adresse oder Schlüssel. Scopes können nicht für eine einzelne Anfrage ergänzt werden.


Lösungen - Scopes und Berechtigungen

Für die vollständige Arbeit mit Lösungen benötigen Sie Scopes passend zu den von Ihrer Integration verwendeten Operationen:

solutions:read
solutions:write
solutions:delete
solutions:schema
solutions:stats
solutions:relationships:read
solutions:relationships:write
solutions:users:read
solutions:files:read
solutions:files:write
solutions:technical:read
solutions:technical:write
solutions:rating:write
problems:read
users:read

Für gewöhnliche Lesevorgänge genügt solutions:read. Schema und Statistiken verwenden die separaten Scopes solutions:schema und solutions:stats. Für das Lesen von Beziehungen, Autoren, Bearbeitern und Dateien sind die jeweiligen Lese-Scopes erforderlich. Schreiboperationen verwenden die passenden :write-Scopes.

  • solutions:relationships:read und solutions:relationships:write gelten für Objektbeziehungen mit Problemen;
  • solutions:users:read und users:read gelten je nach Konfiguration für Angaben zu Autoren und Bearbeitern;
  • solutions:files:read und solutions:files:write gelten für Auflisten, Hochladen, Anhängen und Löschen von Dateien;
  • solutions:rating:write ist zum Abgeben oder Zurücknehmen der eigenen Bewertung erforderlich;
  • technische Scopes verwenden Sie nur, wenn die Integration im Schema als technisch gekennzeichnete Felder benötigt.

Der Scope problems:read ist erforderlich, wenn die Integration nach einem Problem als Beziehungsziel sucht. Das Solutions-Modul erstellt oder löscht dieses Problem nicht. Vergeben Sie nur die Scopes, die die Integration tatsächlich benötigt.


Lösungen - Schema und Felder

Das Schema zeigt, welche Felder in der ausgewählten Datenbank gelesen und geschrieben werden können. Rufen Sie es ab, bevor Sie ein Formular oder eine Feldzuordnung erstellen:

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

Die Antwort enthält unter anderem data.itemType, data.fields und data.relationshipTargets. Der feste itemType dieses Moduls lautet solution. Prüfen Sie für jedes Feld readable, writable, required, technical, unique und maxLength. Bauen Sie die Zuordnung nicht allein anhand der Beispiele dieses Artikels.


Lösungen - beschreibbare und Systemfelder

Beim Erstellen müssen Sie title und category angeben. Der öffentliche Katalog der Geschäftsfelder umfasst:

customId
title
description
location
department
type
tags
section
category
visibility

Maximale Längen laut öffentlichem Schema:

Feld
Maximale Länge
customId
500
title
1000
description
10000
location
300
department
300
type
300
tags
2000
section
300
category
300
visibility
100

Die folgenden Werte sind schreibgeschützt und gehören nicht in einen gewöhnlichen PATCH-Body:

helpful
notHelpful
totalFiles
creator
updater
importId
importSource
dateImported

id und itemType sind Teil der Ressourcenhülle. dateCreated und dateUpdated sind Systemdaten. Versuchen Sie nicht, sie über attributes zu ändern.


Lösungen - zentrale Endpunkte

Die wichtigsten Routen des Moduls solutions sind:

GET    /api/v1/solutions
POST   /api/v1/solutions
GET    /api/v1/solutions/{SOLUTION_ID}
PATCH  /api/v1/solutions/{SOLUTION_ID}
DELETE /api/v1/solutions/{SOLUTION_ID}
GET    /api/v1/solutions/schema
GET    /api/v1/solutions/stats
GET    /api/v1/solutions/values
GET    /api/v1/solutions/{SOLUTION_ID}/relationships
POST   /api/v1/solutions/{SOLUTION_ID}/relationships
POST   /api/v1/solutions/{SOLUTION_ID}/relationships:batch
GET    /api/v1/solutions/{SOLUTION_ID}/user-relationships
GET    /api/v1/solutions/{SOLUTION_ID}/files
POST   /api/v1/solutions/{SOLUTION_ID}/files
GET    /api/v1/solutions/{SOLUTION_ID}/files/{FILE_ID}/content
POST   /api/v1/solutions/{SOLUTION_ID}/rating

Jede Route erfordert Authentifizierung. Ändernde Operationen benötigen außerdem Idempotency-Key, versionsgeschützte Operationen den aktuellen If-Match-Wert. Die genauen Anforderungen der geplanten Anfrage finden Sie im Schema und in der Context-Antwort.


Lösungen - Listen und Paginierung

Die Liste ist paginiert. Das folgende Beispiel ruft die erste Seite ab und sortiert Lösungen nach dem Titel:

curl --request GET --url "$BASE_URL/api/v1/solutions?itemType=solution&page=1&pageSize=25&sort=title&direction=asc" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Die Antwort enthält unter anderem:

data.items
data.page
data.pageSize
data.totalItems
data.totalPages
data.hasNextPage

Rufen Sie weitere Seiten ab, solange data.hasNextPage den Wert true hat. Nehmen Sie nicht an, dass die Zahl der Einträge auf der ersten Seite die vollständige Liste darstellt. Passen Sie pageSize an das vom Context gelieferte Limit an, statt immer den Höchstwert anzufordern.


Lösungen - Suche, Filter und Sortierung

Sie können unter anderem nach ids, customId, title, description, location, department, type, tags, section, category, visibility, helpful, notHelpful, createdAfter, createdBefore, updatedAfter und updatedBefore filtern. URL-kodieren Sie Werte mit Leerzeichen, Kommas oder Sonderzeichen.

Beispiel: Lösungen der Kategorie Public API auflisten:

curl --request GET --url "$BASE_URL/api/v1/solutions?category=Public%20API&page=1&pageSize=25&sort=title&direction=asc" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Der Parameter search durchsucht Textdaten der Lösung, darunter Titel, Beschreibung, Typ, Tags, Abschnitt, Kategorie, Sichtbarkeit, Ort und Abteilung:

curl --request GET --url "$BASE_URL/api/v1/solutions?search=backup&page=1&pageSize=25" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Sortieren Sie nur nach einem Feld, das vom Schema bereitgestellt wird. Gehen Sie nicht davon aus, dass jedes im Formular sichtbare Feld als sort-Parameter verwendet werden kann.


Lösungen - Feldauswahl und zusätzliche Daten

Wenn die Integration nur einen Teil des Datensatzes benötigt, begrenzen Sie die Antwort mit fields:

curl --request GET --url "$BASE_URL/api/v1/solutions?customId=PUBLIC-API-SOLUTION-20260905134845-SOURCE&fields=title%2Ccategory%2Cvisibility&page=1&pageSize=10" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Sie können einen einzelnen Datensatz zusammen mit seinen Dateien, Beziehungen sowie Angaben zum Autor oder Bearbeiter abrufen:

curl --request GET --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}?fields=title%2Ccategory%2Cdescription%2Cvisibility&include=files%2Crelationships%2Cusers" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Zulässige include-Werte sind files, relationships und users. Jeder Wert erfordert den passenden Scope. Mit fields=* fordern Sie alle verfügbaren Felder an. Technische Felder erscheinen jedoch nur mit dem entsprechenden technischen Scope.


Lösungen - Statistiken und Feldwerte

Verwenden Sie Statistiken, um Datensätze zu zählen und nach einem Feld zu gruppieren:

curl --request GET --url "$BASE_URL/api/v1/solutions/stats?field=category&limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Die Antwort enthält unter anderem total, field und ein Array values. Der Wert category=Public API kann als praktischer Filter für Demonstrationsdaten dienen.

Für unterschiedliche Werte eines Feldes verwenden Sie die Route values:

curl --request GET --url "$BASE_URL/api/v1/solutions/values?field=visibility&search=internal&limit=20" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

limit muss innerhalb des vom API unterstützten Bereichs liegen. Der aktuelle Bereich für diese Endpunkte reicht von 1 bis 500. Statistik- und Feldwertanfragen sind schreibgeschützt und ändern keine Lösungen.


Lösungen - einen Datensatz erstellen

Geben Sie beim Erstellen den technischen Typ solution im Body und die beschreibbaren Felder innerhalb von attributes an. Der minimale Payload benötigt title und category:

{
  "itemType": "solution",
  "attributes": {
    "customId": "PUBLIC-API-SOLUTION-20260905134845-SOURCE",
    "title": "PUBLIC-API-SOLUTION-20260905134845 integration knowledge article",
    "description": "Created through the Codenica Public API Solutions flow.",
    "location": "Warsaw",
    "department": "IT",
    "type": "How-to",
    "tags": "public-api,solution,integration",
    "section": "Integrations",
    "category": "Public API",
    "visibility": "team"
  }
}

Speichern Sie den Inhalt als solution-create.json und senden Sie ihn:

curl --request POST --url "$BASE_URL/api/v1/solutions" \
  --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-solution-create-20260905134845" \
  --data-binary @solution-create.json

Eine erfolgreiche Erstellung liefert 201 Created. Die Antwort enthält die UUID der Lösung, data.itemType=solution, die gespeicherten Attribute, Systemdaten und data.meta.etag. In den meisten Integrationen sollte das System die id vergeben.


Lösungen - Erstellung sicher wiederholen

Wenn das Ergebnis einer Anfrage unklar ist, wiederholen Sie exakt denselben Payload mit demselben Idempotency-Key. So verhindert die Integration, dass eine zweite Lösung entsteht:

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

Verwenden Sie denselben Schlüssel nur für dieselbe Absicht und denselben Body. Für eine neue Lösung oder einen neuen Payload erzeugen Sie einen neuen Schlüssel. Ändern Sie nach einem Timeout den Schlüssel nicht, bevor Sie geprüft haben, ob der erste Schreibvorgang auf dem Server abgeschlossen wurde.


Lösungen - Datensatz und ETag lesen

Rufen Sie nach dem Erstellen oder Finden einer Lösung den einzelnen Datensatz ab und speichern Sie den ETag aus dem HTTP-Header sowie aus data.meta.etag:

curl --request GET --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}?fields=title%2Ccategory%2Cdescription%2Cvisibility%2Ctags" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Eine erfolgreiche Antwort liefert 200 OK und einen ETag-Header:

ETag: "..."
data.meta.etag: "..."
meta.etag: "..."

Verwenden Sie den aktuellen Wert für die nächste Änderung, Beziehung, Dateioperation, Bewertung oder Löschung. Der ETag repräsentiert die Version der gesamten Lösung. Eine Änderung an Attributen, Beziehungen oder Dateien kann daher den vorherigen Wert ungültig machen.


Lösungen - Teilaktualisierung mit If-Match

Aktualisieren Sie nur die Felder, die sich ändern sollen. Die folgende Anfrage ändert Beschreibung und Sichtbarkeit:

{
  "attributes": {
    "description": "Updated through the Solutions Public API flow.",
    "visibility": "internal",
    "tags": "public-api,solution,updated",
    "section": "Updated integrations"
  }
}
curl --request PATCH --url "$BASE_URL/api/v1/solutions/{SOLUTION_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-solution-update-20260905134845" \
  --data-binary @solution-update.json

Eine erfolgreiche Aktualisierung liefert 200 OK, die unveränderte UUID und einen neuen ETag sowohl im Antwort-Header als auch in den Antwortmetadaten. Speichern Sie den neuen Wert vor jeder weiteren Mutation.


Lösungen - veralteter ETag und fehlendes If-Match

Die API verhindert, dass eine Lösung eine neuere Version überschreibt. Ein alter ETag wird abgewiesen:

Wenn zwei Prozesse dieselbe Lösung lesen und einer zuerst speichert, besitzt der zweite Prozess einen veralteten ETag. Ein Schreibversuch mit diesem Wert wird abgewiesen:

HTTP 412 Precondition Failed
code: if_match_failed

Nach HTTP 412 lesen Sie den Datensatz erneut, entscheiden Sie, wie die Änderungen zusammengeführt werden sollen, und senden Sie erst danach einen neuen PATCH. Eine wegen eines veralteten ETag abgewiesene Anfrage darf die Daten nicht verändern.

Eine Mutation ohne den erforderlichen Header liefert:

HTTP 428 Precondition Required
code: if_match_required

Umgehen Sie diese Anforderung nicht durch einen leeren Wert. Lesen Sie zuerst den aktuellen Datensatz und verwenden Sie exakt seinen ETag.


Lösungen - Batch-Vorgänge

Verwenden Sie POST /api/v1/solutions:batch, wenn mehrere Lösungen in einer übermittelten Menge erstellt, aktualisiert oder gelöscht werden sollen. Jedes Element gibt seine Operation an:

{
  "items": [
    {
      "operation": "create",
      "create": {
        "itemType": "solution",
        "attributes": {
          "customId": "PUBLIC-API-SOLUTION-BATCH-A",
          "title": "Batch Solution A",
          "category": "Public API",
          "description": "Batch-created Solution A",
          "type": "How-to",
          "visibility": "team"
        }
      }
    },
    {
      "operation": "create",
      "create": {
        "itemType": "solution",
        "attributes": {
          "customId": "PUBLIC-API-SOLUTION-BATCH-B",
          "title": "Batch Solution B",
          "category": "Public API",
          "description": "Batch-created Solution B",
          "type": "Reference",
          "visibility": "team"
        }
      }
    }
  ]
}
curl --request POST --url "$BASE_URL/api/v1/solutions:batch" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "Idempotency-Key: public-api-solution-batch-create-20260905134845" \
  --data-binary @solutions-batch.json

Bei einer Aktualisierung enthält ein Element operation=update, id, ifMatch und update.attributes:

{
  "items": [
    {
      "operation": "update",
      "id": "{SOLUTION_A_ID}",
      "ifMatch": "{SOLUTION_A_ETAG}",
      "update": {
        "attributes": {
          "description": "Batch update A"
        }
      }
    }
  ]
}

Bei einer Löschung enthält ein Element operation=delete, id und den aktuellen Wert ifMatch. Die Antwort kann succeeded und failed enthalten. Bei einem Teilergebnis ist auch HTTP 207 Multi-Status möglich. Prüfen Sie jedes Element einzeln. Ein Batch ist keine Transaktion.


Lösungen - Beziehungen nur mit Problemen

Lösungen unterstützen Objektbeziehungen ausschließlich mit dem Modul Probleme. Ein typisches Ziel aus dem Schema ist:

targetDataSet: problems
targetItemType: problem

Nehmen Sie nicht an, dass eine Lösung über diese Endpunkte mit einem Asset, Dokument, Kunden, Lieferanten, Ticket, einer Änderung oder einem Release verbunden werden kann. Wenn das Schema einer bestimmten Datenbank kein Ziel liefert, darf die Integration es nicht verwenden.

Suchen Sie zuerst ein lesbares Problem und verwenden Sie dafür ein öffentliches Sortierfeld:

curl --request GET --url "$BASE_URL/api/v1/problems?itemType=problem&page=1&pageSize=10&sort=subject&direction=asc" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Im Demonstrationsablauf wurde das Problem mit der ID 9793181f-a225-4928-8062-80d6e69cb792 verwendet. Ihre Integration sollte das aktuelle Ziel suchen und diese UUID nicht als feste Konstante behandeln.


Lösungen - Beziehungen hinzufügen, lesen und löschen

Der Body zum direkten Hinzufügen einer Beziehung kann so aussehen:

{
  "targetId": "9793181f-a225-4928-8062-80d6e69cb792",
  "targetDataSet": "problems",
  "targetItemType": "problem",
  "relationshipType": "related"
}

Lesen Sie vor jeder Mutation den aktuellen ETag der Lösung:

curl --request POST --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/relationships" \
  --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-solution-problem-relation-add-20260905135119" \
  --data-binary @solution-problem-relation.json

Ein korrektes Hinzufügen liefert 201 Created. Lesen Sie die Beziehung über eine eigene Route:

curl --request GET --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/relationships?targetDataSet=problems&targetItemType=problem&page=1&pageSize=50" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Zum direkten Löschen benötigen Sie den aktuellen ETag und die ID des Ziels:

curl --request DELETE --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/relationships/problems/9793181f-a225-4928-8062-80d6e69cb792?relationshipType=related" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-solution-problem-relation-delete-20260905135119"

Die Löschantwort liefert 200 und data=true. Lesen Sie die Sammlung anschließend erneut.


Lösungen - Batch-Beziehungen mit Problemen

Für gleichzeitiges Hinzufügen und Löschen verwenden Sie die Route relationships:batch:

{
  "add": [
    {
      "targetId": "9793181f-a225-4928-8062-80d6e69cb792",
      "targetDataSet": "problems",
      "targetItemType": "problem",
      "relationshipType": "related"
    }
  ],
  "remove": []
}
curl --request POST --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/relationships:batch" \
  --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-solution-problem-relation-batch-add-20260905135119" \
  --data-binary @solution-problem-relation-batch.json

Um eine Beziehung per Batch zu löschen, lassen Sie add leer und verschieben Sie das Element nach remove:

{
  "add": [],
  "remove": [
    {
      "targetId": "9793181f-a225-4928-8062-80d6e69cb792",
      "targetDataSet": "problems",
      "targetItemType": "problem",
      "relationshipType": "related"
    }
  ]
}

Die Antwort enthält die Zähler added, removed und skipped. Prüfen Sie nach dem Hinzufügen added=1 und nach dem Löschen removed=1. Verwenden Sie vor jedem weiteren Schreibvorgang einen frischen ETag.


Lösungen - Beziehungen zu Autoren und Bearbeitern

Benutzerbeziehungen sind in diesem Modul Metadaten zur Autorschaft und zur letzten Bearbeitung. Zulässige Typen sind author und editor:

curl --request GET --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/user-relationships?page=1&pageSize=50" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Ein Beispielobjekt kann enthalten:

{
  "targetId": "8e9cbff3-340f-41f6-97ec-6997bb915829",
  "targetDataSet": "users",
  "relationshipType": "author",
  "displayName": "Fred Savage",
  "email": "[email protected]",
  "role": "Administrator"
}

Die Beziehungen author und editor werden aus den Autor- und Bearbeiterfeldern der Lösung gelesen. Das öffentliche Lösungsmodul bietet dafür keine Endpunkte zum Hinzufügen, Ändern oder Löschen. Versuchen Sie nicht, die Typen agent, watcher, appUserRequester oder clientRequester zu erstellen, da sie zu anderen Objekten gehören.


Lösungen - Dateien

Lesen Sie vor jeder Dateioperation die aktuelle Lösung und ihren ETag. Dateiliste:

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

Ein Listenelement enthält unter anderem id, name, fileName, contentType, size, width, height, relationshipType, isMain und downloadUrl. Für Lösungen ist isMain immer false. Das Modul bietet keinen set-main-Endpunkt. Versuchen Sie daher nicht, eine Hauptdatei festzulegen.

Das Senden einer Datei erfordert multipart/form-data:

curl --request POST --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/files?relationshipType=documentation" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-solution-file-20260905134845" \
  --form "[email protected];type=text/plain"

Ein erfolgreicher Upload liefert 201 Created und eine Dateiresource. Im Beispiel wird die Datei solution-one.txt mit dem Typ text/plain verwendet. Der Upload ändert die Version der Lösung. Rufen Sie deshalb danach einen neuen ETag ab.

Den Inhalt laden Sie über einen authentifizierten Pfad herunter:

curl --request GET --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/files/{FILE_ID}/content" \
  --header "Accept: application/octet-stream" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --output solution-one-downloaded.txt

Behandeln Sie downloadUrl als API-Pfad und nicht als öffentlichen anonymen Link. Wenn die Datei bereits im selben Dateibereich existiert, können Sie sie an eine andere Lösung anhängen:

curl --request POST --url "$BASE_URL/api/v1/solutions/{TARGET_SOLUTION_ID}/files/{FILE_ID}?relationshipType=manual" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $TARGET_CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-solution-file-attach-20260905134845"

Verwenden Sie beim Anhängen den ETag der Ziellösung und nicht den Datensatz, aus dem die Datei stammt. Das Löschen einer Datei erfordert den aktuellen ETag:

curl --request DELETE --url "$BASE_URL/api/v1/solutions/{SOLUTION_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-solution-file-delete-20260905134845"

Lesen Sie nach der Antwort 200 die Dateiliste erneut, um zu bestätigen, dass die Datei nicht mehr zurückgegeben wird.


Lösungen - Bewertung der Nützlichkeit

Die Bewertung ist eine eigene Mutation. Sie können eine Lösung als hilfreich oder nicht hilfreich markieren oder die eigene Bewertung zurücknehmen:

{
  "rating": 1
}
  • 1 - hilfreich;
  • 0 - nicht hilfreich;
  • -1 - eigene Bewertung zurücknehmen.

Als hilfreich markieren:

curl --request POST --url "$BASE_URL/api/v1/solutions/{SOLUTION_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-solution-rating-helpful-20260905134845" \
  --data '{"rating":1}'

Eigene Bewertung zurücknehmen:

curl --request POST --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}/rating" \
  --header "Content-Type: application/json" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
  --header "If-Match: $RATING_CURRENT_ETAG" \
  --header "Idempotency-Key: public-api-solution-rating-reset-20260905134845" \
  --data '{"rating":-1}'

Beide Operationen benötigen einen ETag. Die Antwort enthält die aktuellen Zähler helpful und notHelpful sowie einen neuen ETag. Aktualisieren Sie helpful und notHelpful nicht über einen gewöhnlichen PATCH.


Lösungen - Datensatz löschen

Das Löschen ist nicht rückgängig zu machen. Lesen Sie deshalb zuerst den Datensatz und holen Sie den aktuellen ETag:

curl --request DELETE --url "$BASE_URL/api/v1/solutions/{SOLUTION_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-solution-delete-20260905134845"

Die korrekte Antwort ist 200 mit data=true. Führen Sie anschließend einen kontrollierenden GET und eine gefilterte Liste aus:

curl --request GET --url "$BASE_URL/api/v1/solutions/{SOLUTION_ID}" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

curl --request GET --url "$BASE_URL/api/v1/solutions?customId=PUBLIC-API-SOLUTION-20260905134845-SOURCE&page=1&pageSize=10" \
  --header "X-Codenica-Client-Id: $CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $CLIENT_SECRET"

Nach dem Löschen liefert der einzelne GET 404 Not Found mit dem Code solution_not_found. Die nach customId gefilterte Liste sollte totalItems=0 enthalten. Beziehungen und Dateien sollten Sie vorher über die Integration prüfen oder aufräumen.


Lösungen - Fehler, Limits und Sicherheit

API-Fehler verwenden das Format Problem Details. Wichtige Felder sind status, code, detail und requestId:

{
  "type": "https://docs.codenica.com/errors/if_match_failed",
  "title": "Precondition failed.",
  "status": 412,
  "detail": "The supplied ETag is not the current solution version.",
  "instance": "/api/v1/solutions/{SOLUTION_ID}",
  "code": "if_match_failed",
  "requestId": "..."
}
HTTP
Bedeutung
Reaktion
400
ungültiges Feld, Filter, Body oder ungültige Beziehung
Anfrage gemäß Schema korrigieren
401
fehlende oder ungültige Authentifizierung
Adresse und Schlüssel prüfen
403
fehlender Scope oder fehlender Datenbankzugriff
Scope oder Benutzerberechtigung ändern
404
Lösung, Problem, Datei oder Beziehungsziel existiert nicht oder ist nicht sichtbar
UUID und Installationsadresse prüfen
409
Konflikt bei Identifikator oder bestehender Beziehung
Zustand lesen und entscheiden, ob der Konflikt erwartet ist
412
ETag ist nicht mehr aktuell
Datensatz und neuen ETag abrufen
413
Datei oder Body ist zu groß
Limit in context prüfen
422
Feldwert oder bestehender Ablauf lehnt die Operation ab
code und detail auswerten
428
If-Match oder Idempotency-Key fehlt
Passenden Header ergänzen
429
Anfragelimit überschritten
Backoff und Retry-After verwenden
500
Serverfehler
requestId sichern und Mutationen ohne Idempotenz nicht wiederholen

Lesen Sie die Header X-RateLimit-Limit und X-RateLimit-Remaining. Nach 429 beachten Sie Retry-After, falls vorhanden, und verwenden Sie kontrollierte Wiederholungen mit zunehmender Verzögerung.

Lösungen können betriebliche Informationen und interne Anleitungen enthalten. Begrenzen Sie die Feldauswahl, verwenden Sie HTTPS und beschränken Sie den Schlüssel auf die konkrete Datenbank. Bewahren Sie Client ID und Client Secret außerhalb des Quellcodes auf, schreiben Sie sie nicht in Logs und senden Sie sie nicht in Tickets.


Lösungen - Reihenfolge für die Integration

  1. Ermitteln Sie die tatsächliche Cloud- oder On-Premise-Adresse und setzen Sie BASE_URL.
  2. Erstellen Sie für Anwendung und Umgebung einen eigenen Schlüssel unter Einstellungen - API - API Keys.
  3. Vergeben Sie nur die für Lesen, Schreiben, Beziehungen, Dateien oder Bewertungen erforderlichen Scopes.
  4. Senden Sie GET /api/v1/context und prüfen Sie Datenbank, Caller, Scopes und Limits.
  5. Rufen Sie GET /api/v1/solutions/schema ab und erstellen Sie die Feldzuordnung.
  6. Rufen Sie die Liste ab oder suchen Sie eine vorhandene Lösung.
  7. Erstellen Sie den Datensatz mit POST und einem eindeutigen Idempotency-Key.
  8. Speichern Sie UUID und ETag aus der Antwort.
  9. Aktualisieren Sie den ETag vor jeder Änderung, Beziehung, Dateioperation, Bewertung oder Löschung.
  10. Erstellen Sie Objektbeziehungen ausschließlich zu einem vom Schema gelieferten Problem.
  11. Lesen Sie Autoren- und Bearbeiterbeziehungen nur aus, weil es dafür keine öffentlichen Schreibendpunkte gibt.
  12. Lesen Sie das Ergebnis nach jeder Mutation und speichern Sie den neuen ETag.
  13. Bei 412 lesen Sie den Datensatz erneut, lösen Sie den Konflikt und wiederholen Sie erst dann die Operation.
  14. Prüfen Sie bei Batch-Vorgängen jedes Ergebnis, weil ein Teilerfolg erfolgreiche Elemente nicht zurücknimmt.
  15. Bestätigen Sie vor dem Löschen den aktuellen ETag und prüfen Sie danach HTTP 404 sowie eine leere Liste über customId.

Mit diesem Ablauf können Sie Lösungen der Wissensdatenbank mit einem anderen System synchronisieren, ohne Annahmen über Felder, Beziehungen oder Systemdaten in die Integration einzubauen.