Kasimir Docs DEEN Zur App →

API-Überblick

OpenAI-kompatible, EU-souveräne LLM-API von Kasimir: Authentifizierung, Endpunkte, Modelle, Streaming, Fehler und Metering.

Die Kasimir Public API stellt den geregelten, EU-souveränen LLM-Zugang programmatisch bereit. Sie ist drop-in-kompatibel mit der OpenAI-API — bestehende Tools und SDKs funktionieren, indem Sie lediglich base_url und den API-Schlüssel austauschen. Kasimir agiert dabei als schlanker Metering- und Governance-Proxy vor dem internen LiteLLM-Proxy: identisches Wire-Format, plus firmenspezifische Schlüssel-Isolation, ein gebrandeter Modell-Namespace, die EU-/Nicht-EU-Schranke, Nutzungsabrechnung und Durchsetzung des Firmen-Budgets.

Basis-URL

https://kasimir.ai/api/v1

Alle Endpunkte sind relativ zu dieser Basis-URL. Sie ist exakt das, was Sie als base_url in einem OpenAI-SDK setzen.

Authentifizierung

Jede Anfrage trägt einen Firmen-API-Schlüssel im Authorization-Header als Bearer-Token:

Authorization: Bearer kasi_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Schlüssel haben das Präfix kasi_ gefolgt von 32 Zeichen (Base32-Alphabet, ~160 Bit Entropie). Sie werden in /administration/access erzeugt, nur einmal bei der Erstellung im Klartext angezeigt und serverseitig ausschließlich als SHA-256-Digest gespeichert. Zur Identifikation zeigt die Oberfläche dauerhaft nur das Präfix (erste 8 Zeichen).

⚠️

Behandeln Sie den Schlüssel wie ein Passwort. Er wird nach der Erstellung nie wieder im Klartext angezeigt. Bei Verlust widerrufen Sie ihn und erstellen einen neuen. Der interne LiteLLM-Master-Key verlässt niemals den Server — Sie erhalten ausschließlich kasi_-Schlüssel.

Scopes

Schlüssel tragen Scopes. Die Endpunkte prüfen serverseitig:

Scope

Benötigt für

chat:write

POST /chat/completions, POST /embeddings, POST /assistants/{id}/run

(kein Scope)

GET /models — jeder gültige, nicht widerrufene Schlüssel genügt

Fehlt ein erforderlicher Scope, antwortet die API mit 403. Ein ungültiger oder widerrufener Schlüssel ergibt 401.

Metering & Governance Proxy One bearer key in. EU-gated model routing out. Script / SDK client = Kasimir( api_key= kasi_a9f3…7b2 ) Authorization: Bearer Metering + Governance Kasimir Proxy Key isolation EU gate Model namespace Usage ledger Budget LiteLLM proxy routing · fanout EU models non-EU gated opt-in Non-EU branch is locked behind a per-tenant sovereignty gate — disabled by default.
Kasimir sitzt als Metering- und Governance-Proxy zwischen Ihrem Code und den Modellen — Sie halten nur einen kasi_-Schlüssel.

Endpunkte im Überblick

Methode

Pfad

Zweck

Scope

GET

/models

Für die Firma freigegebene Chat- und Embedding-Modelle auflisten

beliebig gültig

POST

/chat/completions

Chat-Completion (Streaming + Non-Streaming)

chat:write

POST

/embeddings

Embedding-Vektoren erzeugen

chat:write

POST

/assistants/{id}/run

Gespeicherten Assistenten als One-Shot-Funktion ausführen

chat:write

Die ersten drei sind OpenAI-shaped. assistants/{id}/run ist ein Kasimir-spezifischer Komfort-Endpunkt (siehe unten).

GET /models

Liefert die für Ihre Firma freigegebenen Modelle, OpenAI-shaped. Die Liste wendet bereits die Firmen-Filter an: deaktivierte Modelle (disabled_model_slugs) sind ausgeblendet, und Nicht-EU-Modelle erscheinen nur, wenn Ihre Organisation allow_non_eu_models aktiviert hat.

curl https://kasimir.ai/api/v1/models \
  -H "Authorization: Bearer kasi_..."

Antwort:

{
  "object": "list",
  "data": [
    {
      "id": "self-hosted-llama-3.3-70b",
      "object": "model",
      "created": 1745971200,
      "owned_by": "kasimir"
    }
  ]
}

Das Feld id ist der Modell-Slug — genau dieser Wert gehört in das model-Feld der Completion- und Embedding-Aufrufe. Interne model_id-Werte und Upstream-Aliase werden nie nach außen gegeben.

ℹ️

Modell-Slugs sind firmen- und konfigurationsspezifisch. Verlassen Sie sich nicht auf hartkodierte Namen — fragen Sie GET /models ab, um die für Ihren Schlüssel gültigen Slugs zu erhalten.

POST /chat/completions

Akzeptiert einen OpenAI-Chat-Body. Pflichtfelder sind model und messages; alle weiteren Felder (temperature, max_tokens, tools, response_format, …) werden transparent durchgereicht, sodass Function-Calling, strukturierte Ausgaben, finish_reason und multimodale Inhalte so funktionieren, wie der Upstream sie unterstützt.

Parameter

Feld

Typ

Pflicht

Beschreibung

model

string

ja

Modell-Slug aus GET /models

messages

array

ja

Mindestens 1 Nachricht im OpenAI-Format (role + content)

stream

boolean

nein

true für Server-Sent-Events-Streaming (Default: false)

temperature

number

nein

Durchgereicht

max_tokens

number

nein

Durchgereicht

tools, response_format, …

nein

Durchgereicht (LiteLLM-Parität)

Non-Streaming

curl https://kasimir.ai/api/v1/chat/completions \
  -H "Authorization: Bearer kasi_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "self-hosted-llama-3.3-70b",
    "messages": [
      {"role": "system", "content": "Du bist ein hilfreicher Assistent."},
      {"role": "user", "content": "Erkläre DSGVO in einem Satz."}
    ]
  }'

Antwort (OpenAI-shaped; das model-Feld trägt den Slug zurück):

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1745971200,
  "model": "self-hosted-llama-3.3-70b",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Die DSGVO ist..." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 24, "completion_tokens": 18, "total_tokens": 42 }
}

Streaming

Mit "stream": true liefert die API einen text/event-stream. Die Upstream-SSE-Bytes werden transparent durchgereicht; Kasimir schreibt nur das model-Feld auf den Slug um und greift den finalen usage-Chunk für das Metering ab. Das Ende ist die übliche data: [DONE]-Zeile.

curl -N https://kasimir.ai/api/v1/chat/completions \
  -H "Authorization: Bearer kasi_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "self-hosted-llama-3.3-70b",
    "messages": [{"role": "user", "content": "Zähle bis drei."}],
    "stream": true
  }'
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"self-hosted-llama-3.3-70b","choices":[{"index":0,"delta":{"content":"Eins"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":12,"completion_tokens":5,"total_tokens":17}}

data: [DONE]

POST /embeddings

OpenAI-shaped Embeddings. Pflichtfelder: model (ein Embedding-Slug) und input (String oder String-Array).

Feld

Typ

Pflicht

Beschreibung

model

string

ja

Embedding-Modell-Slug (purpose='embedding')

input

string | string[]

ja

Zu embeddender Text bzw. Texte

curl https://kasimir.ai/api/v1/embeddings \
  -H "Authorization: Bearer kasi_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "self-hosted-bge-m3",
    "input": "Beispieltext zum Einbetten"
  }'
{
  "object": "list",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0123, -0.045, "..."] }
  ],
  "model": "self-hosted-bge-m3",
  "usage": { "prompt_tokens": 6, "total_tokens": 6 }
}
ℹ️

Die Vektordimension des Standard-Embedding-Modells ist auf 1024 festgelegt (BAAI/bge-m3).

POST /assistants/{id}/run

Komfort-Endpunkt (kein OpenAI-Standard), der einen in Kasimir gespeicherten Assistenten als One-Shot-Funktion ausführt. Der System-Prompt des Assistenten wird automatisch vorangestellt (plus das aktuelle Datum); kein SSE-Streaming, keine Konversations-Persistenz, kein Tool-Calling-Roundtrip.

Feld

Typ

Pflicht

Beschreibung

messages

array

ja

1–50 Nachrichten mit role (system/user/assistant) + content (string)

model_slug

string

nein

Überschreibt das Standardmodell des Assistenten

temperature

number (0–2)

nein

Überschreibt die Assistenten-Einstellung

max_tokens

integer (1–32000)

nein

Überschreibt die Assistenten-Einstellung

curl https://kasimir.ai/api/v1/assistants/<assistant-id>/run \
  -H "Authorization: Bearer kasi_..." \
  -H "Content-Type: application/json" \
  -d '{ "messages": [{"role": "user", "content": "Fasse den Quartalsbericht zusammen."}] }'
{
  "text": "Der Quartalsbericht zeigt...",
  "model": "self-hosted-llama-3.3-70b",
  "usage": { "prompt_tokens": 312, "completion_tokens": 88 }
}

Fehlt sowohl model_slug als auch ein Standardmodell am Assistenten, antwortet der Endpunkt mit 400. Ein nicht gefundener oder fremder Assistent ergibt 404.

Verwendung mit dem OpenAI Python SDK

Da die Endpunkte OpenAI-shaped sind, genügt es, base_url und api_key zu setzen:

from openai import OpenAI

client = OpenAI(
    base_url="https://kasimir.ai/api/v1",
    api_key="kasi_...",
)

# Modelle auflisten
for m in client.models.list().data:
    print(m.id)

# Chat-Completion
resp = client.chat.completions.create(
    model="self-hosted-llama-3.3-70b",
    messages=[{"role": "user", "content": "Erkläre DSGVO in einem Satz."}],
)
print(resp.choices[0].message.content)

# Streaming
stream = client.chat.completions.create(
    model="self-hosted-llama-3.3-70b",
    messages=[{"role": "user", "content": "Zähle bis drei."}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

# Embeddings
emb = client.embeddings.create(
    model="self-hosted-bge-m3",
    input="Beispieltext zum Einbetten",
)
print(len(emb.data[0].embedding))

Fehler

Fehler sind OpenAI-shaped, mit korrektem HTTP-Statuscode, sodass Standard-SDKs sie normal melden:

{ "error": { "message": "Model \"foo\" not found", "type": "not_found_error", "code": null } }

HTTP

type

Bedeutung

400

invalid_request_error

Ungültiger Request-Body (z. B. fehlendes model/messages)

401

authentication_error

Fehlender, ungültiger oder widerrufener Schlüssel

402

insufficient_quota

Monatsbudget der Firma erreicht

403

permission_error

Fehlender Scope oder durch EU-Schranke gesperrtes Nicht-EU-Modell

404

not_found_error

Modell/Assistent nicht gefunden bzw. für die Firma deaktiviert

502

api_error

Upstream-Fehler (LiteLLM/Modell)

EU-Governance & Souveränität

Jeder API-Aufruf durchläuft serverseitig dieselbe EU-/Nicht-EU-Schranke wie die In-App-Modellauswahl. Modelle mit eu_hosted=false sind nur erreichbar, wenn die Organisation allow_non_eu_models explizit aktiviert hat — andernfalls 403. Der gebrandete Modell-Namespace (Slug ↔ interne model_id) und der LiteLLM-Master-Key bleiben vollständig serverseitig. So gilt für die API dieselbe DSGVO-Garantie wie für die Anwendung.

Metering & Budget

Jeder erfolgreiche Completion- bzw. Embedding-Aufruf wird im api_usage-Ledger verbucht (Modell-Slug, Endpunkt, Prompt-/Completion-Tokens, Kosten in EUR). Die Kosten folgen der Standardformel:

cost = (prompt_tokens / 1000) * cost_eur_per_1k_input
     + (completion_tokens / 1000) * cost_eur_per_1k_output

Beim Streaming stammt die Nutzung aus dem getappten finalen usage-Chunk (stream_options.include_usage wird automatisch gesetzt). Metering ist best-effort — ein Abrechnungsfehler bricht die bereits gesendete Antwort nie ab.

Budget-Durchsetzung: Vor jedem Forward prüft die API das Firmen-Monatsbudget (companies.monthly_budget_eur). Der Monatsverbrauch umfasst API- und In-App-Chat-Kosten des laufenden Kalendermonats. Ist das Budget erreicht, antwortet die API mit 402. Ein Budget von null/0 bedeutet unbegrenzt. Eine Nutzungsübersicht (Requests, Tokens, EUR diesen Monat) finden Owner/Admins unter /administration/access.

💡

Setzen Sie ein Monatsbudget in der Administration, um Kostenkontrolle zu erzwingen — ohne Budget laufen API-Aufrufe unbegrenzt.