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-API stellt die KI-Modelle eurer Firma programmatisch bereit. Sie ist kompatibel mit der OpenAI-API – bestehende Tools und SDKs funktionieren, wenn Sie base_url und den API-Schlüssel austauschen. Dabei gelten dieselben Regeln wie in der App: nur die für eure Firma freigegebenen Modelle, dieselbe EU-Freigabe und dasselbe Monatsbudget.

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 beginnen mit kasi_. Sie werden unter Administration → Zugriff erzeugt und nur einmal bei der Erstellung vollständig angezeigt; danach sieht man in der Oberfläche nur noch den Anfang zum Wiedererkennen.

Behandeln Sie den Schlüssel wie ein Passwort und verwenden Sie ihn nur serverseitig. Bei Verlust widerrufen Sie ihn und erstellen einen neuen.

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.

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 Agenten 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 sind ausgeblendet, und Nicht-EU-Modelle erscheinen nur, wenn Ihre Firma sie freigeschaltet hat.

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

Antwort:

{
  "object": "list",
  "data": [
    {
      "id": "self-hosted-gemma-4-31b",
      "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.

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 das gewählte Modell 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

Wird an das Modell weitergegeben

max_tokens

number

nein

Wird an das Modell weitergegeben

tools, response_format, …

–

nein

Wird an das Modell weitergegeben

Non-Streaming

curl https://kasimir.ai/api/v1/chat/completions \
  -H "Authorization: Bearer kasi_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "self-hosted-gemma-4-31b",
    "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-gemma-4-31b",
  "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 im OpenAI-Format. 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-gemma-4-31b",
    "messages": [{"role": "user", "content": "Zähle bis drei."}],
    "stream": true
  }'
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"self-hosted-gemma-4-31b","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": "jina-embeddings-v3",
    "input": "Beispieltext zum Einbetten"
  }'
{
  "object": "list",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0123, -0.045, "..."] }
  ],
  "model": "jina-embeddings-v3",
  "usage": { "prompt_tokens": 6, "total_tokens": 6 }
}

Die Vektordimension des Standard-Embedding-Modells ist auf 1024 festgelegt (jinaai/jina-embeddings-v3).

POST /assistants/{id}/run

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

Über die API laufen nur Agenten, die firmenweit freigegeben sind und kein Heimat-Projekt haben. Für private Agenten, Agenten mit Freigaben nur an Personen, Teams oder Projekte sowie Projekt-Agenten antwortet der Endpunkt mit 404.

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 Agenten

temperature

number (0–2)

nein

Überschreibt die Agenten-Einstellung

max_tokens

integer (1–32000)

nein

Überschreibt die Agenten-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-gemma-4-31b",
  "usage": { "prompt_tokens": 312, "completion_tokens": 88 }
}

Fehlt sowohl model_slug als auch ein Standardmodell am Agenten, antwortet der Endpunkt mit 400. Ein nicht gefundener oder fremder Agent 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-gemma-4-31b",
    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-gemma-4-31b",
    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="jina-embeddings-v3",
    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

Vorübergehender Fehler bei der Verarbeitung

EU-Governance & Souveränität

Für jeden API-Aufruf gilt dieselbe EU-Freigabe wie bei der Modellauswahl in der App: Modelle außerhalb der EU sind nur nutzbar, wenn eure Firma sie ausdrücklich freigeschaltet hat – sonst kommt 403.

Metering & Budget

Jeder erfolgreiche Completion- und Embedding-Aufruf wird mit Modell, Tokens und Kosten in Euro verbucht und zählt zum Monatsbudget eurer Firma. Die Kosten berechnen sich so:

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

Beim Streaming wird der Verbrauch am Ende des Streams verbucht.

Budget-Durchsetzung: Vor jeder Anfrage prüft die API das Monatsbudget der Firma. Der Monatsverbrauch umfasst API- und In-App-Chat-Kosten des laufenden Kalendermonats. Ist das Budget erreicht, antwortet die API mit 402. Ohne Budget gibt es keine Grenze. Eine Nutzungsübersicht (Anfragen, Tokens, Euro im laufenden Monat) finden Owner und Admins unter Administration → Zugriff.

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