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.
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. 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:
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 | 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:
declare const syncore: {
crm: {
/** Liste/Suche: Konten (CRM) … */
konto_list(input: CrmKontoListInput): Promise<SynCoreErgebnis<unknown>>;
};
};
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. |
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. 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
{
"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
{
"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:
{
"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
- Katalog und Struktur abrufen.
- Zielentität über ein Lese- oder Such-Tool eindeutig bestimmen.
- Eingabe gegen
inputSchemaaufbauen. - Bei
confirmationRequired: truedie konkrete Aktion bestätigen lassen. - Mutation ausführen.
- 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.
{
"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.listreicht 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.
files.upload_linkmit Name, Typ und Datensatz aufrufen. Die Antwort enthälturl,expiresAtundbefehle.bashbeziehungsweisebefehle.powershell.- Den Befehl im Ordner der Datei ausführen, zum Beispiel:
curl -sS -f -T "foto.png" -H "Content-Type: image/png" "https://deine-instanz/api/files/direkt/<token>"
- Die Antwort des PUT ist die angelegte Datei (
id,url). Mitfiles.listprü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" "<url>". 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-Typeim Befehl muss zum angemeldeten Typ passen, sonst antwortet der Server mit415. OhneContent-Typegilt 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/<token>), 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/<token>). |
415 | Der Content-Type des PUT passt nicht zum angemeldeten Typ (/api/files/direkt/<token>). |
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:
{
"message": "Tool nicht gefunden: crm.konto_lsit"
}
Bei einem fachlichen Fehler liefert 422 stattdessen ok, tool und error:
{
"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.
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.
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 und in Postman, Bruno oder Insomnia importieren. Da die verfügbaren Tools dynamisch sind, ersetzt die OpenAPI-Datei nicht den Katalogabruf.