{
  "openapi": "3.1.0",
  "info": {
    "title": "SovrGPT API",
    "version": "1.0.0",
    "description": "OpenAI-kompatible HTTP-API für die SovrGPT-Plattform, vollständig auf EU-Infrastruktur. Bestehende OpenAI-Clients funktionieren ohne Code-Änderung — nur `baseURL` und ggf. `model` umstellen. Menschliche Doku: https://sovrgpt.com/docs/api",
    "contact": { "name": "SovrGPT", "url": "https://sovrgpt.com/docs/api" },
    "license": { "name": "Betreiber: eNetworkers", "url": "https://e-networkers.de" }
  },
  "servers": [
    { "url": "https://sovrgpt.com/api/v1", "description": "Produktion (EU)" }
  ],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "Models", "description": "Modelle abfragen" },
    { "name": "Chat", "description": "Chat-Completions (LLM)" },
    { "name": "Embeddings & Rerank", "description": "RAG-Bausteine" },
    { "name": "Audio", "description": "Text-to-Speech & Speech-to-Text" }
  ],
  "paths": {
    "/models": {
      "get": {
        "tags": ["Models"],
        "summary": "Alle aktiven Modelle abfragen",
        "description": "Listet alle für die aufrufende Org freigeschalteten Modelle (Chat, Embeddings, Rerank, TTS, STT). Das Feld `kind` sagt, über welchen Endpoint ein Modell adressiert wird. Kein spezieller Scope nötig.",
        "operationId": "listModels",
        "responses": {
          "200": {
            "description": "Liste der Modelle",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ModelList" },
                "example": {
                  "object": "list",
                  "data": [
                    { "id": "qwen3.5-9b", "object": "model", "owned_by": "sovrgpt", "kind": "chat", "tier": "default", "display_name": "Qwen 3.5 9B", "license": "Apache 2.0" },
                    { "id": "supertonic-3", "object": "model", "owned_by": "sovrgpt", "kind": "tts", "display_name": "Supertonic 3 — Text-to-Speech", "license": "OpenRAIL-M" },
                    { "id": "cosyvoice-3", "object": "model", "owned_by": "sovrgpt", "kind": "tts", "display_name": "CosyVoice 3 — Expressive TTS + Voice-Cloning", "license": "Apache 2.0" },
                    { "id": "voxtral-mini-transcribe", "object": "model", "owned_by": "sovrgpt", "kind": "stt", "display_name": "Voxtral Mini Transcribe — Speech-to-Text" }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/chat/completions": {
      "post": {
        "tags": ["Chat"],
        "summary": "Chat-Completion erzeugen",
        "description": "OpenAI-kompatibel. Streaming via SSE (`stream: true`). Scope: `chat`.",
        "operationId": "createChatCompletion",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["model", "messages"],
                "properties": {
                  "model": { "type": "string", "example": "qwen3.5-9b", "description": "Modell-ID aus GET /models (kind=chat)." },
                  "messages": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "role": { "type": "string", "enum": ["system", "user", "assistant", "tool"] },
                        "content": { "type": "string" }
                      }
                    }
                  },
                  "temperature": { "type": "number", "default": 1 },
                  "top_p": { "type": "number" },
                  "max_tokens": { "type": "integer" },
                  "stream": { "type": "boolean", "default": false },
                  "stop": { "type": "array", "items": { "type": "string" } },
                  "tools": { "type": "array", "items": { "type": "object" } },
                  "tool_choice": {},
                  "response_format": { "type": "object" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Chat-Completion (JSON) oder SSE-Stream (text/event-stream bei stream=true)." },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/embeddings": {
      "post": {
        "tags": ["Embeddings & Rerank"],
        "summary": "Text-Embeddings erzeugen",
        "description": "OpenAI-kompatibel. Scope: `embeddings`. Modelle: `bge-m3` (1024, mehrsprachig), `nomic-embed-code` (3584, Code).",
        "operationId": "createEmbeddings",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["model", "input"],
                "properties": {
                  "model": { "type": "string", "example": "bge-m3" },
                  "input": {
                    "oneOf": [
                      { "type": "string" },
                      { "type": "array", "items": { "type": "string" } }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Embedding-Vektoren (OpenAI-Schema)." },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/rerank": {
      "post": {
        "tags": ["Embeddings & Rerank"],
        "summary": "Dokumente nach Relevanz neu ordnen",
        "description": "Cohere-kompatibel (Cross-Encoder). Scope: `rerank`. Modell: `bge-reranker-base`.",
        "operationId": "rerank",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["query", "documents"],
                "properties": {
                  "model": { "type": "string", "example": "bge-reranker-base" },
                  "query": { "type": "string" },
                  "documents": { "type": "array", "items": { "type": "string" } },
                  "top_n": { "type": "integer" },
                  "return_documents": { "type": "boolean", "default": false }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Nach Relevanz sortierte Ergebnisse." },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/audio/speech": {
      "post": {
        "tags": ["Audio"],
        "summary": "Text-to-Speech",
        "description": "Erzeugt gesprochene Audio-Bytes aus Text. Antwort = roher Audio-Body (kein JSON-Wrapper). Scope: `speech`.\n\nDrei EU-souveräne Engines, wählbar über das Standard-`model`-Feld (OpenAI-idiomatisch) oder das explizite `provider`-Feld:\n- `supertonic-3` — schnell, kein Cold-Start, feste Stimmen M1–M5/F1–F5.\n- `cosyvoice-3` — Deutsch nativ, Inline-Tags ([laughter]/[breath]/<strong>), Emotion per natürlichsprachiger Anweisung, Zero-Shot-Voice-Cloning.\n- `voxtral-mini-tts` — Mistral-Fallback.\n\nSovrGPT-Erweiterungsfelder (emotion/instruction, reference_audio_b64, prompt_text, provider, language) sind kein OpenAI-Standard → im Python-SDK via `extra_body` mitgeben.",
        "operationId": "createSpeech",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SpeechRequest" },
              "examples": {
                "supertonic": {
                  "summary": "Supertonic (schnell, feste Stimme)",
                  "value": { "model": "supertonic-3", "voice": "F3", "input": "Guten Tag <breath> willkommen bei SovrGPT.", "response_format": "wav" }
                },
                "cosyvoice_tags": {
                  "summary": "CosyVoice — Deutsch mit Inline-Tags + Betonung",
                  "value": { "model": "cosyvoice-3", "voice": "de-thorsten", "input": "Und dann [breath] öffnete ich die Tür. [laughter] Das war <strong>unglaublich</strong>." }
                },
                "cosyvoice_emotion": {
                  "summary": "CosyVoice — Emotion (natürlichsprachig)",
                  "value": { "model": "cosyvoice-3", "voice": "de-thorsten", "input": "Diese Zeiten sind für immer vorbei.", "emotion": "Sprich sehr traurig, leise und langsam." }
                },
                "cosyvoice_clone": {
                  "summary": "CosyVoice — eigene Stimme (Zero-Shot-Cloning)",
                  "value": { "model": "cosyvoice-3", "input": "Ein neuer Satz in meiner geklonten Stimme.", "reference_audio_b64": "<base64 wav/flac, <=30s>", "prompt_text": "<Transkript des Referenzclips>" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Roher Audio-Body. Header `X-Voice-Provider` nennt die genutzte Engine.",
            "headers": {
              "X-Voice-Provider": { "schema": { "type": "string", "enum": ["supertonic", "cosyvoice", "mistral"] } }
            },
            "content": {
              "audio/wav": { "schema": { "type": "string", "format": "binary" } },
              "audio/flac": { "schema": { "type": "string", "format": "binary" } },
              "audio/mpeg": { "schema": { "type": "string", "format": "binary" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "503": { "description": "TTS-Anbieter nicht konfiguriert ODER CosyVoice-Worker im Cold-Start (warming up) — in ~1 Min erneut senden." }
        }
      }
    },
    "/audio/transcriptions": {
      "post": {
        "tags": ["Audio"],
        "summary": "Speech-to-Text",
        "description": "Transkribiert eine hochgeladene Audiodatei. Läuft auf Mistral Voxtral (Paris/EU). Scope: `transcribe`.",
        "operationId": "createTranscription",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary", "description": "Audio (webm/ogg/mp3/wav/m4a …), ≤ 25 MiB." },
                  "language": { "type": "string", "example": "de", "description": "ISO-639-1; erhöht die Genauigkeit." },
                  "response_format": { "type": "string", "enum": ["json", "text", "verbose_json"], "default": "json" },
                  "model": { "type": "string", "example": "voxtral-mini-transcribe" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transkript",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "text": { "type": "string" } } } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "413": { "description": "Datei > 25 MiB." }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "SovrGPT-API-Key (`sov_…`) aus https://sovrgpt.com/settings/api-keys. Pro Key wählbare Scopes: chat, embeddings, rerank, speech, transcribe, mcp."
      }
    },
    "responses": {
      "Unauthorized": { "description": "Fehlender/ungültiger Bearer-Token.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Forbidden": { "description": "Key fehlt der nötige Scope.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "BadRequest": { "description": "Ungültige Anfrage (fehlendes/zu langes Feld, ungültige Stimme).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "message": { "type": "string" },
              "type": { "type": "string" }
            }
          }
        }
      },
      "ModelList": {
        "type": "object",
        "properties": {
          "object": { "type": "string", "example": "list" },
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Model" } }
        }
      },
      "Model": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "object": { "type": "string", "example": "model" },
          "owned_by": { "type": "string", "example": "sovrgpt" },
          "kind": { "type": "string", "enum": ["chat", "embedding", "rerank", "tts", "stt"] },
          "tier": { "type": "string" },
          "display_name": { "type": "string" },
          "description": { "type": "string" },
          "license": { "type": "string" }
        }
      },
      "SpeechRequest": {
        "type": "object",
        "required": ["input"],
        "properties": {
          "input": { "type": "string", "maxLength": 4000, "description": "Zu sprechender Text. Inline-Tags je nach Engine: Supertonic <breath>/<sigh>; CosyVoice [laughter]/[breath]/<laughter>…</laughter>/<strong>…</strong>." },
          "model": { "type": "string", "enum": ["supertonic-3", "cosyvoice-3", "voxtral-mini-tts"], "description": "Wählt die Engine (OpenAI-idiomatisch)." },
          "provider": { "type": "string", "enum": ["supertonic", "cosyvoice", "mistral"], "description": "Explizite Engine-Wahl; hat Vorrang vor `model`." },
          "voice": { "type": "string", "description": "Supertonic: M1–M5/F1–F5. CosyVoice: de-thorsten. Mistral: default-de/default-en." },
          "response_format": { "type": "string", "enum": ["wav", "flac", "ogg", "mp3", "opus", "aac"], "description": "CosyVoice liefert immer wav." },
          "language": { "type": "string", "example": "de", "description": "ISO-639-1 (Supertonic/CosyVoice)." },
          "emotion": { "type": "string", "description": "CosyVoice: natürlichsprachige Emotions-/Stil-Anweisung, z. B. 'Sprich sehr traurig und langsam.' (Alias: instruction)." },
          "instruction": { "type": "string", "description": "Alias von `emotion`." },
          "reference_audio_b64": { "type": "string", "description": "CosyVoice: Base64 wav/flac (≤ 30 s) → klont diese Stimme (Zero-Shot). Überschreibt `voice`." },
          "prompt_text": { "type": "string", "description": "CosyVoice: wörtliches Transkript des Referenzclips (beste Qualität)." },
          "speed": { "type": "number", "minimum": 0.5, "maximum": 2.0, "default": 1.0, "description": "CosyVoice: Sprechtempo." }
        }
      }
    }
  }
}
