# SynCore-API: Anleitungen und Referenz > Die SynCore-API hat einen Endpunkt: `/api/app-tools`. `GET` liefert den Katalog der Tools, die der API-Key nutzen darf, `POST` führt ein Tool aus. Diese Datei enthält alle Artikel von https://support.unitedsynergy.com/api/ und https://support.unitedsynergy.com/mcp/ und die Referenz aller 867 App-Tools aus 26 Apps (355 lesen, 189 anlegen, 174 ändern, 148 löschen, 1 sonstige). Maßgeblich für eine Instanz bleibt ihr eigener Katalog. --- # API & Integrationen im Überblick > Was die App-Tools-API kann, was du dafür brauchst und in welcher Reihenfolge du vorgehst. Quelle: https://support.unitedsynergy.com/api/uebersicht/ Mit der **App-Tools-API** bindest du SynCore an andere Systeme an: Daten lesen, Datensätze anlegen oder ändern, Abläufe anstoßen. Die API nutzt dieselben Aktionen wie SynCore selbst und prüft dieselben Rechte wie bei einem Benutzer in der Oberfläche. ## So ist die API aufgebaut - **Ein Endpunkt:** `/api/app-tools`. `GET` liefert den Katalog der für dich erlaubten Aktionen, der sogenannten Tools. `POST` führt genau eines davon aus. - **Ein Schlüssel je Integration:** Der API-Key gehört zu einem Mandanten und handelt als ein technischer Benutzer, der **Actor-User**. Was dieser Benutzer in SynCore sehen und ändern darf, darf auch die Integration. - **Ein Katalog, der sich anpasst:** Welche Tools es gibt, hängt von den aktiven Apps, den Rollen und den Datenbereichen des Actor-Users ab. Eine feste, für alle gültige Tool-Liste gibt es nicht. - **Eine Spur im Audit-Log:** Standardmäßig steht jeder ausgeführte Aufruf mit Mandant, Actor-User, Tool und Ergebnis im Audit-Log. Wie die API geschützt ist, steht unter [Sicherheit der API](https://support.unitedsynergy.com/api/sicherheit/). ## In dieser Reihenfolge vorgehen 1. Technischen Benutzer mit knappen Rechten anlegen und API-Key beantragen: [API-Keys, Scopes und Berechtigungen](https://support.unitedsynergy.com/api/api-keys/) 2. Ersten Katalog abrufen und ein lesendes Tool ausführen: [API-Quickstart](https://support.unitedsynergy.com/api/quickstart/) 3. Anfragen und Fehlerfälle gezielt testen: [API-Anfragen sicher testen](https://support.unitedsynergy.com/api/anfragen-testen/) 4. Felder, Antworten, Statuscodes und Limits nachschlagen: [App-Tools-API Referenz](https://support.unitedsynergy.com/api/app-tools/) 5. Tools einer App mit Eingabefeldern und Rechten nachschlagen: [Referenz nach App](https://support.unitedsynergy.com/api/referenz/) Für einige feste Aufgaben, etwa ein Anmeldeformular auf deiner Website oder Bestellungen aus einem Shop, gibt es eigene Endpunkte mit eigenem Scope: [Spezialanbindungen neben den App-Tools](https://support.unitedsynergy.com/api/spezialanbindungen/). ## Mit KI-Assistenten arbeiten Claude, Cursor, VS Code und andere Clients verbindest du direkt über MCP mit deiner Instanz. Der Assistent nutzt dann dieselben Tools mit denselben Rechten wie die API, auf Wunsch im Code-Mode mit Programmen statt Einzelaufrufen. Alles dazu steht in der Rubrik [MCP & KI-Assistenten](https://support.unitedsynergy.com/mcp/uebersicht/). Damit ein Assistent die Dokumentation kennt, gib Claude, ChatGPT oder deinem eigenen Assistenten die Adresse `https://support.unitedsynergy.com/api/llms.txt`. Darin stehen alle Artikel zur API und zu MCP und die Referenz aller App-Tools als Klartext. Jede Seite gibt es auch einzeln: Häng `llms.txt` an ihre Adresse an, zum Beispiel `/api/referenz/crm/llms.txt`. Eine Übersicht aller Dateien steht unter `/llms.txt`. Den API-Key gibst du dem Assistenten nicht in den Chat. Er gehört in die Umgebung, in der die Aufrufe laufen. > **Grenzen der API** > > Tools für besonders geschützte Daten der Datenklasse D, zum Beispiel Gesundheitsdaten, bietet die API nicht an. Pro Schlüssel gilt ein Anfragelimit, die Werte stehen in der [Referenz](https://support.unitedsynergy.com/api/app-tools/#anfragelimits). > **Wenn es nicht klappt** > > Statuscodes, Meldungen und ihre häufigsten Ursachen findest du unter [Wenn eine API-Anfrage scheitert](https://support.unitedsynergy.com/api/fehlerbehebung/). --- # API-Quickstart > Rufe den persönlichen App-Tool-Katalog ab und führe deine erste sichere SynCore-Anfrage aus. Quelle: https://support.unitedsynergy.com/api/quickstart/ SynCore stellt Integrationen über die **App-Tools-API** bereit. Der Katalog ist dynamisch: Du siehst ausschließlich die Apps und Aktionen, die für den Benutzer hinter deinem API-Key freigegeben sind. > **Das brauchst du** > > Du benötigst die Basis-URL deiner SynCore-Instanz und einen API-Key mit dem Scope `app-tools` und einem zugeordneten Actor-User. Den Rohwert des Schlüssels erhältst du nur einmal. ## 1. Zugangsdaten als Umgebungsvariablen setzen PowerShell: ```powershell $SynCoreBaseUrl = 'https://syncore.example.com' $env:SYNCORE_API_KEY = 'syn_DEIN_SCHLUESSEL' ``` Bash, z. B. unter Linux oder macOS: ```bash export SYNCORE_BASE_URL='https://syncore.example.com' export SYNCORE_API_KEY='syn_DEIN_SCHLUESSEL' ``` Verwende die URL ohne abschließenden Schrägstrich. Schreibe den Schlüssel nicht in Quellcode, Git-Repositories, Tickets oder Screenshots. ## 2. Deinen verfügbaren Katalog abrufen PowerShell: ```powershell $Headers = @{ 'X-API-KEY' = $env:SYNCORE_API_KEY } Invoke-RestMethod ` -Method Get ` -Uri "$SynCoreBaseUrl/api/app-tools?includeStructure=1" ` -Headers $Headers ``` curl: ```bash curl --request GET \ "$SYNCORE_BASE_URL/api/app-tools?includeStructure=1" \ --header "X-API-KEY: $SYNCORE_API_KEY" ``` Die Antwort enthält: - `tools`: alle für diesen Schlüssel erlaubten Aktionen mit Ein- und Ausgabeschema, - `structure`: sichtbare Apps, Seiten, Navigation und effektive Berechtigungen, - `rules`: verbindliche Laufzeitregeln für Auswahl, Bestätigung und Readback. ## 3. Ein lesendes Tool auswählen Wähle für den ersten Test aus `tools[]` ein Tool mit `sideEffect: "none"`. Übernimm den `name` exakt und bilde `input` nach dem gelieferten `inputSchema`. ```json { "name": "textbausteine.list_templates", "input": { "limit": 10 } } ``` Der Name ist nur ein Beispiel. Ist die App nicht aktiviert oder fehlen dem Actor-User die Rechte, erscheint dieses Tool gar nicht in deinem Katalog. ## 4. Tool ausführen ```powershell $Body = @' { "name": "textbausteine.list_templates", "input": { "limit": 10 } } '@ Invoke-RestMethod ` -Method Post ` -Uri "$SynCoreBaseUrl/api/app-tools" ` -Headers $Headers ` -ContentType 'application/json' ` -Body $Body ``` Eine erfolgreiche Antwort hat immer `ok: true` und nennt das ausgeführte Tool sowie das Modul. Die Fachdaten stehen je nach Tool in `data` oder in weiteren, im `outputSchema` beschriebenen Feldern. > **Ergebnis** > > Wenn der Katalog geladen wird und ein lesendes Tool `ok: true` zurückgibt, sind URL, API-Key, Scope, Actor-User und dessen Berechtigungen korrekt eingerichtet. ## Sicherheitsregeln 1. Lade vor einer Aktion immer zuerst den aktuellen Katalog mit `includeStructure=1`. 2. Rate keine IDs. Ermittle Datensätze zuerst über ein sichtbares Listen- oder Such-Tool. 3. Bei mehreren Treffern muss der Benutzer die Auswahl treffen. 4. Führe Aktionen mit `confirmationRequired: true` erst nach ausdrücklicher Bestätigung aus. 5. Prüfe Änderungen anschließend mit einem Lese- oder Listen-Tool. Standardmäßig steht jeder ausgeführte Tool-Aufruf, auch ein fachlich gescheiterter, mit Mandant, Actor-User, Tool und Ergebnis im Audit-Log. Was sich abschalten lässt, steht unter [Sicherheit der API](https://support.unitedsynergy.com/api/sicherheit/). Abgewiesene Aufrufe (`400`, `403`, `404`) erreichen das Tool nicht. Die Aufbewahrung richtet sich nach der Audit-Einstellung des Mandanten. --- # API-Keys, Scopes und Berechtigungen > Verstehe, wie ein SynCore-API-Key einem Mandanten und einem Benutzer mit begrenzten Rechten zugeordnet ist. Quelle: https://support.unitedsynergy.com/api/api-keys/ Ein API-Key ist kein Generalschlüssel. Er gehört zu genau einem Mandanten und handelt für App-Tools als ein fest zugeordneter **Actor-User**. ## Zweistufiges Berechtigungsmodell | Stufe | Prüfung | | --- | --- | | API-Key | Der Schlüssel muss gültig, nicht gesperrt und mit dem Scope `app-tools` ausgestattet sein. | | Actor-User | Dessen Rollen, aktivierte Apps, Datenrechte und Datenscopes entscheiden, welche Tools sichtbar und ausführbar sind. | Ein erfolgreicher Katalogaufruf zeigt daher nicht alle SynCore-Funktionen, sondern nur die für diese technische Identität erlaubten Aktionen. ## API-Key beantragen API-Keys stellt die SynCore-Plattformadministration aus, nicht der Mandant selbst. So bereitest du den Antrag vor: 1. Lege für die Integration einen eigenen **technischen Benutzer** an, zum Beispiel „Integration Warenwirtschaft". Wie das geht, steht unter [Einen Benutzer anlegen](https://support.unitedsynergy.com/benutzer/benutzer-anlegen/). 2. Gib diesem Benutzer nur die Rollen und Datenbereiche, die die Integration wirklich braucht. 3. Wende dich an den Support und nenne: Mandant, Zweck der Integration, den technischen Benutzer, ob der Schlüssel für Test oder Produktion gedacht ist und ob er Daten löschen soll (siehe [Löschen über den Schlüssel](#löschen-über-den-schlüssel)). Der vollständige Rohwert beginnt mit `syn_` und wird nur unmittelbar nach der Erstellung angezeigt. SynCore speichert danach nur einen SHA-256-Hash und ein kurzes Präfix. > **Rohwert sofort sichern** > > Verlierst du den einmal angezeigten Rohwert, kann SynCore ihn nicht wiederherstellen. Dann wird der alte Schlüssel gesperrt und ein neuer ausgegeben. ## Ausgabe und Widerruf (Plattformadministration) 1. Öffne in der Admin-Konsole unter **Zugriff** die Seite **API Keys**. Die Liste zeigt die Schlüssel des aktiven Mandanten. Einen anderen wählst du links über der Tabelle in der Auswahl **Mandant**; hinter jedem Namen steht die Zahl seiner Schlüssel. **Alle Mandanten** zeigt alle Schlüssel nur zum Lesen, ohne Aktionen. 2. Klick oben rechts auf **Key erzeugen**. Es öffnet sich der Dialog **MCP-Zugang (App-Tools-Key)** mit dem Namen des Mandanten. 3. Wähle unter **Actor-User** den technischen Benutzer. Zur Auswahl stehen nur Mitglieder dieses Mandanten. 4. Trag unter **Bezeichnung** einen sprechenden Namen ein (vorbelegt ist „MCP App-Tools"). 5. Soll die Integration löschen dürfen, schalte **Löschen erlaubt** ein und prüf die **Grenze je Stunde** (vorbelegt 200). Ohne diesen Schalter löscht der Schlüssel nichts. 6. Klick auf **Key erzeugen** und übergib den angezeigten Schlüssel sofort auf einem sicheren Weg. Er ist nur dieses eine Mal sichtbar. Der Schlüssel bekommt immer den Scope `app-tools` und gilt für die App-Tools-API und für den [MCP-Zugang](https://support.unitedsynergy.com/mcp/verbinden/), dessen Adresse unten im Dialog steht. Schlüssel mit anderen Scopes, etwa für eine Newsletter-Anmeldung von deiner Website, stellt United Synergy aus: [Spezialanbindungen neben den App-Tools](https://support.unitedsynergy.com/api/spezialanbindungen/). In der Liste steht er mit Bezeichnung, Präfix, Mandant, Scopes, der Spalte **Löschen**, Alter, letzter Nutzung und Status. Über **⋯** in seiner Zeile: - **Bearbeiten** öffnet den Dialog **Key bearbeiten**, ebenso ein Klick auf die Zeile. Dort änderst du die **Bezeichnung** und bei Schlüsseln mit Benutzer den **Code-Mode** (mit **Programme freigeben**: **Niemand** = Programme schreiben sofort mit den Rechten des Benutzers, sonst gibt die gewählte Person jeden Schreibaufruf frei), **Löschen erlaubt** und die **Grenze je Stunde**. **Speichern** übernimmt alles in einem Schritt. Benutzer, Scopes und Laufzeit lassen sich nicht ändern; dafür stellst du einen neuen Schlüssel aus oder rotierst. - **Löschen freigeben** erscheint nur, wenn die Grenze überschritten wurde, und hebt die Sperre auf. Dasselbe geht im Dialog **Key bearbeiten** über den Hinweis oben. - **Widerrufen** sperrt den Schlüssel nach einer Rückfrage sofort, Integrationen mit diesem Schlüssel bekommen danach `401`. Ausgabe, Widerruf, Änderungen aus **Key bearbeiten** (mit altem und neuem Wert), Sperre und Freigabe stehen im Audit-Log. Die Seite **API-Keys** der Admin-Konsole zeigt alle Schlüssel mit Alter, letzter Nutzung und Status. Sie markiert Schlüssel, die nie genutzt wurden, seit 90 Tagen still sind oder älter als 180 Tage sind. Abgeschaltet wird dabei nichts. > **Kein automatischer Ablauf** > > Ein API-Key läuft nicht von selbst ab. So fällt keine Integration ohne Vorwarnung aus. Tauschen und Sperren passieren immer bewusst. ## Schlüssel tauschen 1. Lass einen neuen Schlüssel für denselben Actor-User ausgeben. 2. Stell die Integration auf den neuen Schlüssel um und prüf sie mit einem lesenden Tool. 3. Lass den alten Schlüssel widerrufen. Ein Mandant kann mehrere aktive Schlüssel haben, deshalb entsteht beim Wechsel keine Lücke. ## Actor-User nach dem Least-Privilege-Prinzip Verwende für eine Integration einen eigenen technischen Benutzer und gib ihm nur die tatsächlich benötigten Rollen und Datenbereiche. Nutze keinen Plattform-Administrator als Actor-User, nur um Berechtigungsprobleme zu umgehen. Änderungen an Rollen oder aktivierten Apps wirken beim nächsten API-Aufruf. Auch ein gültiger Schlüssel kann deshalb später einen kleineren Katalog oder `403 Forbidden` erhalten. Soll eine Integration nur lesen, gib dem technischen Benutzer eine Rolle, die nur lesen darf. Der Schlüssel kann dann nichts anlegen, ändern oder löschen. ## Löschen über den Schlüssel Jeder Schlüssel trägt zwei Einstellungen zum Löschen. Sie gelten für alles, was über diesen Schlüssel läuft, also App-Tools-API und MCP. In der Oberfläche von SynCore ändern sie nichts, dort entscheiden weiter die Rollen. | Einstellung | Wirkung | | --- | --- | | Löschen erlaubt | Aus: Tools, die Daten löschen, fehlen im Katalog und in der Tool-Liste deines MCP-Clients. Ein Aufruf trotzdem endet mit `403`. Neue Schlüssel bekommen „aus“, Schlüssel von vor dem 31.10.2026 behalten das Löschen. | | Grenze je Stunde | Höchstzahl Löschungen über diesen Schlüssel in einer Stunde, Standard 200. Die nächste Löschung endet mit `429`, danach ist Löschen über den Schlüssel gesperrt und die Plattformadministration bekommt einen Alarm. Lesen, Anlegen und Ändern laufen weiter. | Ob der Actor-User etwas löschen darf, entscheiden weiter seine Rollen. Die Einstellungen am Schlüssel schränken nur ein, sie erlauben nie mehr, als die Rollen erlauben. Eine Sperre nach überschrittener Grenze hebt nur die Plattformadministration auf. Viele Datensätze landen beim Löschen im Papierkorb und lassen sich von dort zurückholen, Einträge in Wertelisten werden dagegen endgültig gelöscht. ## Schlüssel sicher verwenden - Übertrage den Schlüssel ausschließlich über HTTPS im Header `X-API-KEY`. - Verwende nie Query-Parameter wie `?apiKey=...`. - Halte Schlüssel aus Quellcode, Browser-Frontend, Logs, Tickets und Screenshots heraus. - Speichere ihn in einem Secret Store oder als geschützte Umgebungsvariable. - Verwende getrennte Schlüssel für Test und Produktion. - Sperre einen kompromittierten oder nicht mehr benötigten Schlüssel sofort. - Stimme eine regelmäßige Rotation mit allen beteiligten Systemen ab. ## Wo welcher Schlüssel liegt | Was | Wo abgelegt | Wer nutzt es | | --- | --- | --- | | Dein SynCore-API-Key im Klartext | Auf der Seite der Integration: Secret Store oder geschützte Umgebungsvariable | Nur die Integration | | Derselbe Schlüssel in SynCore | Nur als SHA-256-Hash mit Präfix, nicht umkehrbar | SynCore prüft damit jede Anfrage | | Zugangsdaten, die SynCore für andere Dienste braucht, zum Beispiel Kartendienst, Mailversand oder angebundene externe Tools | Im **Credential Store** der Admin-Konsole, je Mandant verschlüsselt (AES-256-GCM) | Nur SynCore selbst. Anlegen, Ändern und Löschen stehen im Audit-Log, der letzte Zugriff wird vermerkt | Leg deinen SynCore-API-Key nicht im Credential Store ab. Der ist für Zugangsdaten gedacht, mit denen SynCore andere Dienste aufruft, nicht für Schlüssel, mit denen andere SynCore aufrufen. ## Authentifizierungsbeispiel ```http GET /api/app-tools?includeStructure=1 HTTP/1.1 Host: syncore.example.com X-API-KEY: syn_... Accept: application/json ``` Der Headername ist nicht case-sensitiv. In der Dokumentation verwenden wir einheitlich `X-API-KEY`. ## Typische Authentifizierungsfehler | Status | Bedeutung | | --- | --- | | `401` | Schlüssel fehlt, ist unbekannt oder wurde gesperrt. | | `403` | Scope `app-tools` fehlt, kein Actor-User ist zugeordnet, dessen Berechtigung reicht nicht aus, oder der Schlüssel darf nicht löschen bzw. ist für Löschungen gesperrt. | | `429` | Zu viele Anfragen mit diesem Schlüssel (warte die Sekunden aus `Retry-After` ab) oder die Grenze für Löschungen je Stunde ist erreicht (dann bleibt Löschen gesperrt, bis die Plattformadministration freigibt). | Mehr Fälle mit den genauen Meldungen stehen unter [Wenn eine API-Anfrage scheitert](https://support.unitedsynergy.com/api/fehlerbehebung/). Gib bei einer Supportanfrage nur das sichtbare Schlüsselpräfix und den Namen des Schlüssels an, niemals den vollständigen Rohwert. --- # Sicherheit der API > Wie SynCore Zugriffe über die API schützt, was deine Integration beitragen muss und wo du Sicherheitslücken meldest. Quelle: https://support.unitedsynergy.com/api/sicherheit/ Diese Seite fasst zusammen, wie die SynCore-API geschützt ist und was deine Integration selbst beitragen muss. Sie hilft dir bei der Einrichtung und bei einer Sicherheitsprüfung, zum Beispiel wenn du als Einrichtung unter NIS2 deine Dienstleister bewerten musst. ## Was SynCore schützt - **Schlüssel:** Ein API-Key besteht aus `syn_` und 24 Zufallsbytes. SynCore speichert davon nur einen SHA-256-Hash und die ersten zwölf Zeichen als Erkennungsmerkmal. Den vollständigen Schlüssel siehst du genau einmal, bei der Ausgabe. - **Zweck:** Jeder Schlüssel trägt Scopes. Ein App-Tools-Schlüssel öffnet nur die App-Tools, jede [Spezialanbindung](https://support.unitedsynergy.com/api/spezialanbindungen/) verlangt ihren eigenen Scope. - **Rechte:** Ein App-Tools-Schlüssel handelt als ein technischer Benutzer, der Actor-User. Die API prüft bei jedem Aufruf dieselben Rollen, Rechte und Datenbereiche wie in der Oberfläche. Hat der Schlüssel keinen Actor-User oder gibt es ihn nicht mehr, lehnt SynCore jeden Aufruf ab. - **Mandantentrennung:** Ein Schlüssel gehört zu genau einem Mandanten. Kein Feld der Anfrage kann den Mandanten wechseln, jede Abfrage bleibt auf diesen Mandanten beschränkt. - **Besonders geschützte Daten:** Tools für Daten der Datenklasse D, etwa Personalakten, Abwesenheiten, Schülerdaten und Lohnabrechnungen, bietet die API nicht an. Diese Daten bearbeitest du nur in der Oberfläche. - **Änderungen mit Rückfrage:** Tools, die Daten anlegen, ändern oder löschen, sind im Katalog mit `confirmationRequired` gekennzeichnet. SynCore markiert, deine Anwendung holt die ausdrückliche Bestätigung ein. - **Protokoll:** Standardmäßig steht jeder ausgeführte Aufruf mit Mandant, Actor-User, Tool und Ergebnis im Audit-Log, auch ein fachlich gescheiterter. Die Eingabedaten selbst speichert das Protokoll nicht. Mandanten-Administratoren können die Protokollierung einzelner Bereiche abschalten. Belege, Personal- und Schülerdaten werden immer protokolliert. - **Anfragelimits:** Pro Schlüssel sind 1.200 Anfragen pro Minute und Endpunkt erlaubt, darüber antwortet SynCore mit `429`. Details stehen unter [Anfragelimits](https://support.unitedsynergy.com/api/app-tools/#anfragelimits). - **Kein Zugriff aus fremden Webseiten:** Die API sendet keine CORS-Freigaben. Skripte auf anderen Webseiten können sie im Browser deshalb nicht aufrufen. Der MCP-Zugang lehnt Anfragen mit fremdem `Origin` zusätzlich mit `403` ab. - **MCP mit denselben Regeln:** Der [MCP-Zugang](https://support.unitedsynergy.com/mcp/verbinden/) nutzt dieselben Schlüssel und dieselben Prüfungen wie die App-Tools-API. Im Audit-Log steht als Quelle „mcp“. Mit `?nur=lesen` an der Adresse sieht ein Assistent nur Werkzeuge, die nichts verändern. - **Fehlermeldungen ohne Interna:** Scheitert ein Tool an der Datenbank, nennt die Antwort nur den Fehlercode und einen verständlichen Satz, keine Abfragen und keine Tabellennamen. - **Sofortige Sperre:** Ein widerrufener Schlüssel gilt ab der nächsten Anfrage nicht mehr, die Integration bekommt `401`. - **Zugangsdaten zu fremden Diensten:** Passwörter und Schlüssel für angebundene Dienste liegen verschlüsselt (AES-256-GCM) je Mandant im Credential Store, getrennt von den API-Keys. Mehr dazu unter [Wo welcher Schlüssel liegt](https://support.unitedsynergy.com/api/api-keys/). ## Was deine Integration beitragen muss 1. Leg für jede Integration einen eigenen technischen Benutzer mit knappen Rechten an, nie ein persönliches Konto: [API-Key beantragen](https://support.unitedsynergy.com/api/api-keys/). 2. Halte den Schlüssel auf dem Server, in einem Secret-Speicher oder einer Umgebungsvariable. Er gehört nicht in Browser-Code, Repositories, Tickets, Mails oder in den Chat mit einem KI-Assistenten. 3. Ruf SynCore nur über die HTTPS-Adresse deiner Instanz auf. 4. Führ Tools mit `confirmationRequired` erst nach ausdrücklicher Bestätigung aus und prüf das Ergebnis mit einem Lese-Tool. 5. Tausch Schlüssel regelmäßig, denn sie laufen nicht von selbst ab. Könnte ein Schlüssel bekannt geworden sein, lass ihn sofort widerrufen. 6. Speichere Antworten mit Personendaten nur so lange, wie deine Anwendung sie braucht, und schreib sie nicht in Protokolle. > **Sicherheitskonzept für Prüfungen** > > Für eine Sicherheitsprüfung, zum Beispiel als Einrichtung unter NIS2, stellt United Synergy das Sicherheitskonzept von SynCore auf Anfrage über den [Support](https://support.unitedsynergy.com/support/) bereit. ## Sicherheitslücke gefunden? Schreib an **security@unitedsynergy.com**. Die Kontaktdaten stehen auch in der Datei `/.well-known/security.txt` jeder SynCore-Instanz. Beschreib, was du gefunden hast und wie es sich nachstellen lässt. Schick keine echten Personendaten und nie einen vollständigen API-Key. > **Wenn du einen Missbrauch vermutest** > > Lass den betroffenen Schlüssel sofort widerrufen und melde den Vorfall über den [Support](https://support.unitedsynergy.com/support/). Nenne das Präfix des Schlüssels, den Zeitraum und was dir aufgefallen ist. --- # App-Tools-API Referenz > Referenz für Katalogabruf, Tool-Metadaten, Ausführung, Antworten und Fehler der SynCore-App-Tools-API. Quelle: https://support.unitedsynergy.com/api/app-tools/ Die App-Tools-API hat einen zentralen Endpunkt. `GET` liefert den berechtigungsgefilterten Katalog, `POST` führt genau ein darin beschriebenes Tool aus. KI-Assistenten erreichen dieselben Tools über MCP: [MCP und KI-Assistenten im Überblick](https://support.unitedsynergy.com/mcp/uebersicht/). ## Basis und Authentifizierung - Basis-URL: die HTTPS-Adresse deiner SynCore-Instanz - Endpunkt: `/api/app-tools` - Authentifizierung: Header `X-API-KEY` - Content-Type bei `POST`: `application/json` ## GET /api/app-tools Liefert alle für den Actor-User sichtbaren Tools. ### Query-Parameter | Parameter | Typ | Standard | Bedeutung | | --- | --- | --- | --- | | `includeStructure` | Boolean | `false` | Bei `1`, `true` oder `yes` zusätzlich App-Struktur, effektive Rechte und Laufzeitregeln liefern. | | `stufe` | Text | keine | `name`, `beschreibung`, `schema` oder `typescript`, siehe [Katalog in Stufen](#katalog-in-stufen). Ohne Angabe kommt die volle Form wie bisher. | | `app` | Text | alle | Nur Tools dieser Apps, mehrere durch Komma getrennt, zum Beispiel `crm,projektsyn`. | | `suche` | Text | keine | Suchbegriffe durch Leerzeichen getrennt. Jeder Begriff muss in Name, App-Bezeichnung oder Beschreibung vorkommen. | Empfohlener Aufruf: ```http GET /api/app-tools?includeStructure=1 HTTP/1.1 Host: syncore.example.com X-API-KEY: syn_... Accept: application/json ``` ### Katalog in Stufen Bei vollen Rechten liefert der Katalog über 1.000 Tools, rund 700 KB. Für das Finden reicht meist weniger: | Stufe | Inhalt je Tool | Größe des vollen Katalogs | | --- | --- | --- | | `name` | `name`, `module`, `sideEffect` | rund 80 KB | | `beschreibung` | dazu `appId`, `label`, `description`, `confirmationRequired`, `dataClasses` | rund 270 KB | | `schema` | alle Felder aus [Tool-Metadaten](#tool-metadaten) | rund 700 KB | | `typescript` | die Tools als TypeScript-Deklaration, Antwort als Text statt JSON | rund 550 KB | Mit Stufe enthält die Antwort zusätzlich `stufe` und `anzahl`. Sinnvoll ist ein Ablauf in zwei Schritten: erst `?stufe=name&suche=konto` zum Finden, dann `?stufe=schema&suche=crm.konto.list` für die Eingaben. `?stufe=typescript&app=crm` liefert die Tools der App als Deklaration, die ein Programm oder ein KI-Agent direkt verwenden kann: ```ts declare const syncore: { crm: { /** Liste/Suche: Konten (CRM) … */ konto_list(input: CrmKontoListInput): Promise>; }; }; ``` Die Typen beschreiben nur die Eingaben. Geprüft wird bei jedem `POST` weiter im Server: Schema, Rechte und Datenbereich. Jede Antwort trägt einen `ETag`. Schickst du ihn beim nächsten Abruf im Header `If-None-Match` mit und hat sich nichts geändert, antwortet SynCore mit `304` ohne Inhalt. Eine unbekannte Stufe oder eine ungültige App-Kennung beantwortet SynCore mit `400`. ### Tool-Metadaten | Feld | Bedeutung | | --- | --- | | `name` | Stabiler Name, der bei `POST` unverändert verwendet wird. | | `module` / `appId` | Zugehörige SynCore-App und stabile App-ID. | | `label` / `description` | Anzeigename und fachliche Beschreibung. | | `inputSchema` | Zulässige Eingabe als JSON-Schema. | | `outputSchema` | Beschreibung der Ausgabe, sofern für das Tool hinterlegt. | | `requires` | Erforderliche fachliche Berechtigungen. | | `dataClasses` | Betroffene Datenklassen. Tools für besonders geschützte Klasse-D-Daten werden nicht über diese Fläche angeboten. | | `sideEffect` | Kennzeichnet, ob das Tool Daten liest oder einen Seiteneffekt auslöst. | | `confirmationRequired` | Eine aufrufende Anwendung muss vor der Ausführung eine ausdrückliche Bestätigung einholen. | | `dsgvoNote` | Datenschutzhinweis zum Umfang der verarbeiteten oder übertragenen Daten. | > **Der Katalog ist die Vertragsgrundlage** > > Verwende keine fest eingebaute globale Tool-Liste. Apps, Rechte, Datenscopes und Tool-Schemas können sich je Mandant und Version unterscheiden. Maßgeblich ist immer die aktuelle GET-Antwort der Zielinstanz. Hat dein Mandant externe Dienste angebunden, können deren Tools ebenfalls im Katalog stehen. `dsgvoNote` nennt dann, welche Daten an den Dienst gehen. Alle Tools, die SynCore mitbringt, stehen mit Eingabefeldern und nötigen Rechten in der [Referenz nach App](https://support.unitedsynergy.com/api/referenz/). Welche davon du tatsächlich aufrufen darfst, zeigt dein Katalog. ## POST /api/app-tools Führt ein Tool im Kontext des Mandanten und des Actor-Users aus. ### Request Body ```json { "name": "textbausteine.list_templates", "input": { "typ": "PDF", "limit": 20 } } ``` | Feld | Pflicht | Bedeutung | | --- | --- | --- | | `name` | ja | Exakter Tool-Name aus dem aktuellen Katalog. | | `input` | nein | JSON-Objekt entsprechend `inputSchema`; ohne Eingabe `{}` verwenden. | Vor der Ausführung prüft SynCore den Tool-Namen, das Eingabeschema, die App-Aktivierung, alle benötigten Berechtigungen und den effektiven Datenscope. ### Erfolgreiche Antwort ```json { "ok": true, "tool": "textbausteine.list_templates", "module": "textbausteine", "data": [] } ``` Je nach Tool können zusätzlich unter anderem `summary`, `entityType`, `entityId`, `needsSelection` oder `candidates` vorkommen. Beachte das gelieferte `outputSchema` und behandle unbekannte zusätzliche Felder tolerant. Wenn `needsSelection: true` zurückkommt, darfst du nicht automatisch weiterschreiben. Zeige die Kandidaten an und lasse den Benutzer auswählen. ### Listen blättern Jedes lesende Listen-Tool nimmt `limit` und `offset` an. Liefert ein Tool höchstens 200 Einträge auf einmal (Standard und Höchstwert, bei den Datenobjekt-Listen `…list` Standard 50), steht in der Antwort zusätzlich `seite`: ```json { "ok": true, "tool": "textbausteine.list_documents", "data": [ … ], "seite": { "offset": 0, "limit": 200, "gesamt": 312, "weitere": true } } ``` Bei `weitere: true` holst du die nächste Seite mit `offset` plus `limit`, hier `"offset": 200`. Ein `limit` über 200 beantwortet SynCore mit `400`. Einige Listen-Tools liefern statt einer Liste ein kleines Objekt, etwa die Stufen einer Pipeline oder die Freigaben eines Datensatzes. Dort gibt es kein `limit`, das Eingabeschema im Katalog zeigt es. ## Verbindlicher Ablauf bei Änderungen 1. Katalog und Struktur abrufen. 2. Zielentität über ein Lese- oder Such-Tool eindeutig bestimmen. 3. Eingabe gegen `inputSchema` aufbauen. 4. Bei `confirmationRequired: true` die konkrete Aktion bestätigen lassen. 5. Mutation ausführen. 6. Ergebnis mit einem Lese- oder Listen-Tool verifizieren. Die Bestätigung ist eine Prozesspflicht der aufrufenden Anwendung. Es gibt dafür kein pauschales `confirmed`-Feld im Transportformat. ## Dateien an einen Datensatz hängen Mit `files.upload` legst du eine Datei an einem Datensatz ab, zum Beispiel ein Angebot an einem Projekt oder ein Foto an einer Aufgabe. `files.list` zeigt danach, was dort hängt. ```json { "name": "files.upload", "input": { "filename": "Angebot.pdf", "mimeType": "application/pdf", "contentBase64": "JVBERi0xLjcK...", "ownerType": "projektsyn.projekt", "ownerId": "prj_123" } } ``` | Feld | Pflicht | Bedeutung | | --- | --- | --- | | `filename` | ja | Dateiname mit Endung, höchstens 255 Zeichen. | | `mimeType` | ja | Dateityp, zum Beispiel `application/pdf` oder `image/png`. Er muss zum Inhalt passen. | | `contentBase64` | ja | Dateiinhalt als Base64, auch als `data:`-URL. | | `ownerType` | ja | Art des Datensatzes: `projektsyn.projekt`, `projektsyn.ticket`, `crm.konto`, `crm.kontakt`, `crm.potenzial`, `vertraege.vertrag`, `auftraege.auftrag`, `produkte.artikel`, `seminar.katalog` oder `seminar.veranstaltung`. | | `ownerId` | ja | ID des Datensatzes aus dem passenden Lese-Tool. | | `tags` | nein | Schlagworte. | | `folderId` | nein | Ordner im Dateispeicher deines Mandanten. | Es gelten dieselben Regeln wie beim Hochladen im Browser: - Du brauchst das Recht, den Datensatz zu bearbeiten, und er muss in deinem Datenbereich liegen. Für `files.list` reicht das Leserecht. - Ein Datensatz, den es in deinem Mandanten nicht gibt oder den du nicht sehen darfst, ergibt `404`. - Erlaubt sind PDF, Word, Excel, PowerPoint, Bilder (PNG, JPEG, GIF, WebP, HEIC), Text, CSV, JSON, XML und ZIP. SynCore prüft den Inhalt gegen den angegebenen Typ, HTML und SVG werden abgelehnt. - Eine vorhandene Datei wird nicht ersetzt, jeder Aufruf legt eine neue an. - Die größte Datei bestimmt deine Instanz (Standard 100 MB). Base64 macht die Anfrage etwa ein Drittel größer als die Datei, plane große Dateien entsprechend ein oder lade sie im Browser hoch. Personal-, Bewerber-, Bildungs- und Belegakten nimmt das Tool bewusst nicht an. Lade Dokumente dort über die jeweilige Seite in SynCore hoch. ## Große Dateien ohne Base64: Upload- und Download-Link Base64 im Aufruf kostet Tokens: jedes Byte der Datei läuft durch das Sprachmodell, grob 400.000 Tokens je Megabyte. Von außen (MCP, API) nimmt `files.upload` deshalb nur kleine Dateien an (Standard 1 MB). Für alles, was als Datei vorliegt, gibt es den Link-Weg: das Werkzeug meldet die Datei an und liefert eine Adresse samt fertigem Befehl, die Bytes gehen direkt von der Platte zum Server. 1. `files.upload_link` mit Name, Typ und Datensatz aufrufen. Die Antwort enthält `url`, `expiresAt` und `befehle.bash` beziehungsweise `befehle.powershell`. 2. Den Befehl im Ordner der Datei ausführen, zum Beispiel: ```bash curl -sS -f -T "foto.png" -H "Content-Type: image/png" "https://deine-instanz/api/files/direkt/" ``` 3. Die Antwort des PUT ist die angelegte Datei (`id`, `url`). Mit `files.list` prüfen. Für den Weg zurück liefert `files.download_link` mit der `id` aus `files.list` eine Adresse für `GET`, zum Beispiel `curl -sS -f -o "foto.png" ""`. Die Datei kommt als Anhang. Regeln: - Ein Upload-Link gilt 15 Minuten und genau einmal, ein Download-Link 10 Minuten und bis dahin mehrfach. - Der Link ist an deinen Mandanten, deine Person, deinen API-Key und den Datensatz gebunden. Ein widerrufener Key macht den Link ungültig. Beim Abruf prüft SynCore das Recht am Datensatz noch einmal. - Der `Content-Type` im Befehl muss zum angemeldeten Typ passen, sonst antwortet der Server mit `415`. Ohne `Content-Type` gilt der angemeldete Typ. - Beim Empfang gelten dieselben Prüfungen wie beim Hochladen im Browser (Typ-Allowlist, Inhalt, Größe, Virenscan). Wird die Datei abgelehnt, bleibt der Link bis zum Ablauf für einen korrigierten Versuch offen. - Je Person sind höchstens 20 offene Links gleichzeitig möglich. - Das Protokoll enthält Name, Typ und Größe, nie den Inhalt. Der Befehl braucht eine Shell. Claude Code, Cursor und Skripte können ihn ausführen, ein Chat-Client ohne Shell nicht; dort bleibt `files.upload` für kleine Dateien. ## HTTP-Statuscodes | Status | Bedeutung | | --- | --- | | `200` | Katalog geliefert oder Tool erfolgreich ausgeführt. | | `400` | Tool-Name fehlt, JSON ist ungültig oder `input` verletzt das Schema. | | `401` | Session beziehungsweise API-Key fehlt oder ist ungültig. | | `403` | Scope, Actor-User, App-Aktivierung oder fachliche Berechtigung fehlt. | | `404` | Der angegebene Tool-Name existiert nicht, oder das Tool findet den angegebenen Datensatz nicht. | | `413` | Die Datei ist größer, als die Instanz annimmt (`files.upload`, `/api/files/direkt/`), oder der Base64-Aufruf von außen liegt über der kleinen Grenze (dann `files.upload_link` nehmen). | | `410` | Der Direktlink ist abgelaufen oder schon benutzt (`/api/files/direkt/`). | | `415` | Der `Content-Type` des PUT passt nicht zum angemeldeten Typ (`/api/files/direkt/`). | | `422` | Das Tool wurde gefunden, konnte die fachliche Aktion aber nicht ausführen. | | `429` | Zu viele Anfragen. Warte die Sekunden aus dem Header `Retry-After` ab. | | `501` | Für ein registriertes Tool fehlt serverseitig ein Handler; bitte den Support informieren. | ## Fehlerantworten Bei `400`, `401`, `403`, `404`, `413` und `501` steht die Ursache im Feld `message`: ```json { "message": "Tool nicht gefunden: crm.konto_lsit" } ``` Bei einem fachlichen Fehler liefert `422` stattdessen `ok`, `tool` und `error`: ```json { "ok": false, "tool": "beispiel.tool", "error": "Fachliche Ursache" } ``` `429` antwortet mit einem kurzen Klartext statt JSON und dem Header `Retry-After`. Welche Meldung was bedeutet, steht unter [Wenn eine API-Anfrage scheitert](https://support.unitedsynergy.com/api/fehlerbehebung/). Wiederhole `400`, `403` oder `422` nicht blind. Korrigiere zuerst Eingabe, Rechte oder fachlichen Zustand. ## Anfragelimits SynCore zählt Anfragen mit API-Key je Schlüssel, Methode und Endpunkt in einem Zeitfenster von einer Minute. | Limit | Standardwert | Folge | | --- | --- | --- | | Anfragen je API-Key | 1.200 pro Minute, getrennt für `GET` und `POST` | `429 Zu viele Anfragen` bis zum Ende des Zeitfensters | Jede Antwort trägt `X-RateLimit-Limit` (Limit im Zeitfenster) und `X-RateLimit-Remaining` (verbleibende Anfragen). Bei `429` nennt `Retry-After` die Wartezeit in Sekunden. Die Werte sind Standardwerte und können je Instanz abweichen. > **Sauber mit Limits umgehen** > > Verteile Massenläufe über die Zeit, wiederhole nach `429` erst nach `Retry-After` und nur einmal. Bei `401` prüfst du zuerst den Schlüssel, statt die Anfrage in einer Schleife zu wiederholen. ## OpenAPI-Datei Die Transport-API kannst du als [OpenAPI 3.1 herunterladen](https://support.unitedsynergy.com/openapi/syncore-app-tools.openapi.json) und in Postman, Bruno oder Insomnia importieren. Da die verfügbaren Tools dynamisch sind, ersetzt die OpenAPI-Datei nicht den Katalogabruf. --- # API-Anfragen sicher testen > Teste den App-Tool-Katalog und einzelne SynCore-Tools mit PowerShell, curl oder einer OpenAPI-Anwendung. Quelle: https://support.unitedsynergy.com/api/anfragen-testen/ Teste Integrationen zuerst mit einem eigenen Testschlüssel und einem Actor-User mit begrenzten Rechten. Beginne immer mit einem lesenden Tool. > **Kein API-Key im Hilfe-Center** > > Gib deinen echten API-Key niemals auf einer öffentlichen Webseite ein. Der Befehls-Generator unten verarbeitet nur URL, Tool-Name und JSON lokal im Browser. Er sendet nichts und verwendet im Ergebnis ausschließlich die Variable `SYNCORE_API_KEY`. ## 1. Schlüssel im Terminal setzen PowerShell: ```powershell $env:SYNCORE_API_KEY = 'syn_DEIN_SCHLUESSEL' ``` Bash: ```bash export SYNCORE_API_KEY='syn_DEIN_SCHLUESSEL' ``` ## 2. Katalog testen PowerShell: ```powershell $BaseUrl = 'https://syncore.example.com' $Headers = @{ 'X-API-KEY' = $env:SYNCORE_API_KEY } $Catalog = Invoke-RestMethod ` -Method Get ` -Uri "$BaseUrl/api/app-tools?includeStructure=1" ` -Headers $Headers $Catalog.tools | Select-Object name, module, sideEffect, confirmationRequired ``` Prüfe, ob nur die erwarteten Apps und Aktionen erscheinen. Ein zu großer Katalog deutet auf zu weit gefasste Rollen des Actor-Users hin. ## 3. Ausführbaren Befehl erzeugen Übernimm einen Tool-Namen aus deinem aktuellen Katalog und baue die Eingabe nach dessen `inputSchema`. *(Im Hilfe-Center steht hier ein Generator, der aus Basis-URL, Tool-Name und Eingabe einen PowerShell- und einen curl-Befehl baut: `POST /api/app-tools`, Header `X-API-KEY`, Body `{"name": "", "input": {…}}`.)* ## 4. Ergebnis bewerten - HTTP `200` und `ok: true`: Transport, Schlüssel, Rechte und Tool-Ausführung waren erfolgreich. - Leere Daten sind nicht automatisch ein Fehler; möglicherweise gibt es im Datenscope keine passenden Datensätze. - `needsSelection: true`: Kandidaten anzeigen und eine Auswahl anfordern. - Bei einer Mutation den Zielzustand anschließend mit einem Lese-Tool prüfen. - HTTP `429`: die Sekunden aus `Retry-After` abwarten und die Anfrage dann einmal wiederholen. - Fehler nach Statuscode behandeln und keine automatischen Endlosschleifen bauen. Die Meldungen und ihre Ursachen stehen unter [Wenn eine API-Anfrage scheitert](https://support.unitedsynergy.com/api/fehlerbehebung/). ## Mit OpenAPI-Tools testen 1. Lade die [SynCore App-Tools OpenAPI-Datei](https://support.unitedsynergy.com/openapi/syncore-app-tools.openapi.json) herunter. 2. Importiere sie in Postman, Bruno oder Insomnia. 3. Setze die Server-Variable `baseUrl` auf deine SynCore-Instanz. 4. Hinterlege `X-API-KEY` als geschütztes Secret der lokalen Umgebung. 5. Rufe zuerst `GET /api/app-tools?includeStructure=1` auf. 6. Kopiere einen sichtbaren Tool-Namen und dessen Eingabeschema in den `POST`-Request. Die OpenAPI-Datei beschreibt den stabilen Transport. Welche fachlichen Tools verfügbar sind, bestimmt ausschließlich der aktuelle Katalog der Zielinstanz. ## Abnahmereihenfolge Für einen nachvollziehbaren Integrationstest empfehlen wir: 1. Ungültiger Key ergibt `401`. 2. Gültiger Key liefert einen berechtigungsgefilterten Katalog. 3. Ein lesendes Tool liefert `ok: true`. 4. Ein absichtlich unzulässiges Eingabefeld beziehungsweise ein falscher Typ ergibt `400`. 5. Ein schreibendes Tool wird erst nach Bestätigung ausgeführt. 6. Der geänderte Zustand wird per Readback nachgewiesen. 7. Ein gesperrter Schlüssel wird unmittelbar mit `401` abgewiesen. Dokumentiere dabei Instanz, Version, Zeitpunkt, Schlüsselpräfix, Tool-Name und Ergebnis, aber niemals den vollständigen API-Key oder personenbezogene Antwortdaten. --- # Spezialanbindungen neben den App-Tools > Welche festen Schnittstellen SynCore für Website-Formulare, Shops, Partner-Apps und die Einrichtung von Rollen anbietet und wie du einen Schlüssel dafür bekommst. Quelle: https://support.unitedsynergy.com/api/spezialanbindungen/ Fast alles, was du per API mit SynCore machst, läuft über die [App-Tools](https://support.unitedsynergy.com/api/app-tools/). Für einige feste Aufgaben gibt es zusätzlich eigene Endpunkte, zum Beispiel für ein Anmeldeformular auf deiner Website oder für Bestellungen aus einem Shop. Jeder davon verlangt einen eigenen Scope. ## Was für alle Spezialanbindungen gilt - Du authentifizierst dich mit dem Header `X-API-KEY`. Eine Anmeldung im Browser zählt hier nicht. - Der Schlüssel bestimmt den Mandanten. Kein Feld in der Anfrage kann ihn ändern. - Jeder Endpunkt prüft seinen eigenen Scope. Ein App-Tools-Schlüssel öffnet keine Spezialanbindung, und ein Schlüssel für eine Spezialanbindung öffnet keine App-Tools. - Fehlt der Schlüssel oder ist er ungültig, antwortet SynCore mit `401`. Fehlt der Scope, kommt `403` mit der Meldung `API-Key fehlt Scope: …`. - Pro Schlüssel sind 1.200 Anfragen pro Minute erlaubt. Endpunkte, die Mails auslösen, zählen strenger und pro IP-Adresse: 30 pro Minute für den Mailversand, 10 pro Minute für die Newsletter-Anmeldung. Darüber kommt `429` mit dem Header `Retry-After`. > **Schlüssel bekommst du über United Synergy** > > In der Plattformadministration lassen sich nur App-Tools-Schlüssel erzeugen. Schlüssel für Spezialanbindungen stellt United Synergy aus, jeweils nur mit dem Scope, den die Anbindung braucht. Schreib uns über den [Support](https://support.unitedsynergy.com/support/), wofür du die Anbindung brauchst und welcher Benutzer als Actor-User dahinterstehen soll. ## Übersicht | Anbindung | Endpunkt | Scope | | --- | --- | --- | | Newsletter-Anmeldung von deiner Website | `POST /api/newsletter/anmeldung` | `newsletter.anmeldung` | | Kontakte aus Formularen ins CRM | `POST /api/crm/import` | `crm.import` | | Seminarbuchung aus einem Shop | `POST /api/seminar/webhook/order` | `seminar:webhook` | | Mails über das Postfach des Mandanten | `POST /api/mail/relay` | `mail.relay` | | Rollen und Rechte einrichten | `POST /api/admin/roles`, `PUT /api/admin/roles/{slug}/permissions` | `iam:manage` | ## Newsletter-Anmeldung von deiner Website Dein Formular schickt die Anmeldung an deinen eigenen Server, und der ruft SynCore mit dem Schlüssel auf. Der Schlüssel gehört nie in den Browser. ```json { "email": "anna@example.com", "name": "Anna Beispiel", "company": "Beispiel GmbH", "quelle": "Website Fußzeile" } ``` - Pflicht ist nur `email`. `name`, `company` und `quelle` sind freiwillig. - SynCore verschickt eine Bestätigungsmail (Double-Opt-in). Pro Adresse geht höchstens eine Bestätigungsmail in 24 Stunden raus. - Ist die Adresse noch nicht im CRM, legt SynCore Konto und Kontakt erst an, wenn die Person den Link in der Bestätigungsmail anklickt. Unbestätigte Adressen speichert SynCore nicht. - Die Antwort ist immer `{ "ok": true }`, auch wenn die Adresse schon bekannt ist. So kann niemand über das Formular herausfinden, wer im CRM steht. - Schickst du das Feld `website` mit einem Wert mit, behandelt SynCore die Anfrage als Bot und speichert nichts. Das Feld eignet sich als unsichtbare Falle in deinem Formular. ## Kontakte aus Formularen ins CRM Der Endpunkt legt Konto und Kontakt an oder hängt einen Kontakt an ein bestehendes Konto. Er arbeitet in drei Schritten, die du über `mode` wählst: | `mode` | Was passiert | Nötiges Recht des Actor-Users | | --- | --- | --- | | `preview` (Standard) | Sucht mögliche Dubletten. Schreibt nichts. | Konto lesen | | `search` | Sucht Konten per Freitext im Feld `search`. | Konto lesen | | `commit` | Legt Konto und Kontakt an oder hängt den Kontakt an `kontoId`. | Konto anlegen | ```json { "mode": "commit", "konto": { "name": "Beispiel GmbH", "email": "info@beispiel.de" }, "kontakt": { "vorname": "Anna", "nachname": "Beispiel", "email": "anna@beispiel.de" }, "nachricht": "Bitte um Rückruf wegen einer Demo.", "source": "Kontaktformular", "tags": ["website-lead"] } ``` - Prüf vor dem Anlegen mit `preview`, ob es das Konto schon gibt. Gibt es einen Treffer, schickst du beim `commit` dessen `kontoId` mit. - `nachricht` landet als Eintrag im Verlauf des Kontos. Mit `tags` gibst du einem neu angelegten Konto bis zu fünf Schlagworte mit. - Legt SynCore ein neues Konto an, antwortet es mit `201`, sonst mit `200`. Die Antwort enthält `kontoId`, `kontaktId` und `created`. ## Seminarbuchung aus einem Shop Nach einer abgeschlossenen Bestellung meldet dein Shop die Buchung an SynCore. ```json { "veranstaltungId": "", "teilnehmer": { "personId": "", "organisationId": "", "gebuehrNetto": 490 }, "belegErzeugen": true } ``` - Pflicht ist `veranstaltungId`. Die Buchung bekommt den Teilnehmerstatus „angemeldet“. - Mit `belegErzeugen: true` legt SynCore gleich den Beleg zur Anmeldung an. - Die Antwort enthält `buchungId` und, falls erzeugt, `belegId`. ## Mails über das Postfach des Mandanten Für Partner-Apps, die im Namen des Mandanten Mails verschicken, zum Beispiel die Rettungsheft-App. SynCore verschickt über das Mailkonto, das im Mandanten eingerichtet ist. ```json { "to": "empfaenger@example.com", "toName": "Max Beispiel", "subject": "Deine Anmeldung", "text": "Hallo Max, deine Anmeldung ist eingegangen." } ``` - Pflicht sind `to`, `subject` und entweder `text` oder `html`. - Den Absender bestimmt immer SynCore. Ein Absenderfeld gibt es nicht, damit der Endpunkt kein offenes Mail-Relay wird. - Jeder Versand steht im Mail-Protokoll und im Audit-Log. ## Rollen und Rechte einrichten Für Partner, die einen neuen Mandanten automatisch einrichten. Mit `POST /api/admin/roles` legst du eine Rolle an (`label` ist Pflicht, `slug` und `description` sind freiwillig). Mit `PUT /api/admin/roles/{slug}/permissions` setzt du ihre Rechte: - `{ "seed": "defaults" }` übernimmt die Standardrechte der Apps. - `{ "grants": [{ "permissionKey": "…", "scope": "…" }] }` setzt die Rechte ausdrücklich. Administratorrollen und Administratorrechte lassen sich über diesen Weg nicht ändern. ## Anbindungen, die United Synergy einrichtet - **Rettungsheft-App:** Nachweise, Stundenplan, Anwesenheit per QR-Code und Kurse laufen über eigene Endpunkte. United Synergy richtet sie beim Einrichten der App ein, du musst dafür nichts programmieren. - **Externe Lern- und Praxisplattformen:** Rückmeldungen von Lernergebnissen und Praxisdurchgängen richtet United Synergy mit dem jeweiligen Anbieter ein. - **Betrieb der Plattform:** Schnittstellen für Updates, Lizenzen und Sicherheitsmeldungen nutzt nur United Synergy. Sie stehen deshalb nicht in dieser Hilfe. > **Wenn eine Spezialanbindung scheitert** > > Prüf zuerst Scope und Actor-User des Schlüssels: `403` mit `API-Key fehlt Scope` heißt, dass der Schlüssel für einen anderen Zweck ausgestellt ist. Weitere Meldungen erklärt [Wenn eine API-Anfrage scheitert](https://support.unitedsynergy.com/api/fehlerbehebung/). --- # Wenn eine API-Anfrage scheitert > Statuscode und Meldung einordnen und die Ursache bei Schlüssel, Rechten, Eingabe oder Limit finden. Quelle: https://support.unitedsynergy.com/api/fehlerbehebung/ Jede abgewiesene Anfrage nennt einen Statuscode und eine Meldung. Bei den meisten Fehlern steht die Meldung im Feld `message`, bei `422` im Feld `error`. Die Tabellen zeigen, womit die Meldung beginnt, was dahintersteckt und was du tun kannst. ## 401: Der Schlüssel wird nicht akzeptiert | Meldung beginnt mit | Ursache | Lösung | | --- | --- | --- | | `Nicht eingeloggt` | Der Header `X-API-KEY` fehlt. | Header mitsenden und Schreibweise prüfen. | | `Ungueltiger oder fehlender API-Key` | Der Schlüssel ist falsch kopiert, unbekannt oder wurde widerrufen. | Schlüssel neu aus dem Secret Store einsetzen. Wurde er widerrufen, einen neuen beantragen. | ## 403: Der Schlüssel ist gültig, aber etwas fehlt | Meldung beginnt mit | Ursache | Lösung | | --- | --- | --- | | `API-Key fehlt Scope: app-tools` | Der Schlüssel wurde für eine andere Anbindung ausgegeben. | Einen App-Tools-Key beantragen, siehe [API-Keys](https://support.unitedsynergy.com/api/api-keys/). | | `API-Key hat keinen Actor-User` | Dem Schlüssel ist kein technischer Benutzer zugeordnet. | Neuen Schlüssel mit Actor-User ausgeben lassen. | | `Actor-User des API-Keys existiert nicht mehr` | Der technische Benutzer wurde gelöscht. | Benutzer neu anlegen und dafür einen neuen Schlüssel ausgeben lassen. | | `Modul … ist nicht aktiv` | Die App ist im Mandanten nicht aktiviert. | App aktivieren lassen oder ein Tool einer aktiven App nutzen. | | `Permission fehlt: …` | Der Rolle des Actor-Users fehlt das genannte Recht, zum Beispiel `update:Konto`. | Das Recht in der Rolle ergänzen, aber nur so weit wie nötig. | ## 400, 404, 422 und 501: Anfrage oder Tool passt nicht | Status und Meldung | Ursache | Lösung | | --- | --- | --- | | `400 Tool-Name fehlt` | Im Body fehlt `name`, oder der Body ist kein gültiges JSON. | JSON-Body mit `name` senden und `Content-Type: application/json` setzen. | | `400` mit anderer Meldung | Die Eingabe verletzt das `inputSchema`. Mehrere Verstöße stehen mit Semikolon getrennt in einer Meldung. | Eingabe nach dem Schema aus dem aktuellen Katalog korrigieren. | | `404 Tool nicht gefunden: …` | Der Tool-Name ist falsch geschrieben oder existiert in dieser Version nicht. | Namen exakt aus dem aktuellen Katalog übernehmen. | | `422` mit `ok: false` | Das Tool lief, konnte die fachliche Aktion aber nicht ausführen, zum Beispiel weil ein Datensatz fehlt. | Zustand mit einem Lese-Tool prüfen, nicht blind wiederholen. | | `422` mit `Datenbankcode …` | Die Datenbank hat die Änderung abgelehnt, etwa `23505` für einen Wert, der eindeutig sein muss und schon existiert, oder `23503` für einen fehlenden verknüpften Datensatz. | Eingabe anhand des Satzes vor dem Code korrigieren. Interna wie Tabellennamen nennt die Antwort bewusst nicht. | | `501 Kein Handler registriert` | Das Tool ist bekannt, aber auf dem Server fehlt die Umsetzung. | Support mit Tool-Name und Zeitpunkt informieren. | ## 429: Zu viele Anfragen | Meldung | Ursache | Lösung | | --- | --- | --- | | `Zu viele Anfragen` | Das Limit für diesen Schlüssel ist im aktuellen Zeitfenster erreicht. | Die Sekunden aus `Retry-After` abwarten, Last über die Zeit verteilen. | Die Limits stehen in der [Referenz unter Anfragelimits](https://support.unitedsynergy.com/api/app-tools/#anfragelimits). ## Der Katalog ist leer oder ein Tool fehlt Ein Tool, das in der [Referenz nach App](https://support.unitedsynergy.com/api/referenz/) steht, fehlt in deinem Katalog, wenn die App im Mandanten nicht aktiv ist oder dem Actor-User das Recht fehlt. Ruf den Katalog mit `includeStructure=1` ab: `structure` zeigt die sichtbaren Apps und die effektiven Rechte des Actor-Users. > **Was der Support braucht** > > Nenne Instanz, Zeitpunkt, Statuscode, Meldung, Tool-Name und das Präfix des Schlüssels. Schick nie den vollständigen API-Key und keine personenbezogenen Antwortdaten. --- # MCP und KI-Assistenten im Überblick > Was MCP ist, welche drei Arbeitsweisen SynCore anbietet und in welcher Reihenfolge du einen Assistenten anschließt. Quelle: https://support.unitedsynergy.com/mcp/uebersicht/ MCP (Model Context Protocol) ist der Standard, über den KI-Assistenten wie Claude, Cursor oder VS Code Werkzeuge nutzen. SynCore bietet seine App-Tools über MCP an: Dein Assistent kann damit Konten suchen, Aufgaben anlegen oder Auswertungen ziehen, mit genau den Rechten des technischen Benutzers hinter dem API-Key. Jeder Aufruf steht im Audit-Log. > **Bevor du beginnst** > > Du brauchst einen API-Key mit dem Scope `app-tools` und einem Actor-User: [API-Keys, Scopes und Berechtigungen](https://support.unitedsynergy.com/api/api-keys/). Nimm für den Assistenten einen eigenen technischen Benutzer mit knappen Rechten, nie dein persönliches Konto. ## Drei Arbeitsweisen - **Klassisch:** Dein Assistent sieht jedes Werkzeug einzeln, bei vollen Rechten über 1.000, und ruft je Schritt eines auf. Jedes Ergebnis landet in seinem Kontext. - **Such-Modus:** Dein Assistent sieht zwei Werkzeuge, eines zum Suchen und eines zum Ausführen. Er findet die passenden Werkzeuge per Suche, ruft sie aber weiter einzeln auf. - **Code-Mode:** Dein Assistent schreibt ein kurzes Programm, das viele Werkzeuge nacheinander aufruft, die Daten filtert und zählt und nur das Ergebnis zurückgibt. Er sieht fünf Werkzeuge: suchen, Programm ausführen, Stand abfragen, Skills lesen und vorschlagen. | Arbeitsweise | Passt, wenn | Einschalten | | --- | --- | --- | | Klassisch | dein Client Werkzeuge selbst sucht (etwa Claude Code) und Aufgaben wenige Schritte haben | Standard | | Such-Modus | dein Client alle Werkzeugbeschreibungen in den Kontext lädt (etwa Claude Desktop, Cursor, VS Code) | `?modus=suche` an der Adresse | | Code-Mode | eine Frage viele Datensätze berührt oder ein Ablauf immer wieder gleich läuft | Schalter **Code-Mode** am API-Key | Der Code-Mode spart am meisten. In unserer Messung mit der Frage „offene und überfällige Aufgaben je Projekt“ über zwölf Projekte brauchte der klassische Weg 13 Aufrufe und brachte rund 414.000 Zeichen in den Kontext des Assistenten. Im Code-Mode war es ein Aufruf mit rund 1.200 Zeichen, bei gleichem Ergebnis. Rechte, Datenbereich und Audit-Log sind in allen drei Arbeitsweisen gleich. Keine Arbeitsweise kann mehr als der Actor-User in der Oberfläche. ## In dieser Reihenfolge vorgehen 1. Technischen Benutzer mit knappen Rechten anlegen und einen API-Key ausgeben lassen: [API-Keys, Scopes und Berechtigungen](https://support.unitedsynergy.com/api/api-keys/) 2. Den Assistenten eintragen: [Assistenten mit SynCore verbinden](https://support.unitedsynergy.com/mcp/verbinden/) 3. Festlegen, welche Werkzeuge er sieht, zum Ausprobieren nur lesende: [Welche Werkzeuge dein Assistent sieht](https://support.unitedsynergy.com/mcp/werkzeuge/) 4. Für viele Schritte auf einmal den Code-Mode nutzen: [So arbeitet der Code-Mode](https://support.unitedsynergy.com/mcp/code-mode/) und [Code-Mode einschalten und absichern](https://support.unitedsynergy.com/mcp/code-mode-einschalten/) Klappt etwas nicht, stehen die häufigsten Meldungen unter [Wenn der Assistent nicht verbindet oder abgewiesen wird](https://support.unitedsynergy.com/mcp/fehlerbehebung/). ## Die Dokumentation für den Assistenten Damit dein Assistent diese Anleitungen kennt, gib ihm die Adresse `https://support.unitedsynergy.com/mcp/llms.txt`. Darin stehen alle Artikel dieser Rubrik als Klartext. Soll er eine eigene Anbindung bauen, nimm `https://support.unitedsynergy.com/api/llms.txt`: Dort stehen zusätzlich die Artikel zur API und die Referenz aller App-Tools. Jede Seite gibt es auch einzeln, wenn du `llms.txt` an ihre Adresse anhängst, zum Beispiel `/mcp/code-mode/llms.txt`. --- # Assistenten mit SynCore verbinden > Claude Code, Cursor, VS Code oder Claude Desktop per MCP mit deiner SynCore-Instanz verbinden. Quelle: https://support.unitedsynergy.com/mcp/verbinden/ Dein Assistent spricht SynCore über eine Adresse und einen API-Key an. Wie du beides einträgst, hängt vom Client ab. > **Bevor du beginnst** > > Du brauchst einen API-Key mit dem Scope `app-tools` und einem Actor-User: [API-Keys, Scopes und Berechtigungen](https://support.unitedsynergy.com/api/api-keys/). Wer den Key in der Admin-Konsole erzeugt, sieht die Adresse der Instanz direkt unter dem Formular. ## Adresse und Schlüssel - **Adresse:** `https:///api/mcp` - **Schlüssel:** im Header `X-API-KEY`. Schreib ihn nie in die Adresse. - **Übertragung:** Streamable HTTP. SynCore antwortet mit JSON und braucht keine Sitzung. - **Protokollversionen:** 2026-07-28 sowie 2025-11-25, 2025-06-18, 2025-03-26 und 2024-11-05. Dein Client wählt selbst. Ob dein Assistent Werkzeuge einzeln aufruft oder Programme schickt, legt der Key fest, nicht die Adresse: [Code-Mode einschalten und absichern](https://support.unitedsynergy.com/mcp/code-mode-einschalten/). ## Claude Code Im Terminal: ```bash claude mcp add --transport http syncore https://deine-instanz.example/api/mcp --header "X-API-KEY: syn_…" ``` Der Schlüssel steht danach in deiner lokalen Claude-Code-Konfiguration. Für ein gemeinsames Projekt legst du stattdessen eine `.mcp.json` an und holst den Schlüssel aus einer Umgebungsvariable: ```json { "mcpServers": { "syncore": { "type": "http", "url": "https://deine-instanz.example/api/mcp", "headers": { "X-API-KEY": "${SYNCORE_API_KEY}" } } } } ``` Nimm einen eigenen Variablennamen wie `SYNCORE_API_KEY`. Ist die Variable nicht gesetzt, schickt Claude Code den Platzhalter unverändert und SynCore antwortet mit `401`. ## Cursor In `~/.cursor/mcp.json` (für dich) oder `.cursor/mcp.json` (im Projekt): ```json { "mcpServers": { "syncore": { "url": "https://deine-instanz.example/api/mcp", "headers": { "X-API-KEY": "${env:SYNCORE_API_KEY}" } } } } ``` ## VS Code In `.vscode/mcp.json`. VS Code fragt beim ersten Start nach dem Schlüssel und speichert ihn geschützt: ```json { "inputs": [ { "type": "promptString", "id": "syncore-key", "description": "SynCore API-Key", "password": true } ], "servers": { "syncore": { "type": "http", "url": "https://deine-instanz.example/api/mcp", "headers": { "X-API-KEY": "${input:syncore-key}" } } } } ``` ## Claude Desktop Claude Desktop verbindet sich über das Hilfsprogramm `mcp-remote` (braucht Node.js 18 oder neuer). Trag in `claude_desktop_config.json` ein: ```json { "mcpServers": { "syncore": { "command": "npx", "args": ["mcp-remote", "https://deine-instanz.example/api/mcp", "--header", "X-API-KEY:${SYNCORE_API_KEY}"], "env": { "SYNCORE_API_KEY": "syn_…" } } } } ``` Schreib nach `X-API-KEY:` kein Leerzeichen, unter Windows bricht der Aufruf sonst ab. Der Schlüssel steht in dieser Datei im Klartext, schütz sie wie ein Passwort. > **Connectoren in claude.ai und ChatGPT** > > Die Connector-Einrichtung in claude.ai und in ChatGPT verlangt eine Anmeldung per OAuth. Die bietet SynCore noch nicht an. Einzelne Organisationen können in claude.ai bereits eigene Request-Header eintragen (Beta), dann funktioniert es dort mit `X-API-KEY`. Für alle anderen gelten vorerst die Wege oben. ## Sicherheit - Es gelten dieselben Prüfungen wie bei der [App-Tools-API](https://support.unitedsynergy.com/api/app-tools/): Schlüssel, Scope, Actor-User, Rechte, Datenbereich, Eingabeschema und Audit-Log. Details stehen unter [Sicherheit der API](https://support.unitedsynergy.com/api/sicherheit/). - SynCore nimmt den Schlüssel nur im Header `X-API-KEY` an, keine Anmeldung aus dem Browser und kein Cookie. - Anfragen aus fremden Webseiten (Header `Origin`) lehnt SynCore mit `403` ab. - Zum Ausprobieren eignet sich `?nur=lesen` an der Adresse. So kann der Assistent nichts verändern, auch wenn der Actor-User es dürfte. > **Ergebnis** > > Dein Assistent zeigt SynCore mit seinen Werkzeugen an. Frag ihn zum Beispiel nach den zuletzt angelegten Konten. Der Aufruf steht danach im Audit-Log, als Quelle ist „mcp“ vermerkt. --- # Welche Werkzeuge dein Assistent sieht > Wie Rechte und Parameter an der Adresse bestimmen, welche SynCore-Werkzeuge dein Assistent sieht, und wann der Such-Modus hilft. Quelle: https://support.unitedsynergy.com/mcp/werkzeuge/ Dein Assistent sieht nie mehr als der Actor-User hinter dem API-Key. Mit Parametern an der Adresse engst du die Auswahl zusätzlich ein. Weniger Werkzeuge helfen dem Assistenten, manche Clients arbeiten nur mit einer begrenzten Zahl zuverlässig. ## Was die Rechte festlegen - Die Namen entsprechen der [Referenz nach App](https://support.unitedsynergy.com/api/referenz/), nur mit Unterstrich statt Punkt: aus `crm.konto.list` wird `crm_konto_list`. - Dein Assistent sieht nur Werkzeuge der aktivierten Apps, für die der Actor-User Rechte hat. Werkzeuge für Daten der Datenklasse D fehlen. - Werkzeuge, die Daten anlegen, ändern oder löschen, sind entsprechend gekennzeichnet. Clients wie Claude Code fragen vor solchen Aufrufen nach, solange du sie nicht dauerhaft freigibst. - Werkzeuge, die löschen, gibt es über den Key nur, wenn an ihm **Löschen erlaubt** an ist: [Code-Mode einschalten und absichern](https://support.unitedsynergy.com/mcp/code-mode-einschalten/). ## Auswahl an der Adresse einengen | Parameter | Wirkung | Beispiel | | --- | --- | --- | | `apps` | nur die Werkzeuge dieser Apps (App-Kennungen aus der Referenz) | `?apps=crm,auftraege` | | `nur=lesen` | nur Werkzeuge, die nichts verändern | `?nur=lesen` | | `wertelisten` | Wertelisten: `aus`, `lesen` (Standard) oder `alle` | `?wertelisten=alle` | | `modus=suche` | dein Assistent sieht nur zwei Werkzeuge: `search_tools` zum Suchen und `call_tool` zum Ausführen | `?modus=suche` | Die Parameter lassen sich kombinieren, zum Beispiel `https://deine-instanz.example/api/mcp?apps=crm&nur=lesen`. Sie können die Rechte nur einschränken, nie erweitern: Was der Actor-User nicht darf, bleibt gesperrt. Bei einem Key im Code-Mode gelten `apps` und `nur=lesen` genauso, `modus=suche` hat dort keine Wirkung. ## Viele Werkzeuge: der Such-Modus Ohne Einschränkung zeigt SynCore deinem Assistenten jedes Werkzeug einzeln, bei vollen Rechten über 1.000. Clients ohne eigene Werkzeugsuche (etwa Claude Desktop, Cursor, VS Code) laden dann alle Beschreibungen in ihren Kontext, das sind rund 90.000 Token, bevor du die erste Frage stellst. Mit `?modus=suche` sieht dein Assistent stattdessen nur zwei Werkzeuge, zusammen rund 450 Token: 1. `search_tools` sucht Werkzeuge nach Begriffen, zum Beispiel „konto list“ oder „aufgabe anlegen“, auf Wunsch nur in einer App. Mit `stufe` bestimmt der Assistent, wie viel er je Treffer bekommt: nur den Namen, die Beschreibung (Standard), das Eingabeschema oder eine TypeScript-Deklaration. 2. `call_tool` führt ein gefundenes Werkzeug aus, mit dem Namen aus der Suche und den Eingaben nach dessen Schema. Die übrigen Parameter gelten auch im Such-Modus. `?modus=suche&nur=lesen` findet und startet also nur lesende Werkzeuge. Rechte, Datenbereich und Audit-Log bleiben dieselben wie beim Einzelaufruf. > **Ergebnis** > > Der Such-Modus spart Kontext, aber jeder Schritt bleibt ein eigener Aufruf. Berührt eine Frage viele Datensätze, ist der [Code-Mode](https://support.unitedsynergy.com/mcp/code-mode/) sparsamer. --- # So arbeitet der Code-Mode > Wie dein Assistent im Code-Mode Programme schreibt, welche Werkzeuge und Grenzen es gibt und wie er Skills nutzt. Quelle: https://support.unitedsynergy.com/mcp/code-mode/ Im Code-Mode ruft dein Assistent die Werkzeuge nicht einzeln auf. Er schreibt ein kurzes Programm in TypeScript, das die Werkzeuge nacheinander aufruft, die Daten filtert und zählt und nur das Ergebnis zurückgibt. Die Zwischenstände landen nicht in seinem Kontext. Das spart viele Token, wenn eine Frage Dutzende Datensätze berührt. > **Bevor du beginnst** > > Der API-Key muss im Code-Mode stehen, die Code-Ausführung muss auf deiner Instanz eingerichtet sein, und der Actor-User braucht das Recht „Programme über einen API-Schlüssel ausführen“. Wie du das einrichtest: [Code-Mode einschalten und absichern](https://support.unitedsynergy.com/mcp/code-mode-einschalten/). ## Die fünf Werkzeuge Ein Key im Code-Mode zeigt dem Assistenten nur diese Werkzeuge: - `search_tools` sucht Werkzeuge nach Begriffen, auf Wunsch nur in einer App. Mit `stufe` „typescript“ bekommt der Assistent die Deklaration als `syncore..(input)`. - `code_ausfuehren` führt ein Programm aus (`programm` und `werkzeuge`) oder startet einen Skill (`skill` und `eingabe`). - `lauf_status` zeigt den Stand eines Laufs: läuft, fertig mit Ergebnis, abgebrochen, oder mit Freigabe am Key: wartet, abgelehnt, verfallen. - `skills_lesen` zeigt die Skills, die die Verbindung starten kann, je App eine Übersicht oder einen Skill im Ganzen. - `skill_vorschlagen` schlägt das Programm eines fertigen Laufs als Skill vor. Mit `?nur=lesen` fehlt dieses Werkzeug. ## So läuft ein Programm ab 1. Der Assistent sucht mit `search_tools` die passenden Werkzeuge, zum Beispiel „projekt list“ und „ticket list“, mit `stufe` „typescript“. 2. Er schreibt den Rumpf einer async-Funktion und schickt ihn mit `code_ausfuehren`. In `werkzeuge` nennt er die Namen aus der Suche mit Punkt (`projektsyn.projekt.list`), im Programm ruft er sie mit Unterstrich auf (`syncore.projektsyn.projekt_list`). 3. SynCore startet das Programm in einer eigenen Sandbox. Jeder Werkzeugaufruf kommt zurück zu SynCore und läuft dort mit den Rechten des Actor-Users, wie ein Einzelaufruf. 4. Mit `return` gibt das Programm das Ergebnis zurück. Die Antwort nennt den Lauf (`prl_…`), den Stand liefert bei Bedarf `lauf_status`. So sieht ein Programm aus, das offene Aufgaben je Projekt zählt: ```ts const projekte = await syncore.projektsyn.projekt_list({ limit: 50 }); const ergebnis = []; for (const p of projekte.data) { const aufgaben = await syncore.projektsyn.ticket_list({ filters: { projektId: p.id }, limit: 200 }); ergebnis.push({ projekt: p.name, aufgaben: aufgaben.data.length }); } return ergebnis; ``` Dazu `werkzeuge: ["projektsyn.projekt.list", "projektsyn.ticket.list"]`. Zurück kommt nur die kurze Liste, nicht die einzelnen Aufgaben. ## Was ein Programm darf - **Nur die genannten Werkzeuge.** Ein Werkzeug, das nicht in `werkzeuge` steht, gibt es im Programm nicht. - **Kein Netz, keine Dateien.** Bereit stehen nur `syncore` und `console`. - **Rechte wie der klassische Weg.** Lesen, Anlegen und Ändern laufen sofort, Löschen nur, wenn am Key **Löschen erlaubt** an ist. Ist am Key unter **Programme freigeben** eine Person eingetragen, laufen Schreibaufrufe zuerst als Vorschau und erst nach ihrer Freigabe: [Programme von Agenten freigeben](https://support.unitedsynergy.com/workflows/programme/). - **Jeder Aufruf im Audit-Log.** Als Quelle ist „code“ vermerkt, dazu der Lauf. Die Läufe selbst stehen in der App **Automationen** auf der Seite **Programme**. ## Grenzen | Grenze | Wert | | --- | --- | | Laufzeit je Programm | 60 Sekunden | | Rechenzeit je Programm (Warten auf Werkzeuge zählt nicht) | 15 Sekunden | | Werkzeugaufrufe je Programm | 200 | | Werkzeuge je Programm | 50 | | Länge des Programms | 100.000 Zeichen | | Ergebnis an den Assistenten | gekürzt auf rund 6.000 Token | | Listen je Aufruf | höchstens 200 Einträge, danach mit `offset` weiterblättern | | Gleichzeitige Läufe | 2 je Mandant | | Offene Läufe | 20 je Mandant, 5 je Key | Ein Programm, das eine Grenze überschreitet, bricht ab. Der Lauf steht dann auf **Abgebrochen** mit dem Grund. ## Skills: bewährte Programme wiederverwenden Ein **Skill** ist ein Programm mit Beschreibung und Eingabe, das dein Assistent starten kann, statt es neu zu schreiben. Vier liefert SynCore mit: **Aufgaben anlegen und Zeiten buchen**, **Rechnung aus Zeiten**, **Berichte ziehen** und **CRM-Import mit Abgleich**. 1. `skills_lesen` ohne Angabe zeigt alle Skills, die die Verbindung starten kann. Mit `{ "app": "crm" }` kommt die Übersicht einer App (Werkzeuge, Lesen und Schreiben, typische Abläufe), mit `{ "skill": "crm_import_abgleich" }` ein Skill mit Eingabe-Schema und Programm. 2. Gestartet wird ein Skill mit `code_ausfuehren { "skill": "…", "eingabe": { … } }`. Die Eingabe prüft SynCore gegen das Schema des Skills. 3. Lief ein eigenes Programm gut, schlägt der Assistent es mit `skill_vorschlagen` als Skill vor. Gespeichert wird nur ein Vorschlag; übernehmen kann ihn nur ein Mensch: [Skills übernehmen](https://support.unitedsynergy.com/workflows/programme/). > **Ergebnis** > > Ein Skill schreibt wie jedes Programm: sofort mit den Rechten des Actor-Users oder, wenn am Key eine Person eingetragen ist, erst nach ihrer Freigabe. --- # Code-Mode einschalten und absichern > Code-Mode, Freigabe und Löschen am API-Key einstellen und die Rechte für Programme vergeben. Quelle: https://support.unitedsynergy.com/mcp/code-mode-einschalten/ Ob ein Assistent Programme schickt oder Werkzeuge einzeln aufruft, entscheidet sein API-Key. Ab Werk ist jeder Key klassisch. Den Code-Mode schaltet ein Plattform-Admin je Key ein, zusammen mit zwei Schaltern, die festlegen, wie weit der Assistent schreiben darf. > **Bevor du beginnst** > > Die Code-Ausführung muss auf deiner Instanz eingerichtet sein. Ist sie es nicht, richtet United Synergy sie zuerst auf dem Server ein. Code-Mode, Freigabe und Löschen gibt es nur bei Keys, die als Benutzer handeln (Actor-User). ## Code-Mode am Key einschalten 1. Öffne **Admin-Konsole › Zugriff › API Keys** und wähle über der Tabelle den Mandanten. 2. Klicke auf die Zeile des Keys (oder **⋯** und **Bearbeiten**). Der Dialog **Key bearbeiten** öffnet sich. Beim Erzeugen eines neuen Keys über **Key erzeugen** stehen dieselben Schalter gleich im Formular. 3. Schalte **Code-Mode** ein. 4. Wähle bei **Programme freigeben**, ob Programme sofort schreiben (**Niemand, Programme schreiben sofort**) oder ob eine Person jeden Schreibaufruf vorher freigibt. 5. Lass **Löschen erlaubt** aus, wenn der Assistent nichts löschen soll. Schaltest du es ein, legst du die **Grenze je Stunde** fest. 6. Klicke **Speichern**. > **Ergebnis** > > Die Änderung gilt sofort und steht im Protokoll mit den geänderten Feldern. Schaltest du den Code-Mode aus, bricht auch ein laufendes Programm beim nächsten Werkzeugaufruf ab. ## Was die Schalter bewirken | Schalter | Aus | An | | --- | --- | --- | | **Code-Mode** | klassischer MCP, jedes Werkzeug einzeln; Programme starten nicht | nur Programme in der Sandbox; einzelne Aufrufe über MCP und `/api/app-tools` weist SynCore ab | | **Programme freigeben** | **Niemand**: Programme lesen, legen an und ändern sofort | eine Person: Schreibaufrufe laufen erst als Vorschau, nur diese Person bekommt eine Aufgabe und gibt frei oder lehnt ab | | **Löschen erlaubt** | Werkzeuge, die löschen, sind über den Key nicht nutzbar, weder einzeln noch in Programmen | löschen erlaubt, soweit die Rollen des Actor-Users es erlauben, bis zur **Grenze je Stunde** | Liegt der Key über der Grenze je Stunde, sperrt SynCore das Löschen über diesen Key, bis ein Plattform-Admin es mit **⋯** und **Löschen freigeben** wieder freigibt. Dazu kommt ein Alarm. Der Actor-User des Keys kann seine eigenen Programme nie freigeben. Wie die Freigabe im Alltag abläuft: [Programme von Agenten freigeben](https://support.unitedsynergy.com/workflows/programme/). ## Rechte für Programme Unter **Admin › Berechtigungen** in der App **Automationen**: | Recht | Wer es braucht | | --- | --- | | Programme über einen API-Schlüssel ausführen | die Rolle des Actor-Users, sonst startet kein Programm | | Schreibaufrufe eines Programms freigeben oder ablehnen | die Person, die am Key unter **Programme freigeben** steht | | Seite Programme sehen, dazu Datenobjekt **Programm** lesen | alle, die Läufe ansehen sollen | Ab Werk hat nur die Admin-Rolle des Mandanten diese Rechte. Gib das Recht zum Ausführen nur technischen Benutzern mit eng geschnittener Rolle. Ist die App **Automationen** im Mandanten nicht aktiv, starten keine Programme, auch wenn Key und Rechte stimmen. ## So sicherst du den Assistenten ab - **Eigener technischer Benutzer** je Assistent, mit einer Rolle, die nur die nötigen Apps und Datenbereiche enthält. - **Zum Ausprobieren** `?nur=lesen` an die Adresse hängen. Dann laufen auch im Code-Mode nur lesende Werkzeuge. - **Mit Freigabe**, wenn der Assistent fremde Inhalte liest, etwa Mails oder Dokumente, und ein Mensch jeden Schreibvorgang sehen soll. - **Löschen aus**, solange du keinen Grund hast, es einzuschalten. - **Ablaufdatum** am Key setzen und den Key über **⋯** und **Rotieren** erneuern, wenn er in falsche Hände geraten sein könnte: [API-Keys, Scopes und Berechtigungen](https://support.unitedsynergy.com/api/api-keys/). > **Wenn es nicht klappt** > > Mit Code-Mode funktionieren Befehle und Anleitungen deines Assistenten nicht mehr, die SynCore-Werkzeuge einzeln aufrufen. Brauchst du beides, gib dem Assistenten zwei Keys: einen klassischen und einen im Code-Mode. --- # Wenn der Assistent nicht verbindet oder abgewiesen wird > Die häufigsten Meldungen bei MCP und im Code-Mode, ihre Ursache und was du tust. Quelle: https://support.unitedsynergy.com/mcp/fehlerbehebung/ Die meisten Fehler liegen am Key, an der Adresse oder an den Rechten des Actor-Users. Die Meldung sagt meist schon, was fehlt. ## Verbindung und Key | Antwort | Ursache | Lösung | | --- | --- | --- | | `401` mit `API-Key fehlt` | Der Header `X-API-KEY` kommt nicht an. | Konfiguration prüfen, bei Umgebungsvariablen: ist sie gesetzt? | | `401` mit `Ungueltiger oder fehlender API-Key` | Schlüssel falsch, gekürzt oder widerrufen, oder der Mandant ist nicht mehr aktiv. | Schlüssel neu eintragen oder einen neuen ausgeben lassen. | | `401` mit `API-Schlüssel abgelaufen` | Das Ablaufdatum ist erreicht, oder nach einer Rotation ist die Übergangsfrist des alten Schlüssels vorbei. | Den neuen Schlüssel eintragen oder einen neuen ausgeben lassen. | | `403` mit `API-Key fehlt Scope: app-tools` | Der Schlüssel ist für eine Spezialanbindung ausgestellt. | Einen App-Tools-Schlüssel verwenden. | | `403` mit `API-Key hat keinen Actor-User` | Dem Schlüssel fehlt der technische Benutzer. | Schlüssel mit Actor-User ausgeben lassen. | | `405` | Der Client ruft die Adresse per GET auf. | Im Client die Übertragung „Streamable HTTP“ bzw. `http` wählen. | ## Werkzeuge | Antwort | Ursache | Lösung | | --- | --- | --- | | `Unbekanntes Tool` | Name mit Punkt, Filter an der Adresse oder fehlende Rechte. | Namen aus der Tool-Liste des Clients nehmen, Filter und Rechte prüfen. | | `Unbekanntes Tool … nur search_tools und call_tool` | Die Adresse enthält `modus=suche`. | Werkzeuge über `call_tool` aufrufen oder `modus=suche` aus der Adresse nehmen. | | Ergebnis beginnt mit `Fehler:` | Eingabe, Rechte oder fachlicher Zustand passen nicht. | Die Meldung sagt, was fehlt. Der Assistent kann die Eingabe damit meist selbst korrigieren. | ## Code-Mode | Antwort | Ursache | Lösung | | --- | --- | --- | | `403` mit `Dieser API-Schlüssel ist im Code-Mode: Werkzeuge nur über Programme` | Der Key steht im Code-Mode und ruft ein Werkzeug einzeln auf. | Programme über `code_ausfuehren` schicken oder einen klassischen Key verwenden. | | `Code-Mode ist an diesem API-Schlüssel ausgeschaltet` | Der Key ist klassisch (ab Werk) oder wurde während eines Laufs umgestellt. | Ein Plattform-Admin schaltet **Code-Mode** ein: [Code-Mode einschalten und absichern](https://support.unitedsynergy.com/mcp/code-mode-einschalten/). | | `Die Code-Ausführung ist auf dieser Instanz nicht eingeschaltet` | Auf dem Server deiner Instanz fehlt die Sandbox für Programme. | Bei deinem Ansprechpartner von United Synergy nachfragen. | | `Dem Benutzer des Schlüssels fehlt das Recht „Programme ausführen“` | Die Rolle des Actor-Users darf keine Programme starten. | Unter **Admin › Berechtigungen** der Rolle in der App **Automationen** „Programme über einen API-Schlüssel ausführen“ geben. | | `Die App Automationen ist in diesem Mandanten nicht aktiv` | Programme laufen über die App Automationen. | Die App im Mandanten einschalten lassen. | | `Fehler: Unbekannte Werkzeuge …` | Das Programm nennt in `werkzeuge` einen Namen, den der Key nicht erreicht. | Mit `search_tools` nach dem richtigen Namen suchen, Rechte und Filter an der Adresse prüfen. | | `Cannot read properties of undefined` im Programm | Das Werkzeug wird im Programm mit Punkt statt Unterstrich aufgerufen. | Im Programm `syncore.crm.konto_list(…)`, in `werkzeuge` dagegen `crm.konto.list`. | | Lauf **Abgebrochen** mit Grund `cpu`, `zeit` oder `aufrufe` | Das Programm rechnet zu lange, läuft länger als 60 Sekunden oder ruft mehr als 200 Werkzeuge auf. | Weniger Schleifen, Arbeit auf mehrere Läufe verteilen. Grenzen: [So arbeitet der Code-Mode](https://support.unitedsynergy.com/mcp/code-mode/). | | Lauf **Wartet auf Freigabe** | Am Key ist unter **Programme freigeben** eine Person eingetragen. | Die Person gibt frei: [Programme von Agenten freigeben](https://support.unitedsynergy.com/workflows/programme/). | > **Bevor du beginnst** > > Wer einen eigenen MCP-Client baut: Bei moderner Protokollversion müssen die Header `MCP-Protocol-Version`, `Mcp-Method` und bei `tools/call` `Mcp-Name` zum Inhalt passen, sonst kommt `400` mit Code `-32020`. Eine nicht unterstützte Version beantwortet SynCore mit `400`, Code `-32022` und der Liste der unterstützten Versionen. --- # API-Referenz Arbeitszeit (App-Kennung arbeitszeit) > 30 App-Tools. Aufruf immer mit `POST /api/app-tools`, Header `X-API-KEY`, Body `{"name": "", "input": {…}}`. Welche Tools ein Schlüssel nutzen darf, zeigt `GET /api/app-tools` der Instanz. Quelle: https://support.unitedsynergy.com/api/referenz/arbeitszeit/ ## Datenobjekte Die Standard-Aktionen je Datenobjekt: list (suchen und blättern), get (einen Datensatz lesen), create, update und delete. Nicht jedes Objekt bietet alle fünf an. ### Schichtplan: `arbeitszeit.schicht.*` #### arbeitszeit.schicht.list Liste/Suche: Schichtplan - Art: Lesen - Rechte: Arbeitszeit lesen - Datenklassen: C (vertraulich) - Eingabe: - `search` (string): Freitextsuche - `filters` (object): Feld=Wert-Filter - `limit` (integer) - `offset` (integer) - `orderBy` (string) - Beispiel: `{"name":"arbeitszeit.schicht.list","input":{}}` #### arbeitszeit.schicht.get Detail: Schichtplan - Art: Lesen - Rechte: Arbeitszeit lesen - Datenklassen: C (vertraulich) - Eingabe: - `id` (string, Pflicht) - Beispiel: `{"name":"arbeitszeit.schicht.get","input":{"id":""}}` #### arbeitszeit.schicht.create Anlegen: Schichtplan - Art: Anlegen, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Arbeitszeit anlegen - Datenklassen: C (vertraulich) - Eingabe: - `schichtartCode` (string) - `von` (string, Pflicht) - `bis` (string, Pflicht) - `bezeichnung` (string) - `bemerkung` (string) - `standortId` (string) - `kostenstelleId` (string) - Beispiel: `{"name":"arbeitszeit.schicht.create","input":{"von":"","bis":""}}` #### arbeitszeit.schicht.update Ändern: Schichtplan - Art: Ändern, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Arbeitszeit ändern - Datenklassen: C (vertraulich) - Eingabe: - `id` (string, Pflicht): ID des Datensatzes - `schichtartCode` (string) - `von` (string) - `bis` (string) - `bezeichnung` (string) - `bemerkung` (string) - `standortId` (string) - `kostenstelleId` (string) - Beispiel: `{"name":"arbeitszeit.schicht.update","input":{"id":""}}` #### arbeitszeit.schicht.delete Löschen: Schichtplan - Art: Löschen, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Arbeitszeit löschen - Datenklassen: C (vertraulich) - Eingabe: - `id` (string, Pflicht) - Beispiel: `{"name":"arbeitszeit.schicht.delete","input":{"id":""}}` ### Zeiterfassung: `arbeitszeit.eintrag.*` #### arbeitszeit.eintrag.list Liste/Suche: Zeiterfassung - Art: Lesen - Rechte: Arbeitszeit lesen - Datenklassen: C (vertraulich) - Eingabe: - `search` (string): Freitextsuche - `filters` (object): Feld=Wert-Filter - `limit` (integer) - `offset` (integer) - `orderBy` (string) - Beispiel: `{"name":"arbeitszeit.eintrag.list","input":{}}` #### arbeitszeit.eintrag.get Detail: Zeiterfassung - Art: Lesen - Rechte: Arbeitszeit lesen - Datenklassen: C (vertraulich) - Eingabe: - `id` (string, Pflicht) - Beispiel: `{"name":"arbeitszeit.eintrag.get","input":{"id":""}}` #### arbeitszeit.eintrag.create Anlegen: Zeiterfassung - Art: Anlegen, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Arbeitszeit anlegen - Datenklassen: C (vertraulich) - Eingabe: - `personId` (string, Pflicht) - `datum` (string, Pflicht) - `beginn` (string) - `ende` (string) - `pauseMinuten` (number) - `statusCode` (string) - `bereichCode` (string) - `kommentar` (string) - Beispiel: `{"name":"arbeitszeit.eintrag.create","input":{"personId":"","datum":""}}` #### arbeitszeit.eintrag.update Ändern: Zeiterfassung - Art: Ändern, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Arbeitszeit ändern - Datenklassen: C (vertraulich) - Eingabe: - `id` (string, Pflicht): ID des Datensatzes - `personId` (string) - `datum` (string) - `beginn` (string) - `ende` (string) - `pauseMinuten` (number) - `statusCode` (string) - `bereichCode` (string) - `kommentar` (string) - Beispiel: `{"name":"arbeitszeit.eintrag.update","input":{"id":""}}` #### arbeitszeit.eintrag.delete Löschen: Zeiterfassung - Art: Löschen, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Arbeitszeit löschen - Datenklassen: C (vertraulich) - Eingabe: - `id` (string, Pflicht) - Beispiel: `{"name":"arbeitszeit.eintrag.delete","input":{"id":""}}` ## Wertelisten Auswahllisten der App wie Status, Arten oder Kategorien. Du pflegst sie mit denselben fünf Aktionen. Die Werte (code) nutzt du in den Feldern der Datenobjekte. ### Arbeitsbereiche: `arbeitszeit.bereich.*` #### arbeitszeit.bereich.list Liste/Suche: Katalog „Arbeitsbereiche" (arbeitszeit) - Art: Lesen - Rechte: Einstellungen verwalten - Datenklassen: B (intern) - Eingabe: - `onlyAktiv` (boolean): Nur aktive Einträge - Beispiel: `{"name":"arbeitszeit.bereich.list","input":{}}` #### arbeitszeit.bereich.get Detail: Katalog „Arbeitsbereiche" (arbeitszeit) - Art: Lesen - Rechte: Einstellungen verwalten - Datenklassen: B (intern) - Eingabe: - `id` (string, Pflicht) - Beispiel: `{"name":"arbeitszeit.bereich.get","input":{"id":""}}` #### arbeitszeit.bereich.create Anlegen: Katalog „Arbeitsbereiche" (arbeitszeit) - Art: Anlegen, vor dem Ausführen ausdrücklich bestätigen lassen - Rechte: Einstellungen verwalten - Datenklassen: B (intern) - Eingabe: - `label` (string, Pflicht): Anzeige-Text - `code` (string): Optional, sonst aus label abgeleitet. Immutable - `color` (string): Tailwind-Paar, z.B. "bg-blue-100 text-blue-700" - `icon` (string): Lucide-Icon-Name - `beschreibung` (string) - Beispiel: `{"name":"arbeitszeit.bereich.create","input":{"label":"