{
  "openapi": "3.1.0",
  "info": {
    "title": "NexAI Portal – Kunden-Schnittstelle",
    "version": "1.0.0",
    "description": "Offene Schnittstelle, über die Kunden von NexAI ihre Daten maschinell abrufen (Datenverordnung (EU) 2023/2854, Art. 30 Abs. 2). Kostenlos, für jeden Kunden gleich, ohne Freischaltung. Anmeldung mit der Portal-Sitzung eines Kundenkontos oder mit einem Kundenschlüssel, den der Kunde im Portal unter „Datenexport“ erzeugt. Fehler werden als application/problem+json (RFC 9457) mit einem festen Feld `code` beantwortet.",
    "contact": { "name": "NexAI", "url": "https://nexaisoftware.de" }
  },
  "servers": [{ "url": "https://nexaiapp.de" }],
  "security": [{ "kundenSchluessel": [] }, { "portalSitzung": [] }],
  "paths": {
    "/api/v1/export/chat-agent": {
      "get": {
        "operationId": "chatAgentExport",
        "summary": "Export von Wissensbasis und Einstellungen des Chat Agents",
        "description": "Liefert den aktuellen Export des Chat Agents des angemeldeten Kunden, Byte für Byte wie von NexAI erzeugt. Der Erzeugungszeitpunkt steht im Feld `exportiertAm` (RFC 3339) und im Kopf `Last-Modified`. NexAI erzeugt den Export bei jeder Änderung am Chat Agent neu und auf Verlangen des Kunden sofort (im Portal unter „Datenexport“). Hat der Kunde keinen Chat Agent, antwortet die Schnittstelle mit 404 und dem Code `kein_chat_agent`. Höchstens 120 Abrufe je Kunde und Stunde.",
        "parameters": [
          {
            "name": "download",
            "in": "query",
            "required": false,
            "description": "`1`: als Datei herunterladen (Content-Disposition: attachment).",
            "schema": { "type": "string", "enum": ["1"] }
          }
        ],
        "responses": {
          "200": {
            "description": "Der Export.",
            "headers": {
              "Last-Modified": {
                "description": "Erzeugungszeitpunkt des Exports (gleich `exportiertAm`).",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "https://nexaisoftware.de/schemas/chat-agent-export.json" }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet, oder der Schlüssel ist unbekannt oder widerrufen, oder das Konto, das ihn erzeugt hat, ist gesperrt oder gehört nicht mehr zu diesem Kunden. Ein ungültiger Schlüssel fällt nie auf die Sitzung zurück.",
            "headers": {
              "WWW-Authenticate": { "schema": { "type": "string", "const": "Bearer realm=\"nexaiapp\"" } }
            },
            "content": {
              "application/problem+json": {
                "schema": { "$ref": "#/components/schemas/Problem" },
                "example": { "type": "about:blank", "title": "Nicht angemeldet: Portal-Sitzung eines Kundenkontos oder Kundenschlüssel (Authorization: Bearer nxp_…) erforderlich.", "status": 401, "code": "nicht_angemeldet" }
              }
            }
          },
          "403": {
            "description": "Die Sitzung gehört nicht zu einem Kundenkonto.",
            "content": {
              "application/problem+json": {
                "schema": { "$ref": "#/components/schemas/Problem" },
                "example": { "type": "about:blank", "title": "Nur für Kundenkonten.", "status": 403, "code": "kein_kunde" }
              }
            }
          },
          "404": {
            "description": "Für diesen Kunden ist kein Chat Agent hinterlegt (auch: Kundenkonto, das noch keinem Kunden zugeordnet ist). Diese Antwort ist für jeden Kunden ohne Chat Agent gleich.",
            "content": {
              "application/problem+json": {
                "schema": { "$ref": "#/components/schemas/Problem" },
                "example": { "type": "about:blank", "title": "Für diesen Kunden ist kein Chat Agent hinterlegt.", "status": 404, "code": "kein_chat_agent" }
              }
            }
          },
          "429": {
            "description": "Mehr als 120 Abrufe in einer Stunde.",
            "headers": {
              "Retry-After": { "description": "Sekunden bis zum nächsten Versuch.", "schema": { "type": "integer" } }
            },
            "content": {
              "application/problem+json": {
                "schema": { "$ref": "#/components/schemas/Problem" },
                "example": { "type": "about:blank", "title": "Zu viele Anfragen. Bitte später erneut versuchen.", "status": 429, "code": "zu_viele_anfragen" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "kundenSchluessel": {
        "type": "http",
        "scheme": "bearer",
        "description": "Kundenschlüssel `nxp_…` aus dem Portal (Datenexport → Schnittstelle). Wird nur einmal angezeigt; widerrufbar. Gilt, solange das Konto, das ihn erzeugt hat, aktiv ist und zu diesem Kunden gehört."
      },
      "portalSitzung": {
        "type": "apiKey",
        "in": "cookie",
        "name": "nexai_portal_session",
        "description": "Angemeldete Portal-Sitzung eines Kundenkontos (Browser)."
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "Problem Details nach RFC 9457.",
        "required": ["type", "title", "status", "code"],
        "properties": {
          "type": { "type": "string", "const": "about:blank" },
          "title": { "type": "string" },
          "status": { "type": "integer" },
          "code": { "type": "string", "enum": ["nicht_angemeldet", "kein_kunde", "kein_chat_agent", "zu_viele_anfragen"] }
        }
      }
    }
  }
}
