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/v1Alle 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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxSchlü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 |
|---|---|
|
|
(kein Scope) |
|
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 |
|---|---|---|---|
|
| Für die Firma freigegebene Chat- und Embedding-Modelle auflisten | beliebig gültig |
|
| Chat-Completion (Streaming + Non-Streaming) |
|
|
| Embedding-Vektoren erzeugen |
|
|
| Gespeicherten Agenten als One-Shot-Funktion ausführen |
|
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 |
|---|---|---|---|
| string | ja | Modell-Slug aus |
| array | ja | Mindestens 1 Nachricht im OpenAI-Format ( |
| boolean | nein |
|
| number | nein | Wird an das Modell weitergegeben |
| number | nein | Wird an das Modell weitergegeben |
| – | 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 |
|---|---|---|---|
| string | ja | Embedding-Modell-Slug ( |
| 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 |
|---|---|---|---|
| array | ja | 1–50 Nachrichten mit |
| string | nein | Überschreibt das Standardmodell des Agenten |
| number (0–2) | nein | Überschreibt die Agenten-Einstellung |
| 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 |
| Bedeutung |
|---|---|---|
|
| Ungültiger Request-Body (z. B. fehlendes |
|
| Fehlender, ungültiger oder widerrufener Schlüssel |
|
| Monatsbudget der Firma erreicht |
|
| Fehlender Scope oder durch EU-Schranke gesperrtes Nicht-EU-Modell |
|
| Modell/Assistent nicht gefunden bzw. für die Firma deaktiviert |
|
| 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_outputBeim 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.