Skip to main content
Ottili AI API

Ottili AI API — Schnellstart

Eine Copy-Paste-Anleitung für die öffentliche, OpenAI-kompatible Ottili AI API — authentifizieren, Modelle auflisten, erste Chat-Completion senden, Token streamen und Fehler behandeln.

Dieser Schnellstart bringt dich in wenigen Minuten von null zu deinem ersten API-Aufruf. Die

Ottili AI API ist die öffentliche, versionierte Entwickler-Oberfläche für Ottili AI. Sie ist

OpenAI-kompatibel*: Anfrage- und Antwortformate entsprechen dem OpenAI-Chat-Completions-Vertrag,

sodass vorhandenes OpenAI-Tooling mit einer anderen Base-URL darauf zugreifen kann.

Die Ottili AI API befindet sich im öffentlichen Beta-Stadium*. Felder, Modelle und Limits können sich weiterentwickeln; der live-Endpunkt GET /api/v1/ai/models ist die Quelle der Wahrheit für aktuell verfügbare Modelle.

1. Base-URL

Alle Endpunkte werden über den öffentlichen AI-API-Host bereitgestellt:

https://api.ottilione.com

Diese Oberfläche dokumentiert ausschließlich den öffentlichen Entwickler-Vertrag. Interne

Unified-API-Routen, Admin-Endpunkte, Dashboard-Routen und lokale Entwicklungspfade sind

bewusst kein* Teil dieser Oberfläche.

2. Authentifizierung

Jede Anfrage wird über den Authorization-Header authentifiziert:

Authorization: Bearer ott_your_api_key_here

Zwei Anmeldetypen werden akzeptiert:

  • Service-API-Schlüssel* — in Ottili Auth erstellt, mit ott_ präfixiert, bei der Erstellung

nur einmal angezeigt, verschlüsselt (gehasht) gespeichert.

  • JWT-Bearer-Token* — von Ottili Auth für Benutzersitzungen ausgestellt.

Dein Unternehmens- und Workspace-Kontext wird automatisch* aus der verifizierten Mitgliedschaft

des Schlüssels aufgelöst. Du sendest keine* Tenant- oder Unternehmens-Header, und rohe

Company-ID-Header werden ignoriert. Ein fehlender oder ungültiger Schlüssel führt geschlossen

mit 401 zu einem Fehler.

3. Deine erste Anfrage

Wähle eine Model-ID aus GET /api/v1/ai/models (siehe Schritt 4). Das eingespielte öffentliche

Modell ottili-1.3-chat wird unten als konkretes, funktionierendes Beispiel verwendet.

curl -X POST "https://api.ottilione.com/api/v1/ai/chat/completions" \
  -H "Authorization: Bearer ott_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ottili-1.3-chat",
    "messages": [
      { "role": "system", "content": "Du bist ein präziser Assistent." },
      { "role": "user", "content": "Fasse die offenen Bestellungen dieses Kunden in einem Satz zusammen." }
    ]
  }'

Antwort (OpenAI-kompatibel):

{
  "id": "chatcmpl-9f2c1a4b6e",
  "object": "chat.completion",
  "created": 1783987200,
  "model": "ottili-1.3-chat",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Der Kunde hat 3 offene Bestellungen über insgesamt 1.240 €, alle warten auf Versand." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 18, "completion_tokens": 14, "total_tokens": 32 }
}

Das Feld usage kann null sein, wenn für das gewählte Modell keine Token-Abrechnung verfügbar ist.

4. Verfügbare Modelle auflisten

curl "https://api.ottilione.com/api/v1/ai/models" \
  -H "Authorization: Bearer ott_your_api_key_here"

Antwort (normalisierter Erfolgs-Envelope):

{
  "success": true,
  "request_id": "b1c2d3e4-0000-1111-2222-333344445555",
  "company": {
    "platform_company_id": 1,
    "tenant_key": "acme",
    "company_role": "owner",
    "is_superadmin": false,
    "is_company_admin": true
  },
  "models": [
    {
      "public_model_name": "ottili-1.3-chat",
      "provider_name": "openai",
      "provider_model_name": "gpt-5.4",
      "model_class": "default",
      "input_price_per_1m": 0.45,
      "cached_input_price_per_1m": 0.12,
      "output_price_per_1m": 0.9,
      "default_multiplier": 1,
      "enabled": true,
      "allowed_plans": ["free", "pro", "enterprise"],
      "supports_coding": false,
      "supports_long_context": false,
      "supports_tool_use": true
    }
  ]
}

Übergib den Wert public_model_name als model-Feld in deinen Chat-Anfragen.

5. Token streamen

Verwende den eigenen Streaming-Endpunkt, um Token während der Generierung zu erhalten

(text/event-stream):

curl -N -X POST "https://api.ottilione.com/api/v1/ai/chat/completions/stream" \
  -H "Authorization: Bearer ott_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ottili-1.3-chat",
    "messages": [
      { "role": "user", "content": "Entwirf eine kurze Folge-E-Mail zu einem offenen Angebot." }
    ]
  }'

Jedes Event ist eine data:-Zeile mit einem JSON-Delta, endend mit data: [DONE]:

data: {"id":"chatcmpl-7a1b","object":"chat.completion.chunk","created":1783987300,"model":"ottili-1.3-chat","choices":[{"index":0,"delta":{"content":"Hallo"},"finish_reason":null}]}
data: {"id":"chatcmpl-7a1b","object":"chat.completion.chunk","created":1783987300,"model":"ottili-1.3-chat","choices":[{"index":0,"delta":{"content":" dort"},"finish_reason":null}]}
data: {"id":"chatcmpl-7a1b","object":"chat.completion.chunk","created":1783987300,"model":"ottili-1.3-chat","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]

Stream in JavaScript verarbeiten:

const res = await fetch("https://api.ottilione.com/api/v1/ai/chat/completions/stream", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.OTTILI_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "ottili-1.3-chat",
    messages: [{ role: "user", content: "Entwirf eine kurze Folge-E-Mail." }],
  }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  for (const line of decoder.decode(value).split("\n")) {
    if (!line.startsWith("data:") || line.includes("[DONE]")) continue;
    const chunk = JSON.parse(line.slice(5));
    if (chunk.choices?.[0]?.delta?.content) process.stdout.write(chunk.choices[0].delta.content);
  }
}

6. Fehler behandeln

Fehler verwenden Standard-HTTP-Statuscodes mit einer maschinenlesbaren Hülle, die einen

stabilen code und eine menschenlesbare message enthält:

{
  "detail": {
    "code": "AI_CHAT_NO_USER_MESSAGE",
    "message": "At least one user message is required."
  }
}

Häufige Fälle:

StatuscodeBedeutung
401authentication requiredFehlender oder ungültiger API-Schlüssel / JWT.
400AI_COMPANY_CONTEXT_REQUIREDDer Schlüssel ist keiner aktiven Firma zugeordnet.
422AI_CHAT_NO_USER_MESSAGEDas messages-Array hat keinen role: "user"-Eintrag.
500AI_CHAT_SESSION_CREATE_FAILEDVorübergehender serverseitiger Fehler beim Erstellen der Sitzung.

Ein robuster Client liest den code, um Retry vs. Anzeige zu entscheiden, und behandelt jeden

nicht-2xx-Status als Fehler.

const res = await fetch("https://api.ottilione.com/api/v1/ai/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.OTTILI_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ model: "ottili-1.3-chat", messages: [{ role: "user", content: "Hallo" }] }),
});

if (!res.ok) {
  const err = await res.json().catch(() => ({}));
  const code = err?.detail?.code ?? `HTTP_${res.status}`;
  console.error(`Anfrage fehlgeschlagen (${code}):`, err?.detail?.message ?? res.statusText);
  process.exit(1);
}

const data = await res.json();
console.log(data.choices[0].message.content);

7. Minimaler Python-Client

import os, requests

API_KEY = os.environ["OTTILI_API_KEY"]
BASE = "https://api.ottilione.com/api/v1/ai"

resp = requests.post(
    f"{BASE}/chat/completions",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={
        "model": "ottili-1.3-chat",
        "messages": [{"role": "user", "content": "Wie hoch ist mein Credit-Saldo?"}],
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json()["choices"][0]["message"]["content"])

8. Rate-Limits und Credits

Die KI-Nutzung wird gegen dein unternehmensweites Credit-Wallet abgerechnet. Jede abrechenbare

Anfrage reserviert vor der Ausführung den Worst-Case-Bedarf und rechnet bei Erfolg ab. Details

in [Credits & Nutzung](/docs/ottili-ai-api-credits) und

[Rate-Limits](/docs/ottili-ai-api-rate-limits) sowie

[GET /api/v1/ai/credits/balance](/docs/ottili-ai-api-credits) zum Abrufen des aktuellen Saldos.

9. Nächste Schritte

  • [Ottili AI API Übersicht](/docs/ottili-ai-api) — vollständige Vertragsreferenz.
  • [Modelle & Verfügbarkeit](/docs/ottili-ai-api-models)
  • [Streaming](/docs/ottili-ai-api-streaming)
  • [Fehler](/docs/ottili-ai-api-errors)
  • [Tool-Calls](/docs/ottili-ai-api-tool-calls) und [Strukturierte Ausgaben](/docs/ottili-ai-api-structured-outputs)

War dieser Artikel hilfreich?