{
  "openapi": "3.1.0",
  "info": {
    "title": "SynCore App-Tools API",
    "version": "1.1.0",
    "description": "Berechtigungsgefilterter App-Tool-Katalog und zentraler Ausführungspunkt für SynCore-Integrationen. Die fachlichen Tools und deren Schemas werden dynamisch über GET /api/app-tools bereitgestellt."
  },
  "servers": [
    {
      "url": "{baseUrl}",
      "description": "SynCore-Instanz",
      "variables": {
        "baseUrl": {
          "default": "https://syncore.example.com",
          "description": "HTTPS-Basis-URL der Zielinstanz ohne abschließenden Schrägstrich"
        }
      }
    }
  ],
  "tags": [
    {
      "name": "App Tools",
      "description": "Katalog und Ausführung der für den Actor-User erlaubten SynCore-Tools"
    }
  ],
  "paths": {
    "/api/app-tools": {
      "get": {
        "tags": [
          "App Tools"
        ],
        "operationId": "listAppTools",
        "summary": "Erlaubte App-Tools auflisten",
        "description": "Liefert ausschließlich Tools, Apps und Berechtigungen, die für Mandant und Actor-User des API-Keys sichtbar sind.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "includeStructure",
            "in": "query",
            "required": false,
            "description": "Bei 1, true oder yes zusätzlich App-Struktur, effektive Berechtigungen und Laufzeitregeln liefern.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Berechtigungsgefilterter Tool-Katalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolCatalog"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "tags": [
          "App Tools"
        ],
        "operationId": "executeAppTool",
        "summary": "Ein App-Tool ausführen",
        "description": "Validiert Tool-Name, Eingabeschema, App-Aktivierung, Berechtigungen und Datenscope und führt anschließend genau ein Tool aus.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolExecutionRequest"
              },
              "examples": {
                "readOnlyTool": {
                  "summary": "Lesendes Beispiel",
                  "value": {
                    "name": "textbausteine.list_templates",
                    "input": {
                      "limit": 10
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool erfolgreich ausgeführt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolExecutionResult"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "Fachliche Ausführung fehlgeschlagen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolExecutionError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/ServerConfigurationError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY",
        "description": "API-Key mit Scope app-tools und einem Actor-User. Der Key handelt mit den Rollen und Datenscopes dieses Benutzers."
      }
    },
    "schemas": {
      "JsonSchema": {
        "type": "object",
        "description": "JSON-Schema des jeweiligen dynamischen Tools",
        "additionalProperties": true
      },
      "ToolRequirement": {
        "type": "object",
        "properties": {
          "module": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "permissionKey": {
            "type": "string"
          }
        },
        "required": [
          "action",
          "subject"
        ],
        "additionalProperties": true
      },
      "ToolDefinition": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "appId": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "inputSchema": {
            "$ref": "#/components/schemas/JsonSchema"
          },
          "outputSchema": {
            "$ref": "#/components/schemas/JsonSchema"
          },
          "requires": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolRequirement"
            }
          },
          "dataClasses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sideEffect": {
            "type": "string"
          },
          "confirmationRequired": {
            "type": "boolean"
          },
          "dsgvoNote": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "module",
          "appId",
          "label",
          "description",
          "inputSchema",
          "requires",
          "dataClasses",
          "sideEffect",
          "confirmationRequired",
          "dsgvoNote"
        ],
        "additionalProperties": true
      },
      "ToolCatalog": {
        "type": "object",
        "properties": {
          "tools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolDefinition"
            }
          },
          "structure": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "rules": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "tools"
        ],
        "additionalProperties": false
      },
      "ToolExecutionRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Exakter Name aus dem aktuellen Tool-Katalog"
          },
          "input": {
            "type": "object",
            "description": "Eingabe gemäß inputSchema des gewählten Tools",
            "additionalProperties": true
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      },
      "ToolExecutionResult": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "tool": {
            "type": "string"
          },
          "module": {
            "type": "string"
          },
          "data": {},
          "summary": {
            "type": "string"
          },
          "entityType": {
            "type": "string"
          },
          "entityId": {
            "type": "string"
          },
          "needsSelection": {
            "type": "boolean"
          },
          "candidates": {
            "type": "array",
            "items": {}
          }
        },
        "required": [
          "ok",
          "tool",
          "module"
        ],
        "additionalProperties": true
      },
      "ToolExecutionError": {
        "type": "object",
        "properties": {
          "ok": {
            "const": false
          },
          "tool": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "tool",
          "error"
        ],
        "additionalProperties": false
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Fehlerantwort der Plattform bei 400, 401, 403, 404 und 501. Die lesbare Ursache steht in message.",
        "properties": {
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Fehlender Tool-Name, ungültiges JSON oder Eingabeschema verletzt",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "API-Key fehlt, ist ungültig oder wurde gesperrt",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Scope, Actor-User, App-Aktivierung oder fachliche Berechtigung fehlt",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Tool-Name nicht gefunden",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServerConfigurationError": {
        "description": "Registriertes Tool besitzt keinen ausführbaren Handler",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Anfragelimit erreicht: zu viele Anfragen mit diesem API-Key im aktuellen Zeitfenster. Die Antwort ist Klartext.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          }
        },
        "content": {
          "text/plain": {
            "schema": {
              "type": "string",
              "examples": [
                "Zu viele Anfragen",
                "Zu viele ungültige API-Schlüssel"
              ]
            }
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Anfragen je API-Key, Methode und Endpunkt im Zeitfenster von einer Minute (Standard 1200, je Instanz einstellbar).",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Verbleibende Anfragen im aktuellen Zeitfenster.",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Wartezeit in Sekunden, bevor eine neue Anfrage sinnvoll ist.",
        "schema": {
          "type": "integer"
        }
      }
    }
  }
}
