Schnellstart
Drei Dinge, dann läuft der erste Aufruf: ein Schlüssel, die Base-URL, der Header. Wer schon ein OpenAI-SDK im Projekt hat, ändert nur die letzten zwei.
- Schlüssel ausstellen — Sie sehen ihn genau einmal.
Legen Sie ihn als Umgebungsvariable ab, etwa
PRIMA_API_KEY. -
Base-URL:
https://api.prima.li/api/prima/v1 -
Auth-Header:
X-API-Key: <Ihr Schlüssel>— nichtAuthorization: Bearer.
curl https://api.prima.li/api/prima/v1/chat/completions \
-H "X-API-Key: $PRIMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "prima-core",
"messages": [
{"role": "user", "content": "Fasse in einem Satz zusammen: Prima ist eine Schweizer KI-API."}
],
"max_tokens": 200
}' Antwort, unverändert:
{
"id": "primaapi_563afc5b719a4db0b23213a869182034",
"object": "chat.completion",
"model": "prima-core",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Prima ist die erste Schweizer KI-API für nahtlose Integration von Sprachmodellen in Anwendungen."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 31,
"completion_tokens": 23,
"total_tokens": 54
},
"prima": {
"alias": "prima-core",
"request_id": "primaapi_563afc5b719a4db0b23213a869182034"
}
} import os
from openai import OpenAI
client = OpenAI(
# 1. eine andere Base-URL
base_url="https://api.prima.li/api/prima/v1",
api_key=os.environ["PRIMA_API_KEY"],
# 2. ein anderer Auth-Header
default_headers={"X-API-Key": os.environ["PRIMA_API_KEY"]},
)
r = client.chat.completions.create(
model="prima-core",
messages=[{"role": "user", "content": "Nenne drei Schweizer Kantone."}],
max_tokens=200,
)
print(r.choices[0].message.content)
print(r.usage)
print(r.model_extra["prima"]) # alias + request_id ausgeführt gegen die Live-API, openai 2.2.0 auf Python 3.13.7
Hier sind drei Schweizer Kantone:
1. **Zürich**
2. **Bern**
3. **Genf** (franz. *Genève*)
Möchtest du noch weitere Kantone oder spezifische Informationen dazu? 😊
CompletionUsage(completion_tokens=52, prompt_tokens=22, total_tokens=74, completion_tokens_details=None, prompt_tokens_details=None)
{'alias': 'prima-core', 'request_id': 'primaapi_1fc8cbe0807e419b8d0f30e17886c74d'} import OpenAI from "openai";
const apiKey = process.env.PRIMA_API_KEY!;
const client = new OpenAI({
// 1. eine andere Base-URL
baseURL: "https://api.prima.li/api/prima/v1",
apiKey,
// 2. ein anderer Auth-Header
defaultHeaders: { "X-API-Key": apiKey },
});
const r = await client.chat.completions.create({
model: "prima-core",
messages: [{ role: "user", content: "Nenne drei Schweizer Kantone." }],
max_tokens: 200,
});
console.log(r.choices[0].message.content);
console.log(r.usage);
console.log((r as any).prima); ausgeführt gegen die Live-API, openai 7.3.0 auf Node v22.22.2
Hier sind drei Schweizer Kantone:
1. **Zürich**
2. **Bern**
3. **Genf**
Falls du noch mehr Beispiele oder spezifische Infos zu einem Kanton möchtest, lass es mich wissen! 😊
{ prompt_tokens: 22, completion_tokens: 53, total_tokens: 75 }
{
alias: 'prima-core',
request_id: 'primaapi_5cb26ac72165432a9df4be1124076206'
} Authentifizierung
Ein Header, immer derselbe: X-API-Key. Es gibt keine zweite
Variante und keinen Fallback. Ein API-Schlüssel als Bearer-Token
allein wird nicht akzeptiert — dieser Pfad prüft
Sitzungs-Token, keine Schlüssel.
Ihr SDK darf seinen eigenen Authorization: Bearer-Header
mitschicken. Er wird ignoriert, solange ein gültiger
X-API-Key danebensteht — Sie müssen ihn also
nicht entfernen. Gemessen am 3. August 2026 gegen die
Live-API, mit gültigem wie mit absichtlich falschem Bearer-Wert.
| Gesendet | Ergebnis |
|---|---|
X-API-Key: prima_pk_… | 200 — der normale Weg. |
Authorization: Bearer prima_pk_… allein | 401. Ein API-Schlüssel ist kein Bearer-Token. |
| beide Header zusammen |
200. X-API-Key gewinnt; Authorization
wird nicht geprüft — auch dann nicht, wenn er Unsinn enthält.
|
| gar nichts | 401 Missing credentials. |
Schlüssel tragen genau einen Scope: ai. Damit erreichen sie den
Gateway unter /api/prima/v1/ und sonst nichts — kein anderer
Teil der Plattform ist damit ansprechbar. Ein Prima-Schlüssel kann insbesondere
keine weiteren Schlüssel ausstellen; das geht nur angemeldet, hier im Portal.
OpenAI-Kompatibilität
Die Endpunkte /chat/completions, /embeddings und
/models haben die Form, die OpenAI-Clients erwarten. Sie behalten
Ihr SDK, Ihre Typen und Ihre Retry-Logik. Zwei Änderungen genügen:
base_url auf https://api.prima.li/api/prima/v1. -
X-API-Key als Default-Header setzen. Den
Authorization-Header des SDKs können Sie stehen lassen.
Mehr ist es nicht. Beide Schnellstarts oben sind genau in dieser Form gegen
die Live-API ausgeführt worden.
Was gleich ist
- Request- und Response-Form inklusive
usage. messages, temperature, max_tokens. tools und tool_choice werden durchgereicht. -
Das Feld
model in der Antwort enthält immer den Alias, den Sie
geschickt haben — nie einen internen Modellnamen.
Was anders ist
- Streaming funktioniert.
stream: true liefert
einen gewöhnlichen SSE-Strom aus
chat.completion.chunk-Objekten, abgeschlossen mit
data: [DONE]. Details unter Streaming.
- Ein Zusatzfeld
prima in jeder Antwort, mit
alias und request_id. OpenAI-Clients ignorieren
unbekannte Felder, es bricht also nichts.
- Andere Modellnamen. Vier Aliase, nach Aufgabe benannt:
prima-quick, prima-core, prima-deep, prima-embed.
Chat Completions
POST https://api.prima.li/api/prima/v1/chat/completions
Feld Typ Bedeutung modelstring, Pflicht Ein Alias. Ein interner Modellname wird nicht akzeptiert. messagesarray, Pflicht Wie bei OpenAI: role und content. max_tokensinteger
Obergrenze für die sichtbare Ausgabe.
Keine Obergrenze für die abgerechneten Tokens —
siehe Tokens & Abrechnung.
temperaturefloat, Standard 0.7 — tools, tool_choicearray / string Werden an das Modell weitergereicht; Tool-Calls kommen im gewohnten Format zurück. streambool
Beides funktioniert. true liefert SSE-Chunks, der
usage-Block kommt im letzten Chunk vor
[DONE].
Der prima-Block
Jede Antwort trägt ihn. request_id ist die Nummer, die Sie uns bei
einer Rückfrage nennen — sie steht auch im Zähler, ohne dass dort je ein Inhalt
gespeichert würde.
Bei prima-deep kann er zusätzlich
max_tokens_floor_applied enthalten. Das Modell denkt vor dem
Antworten, und mit einem knappen Limit bricht es mitten im Denken ab und liefert
null Zeichen. Statt das zu tun, hebt der Gateway das Limit auf 8000 an
und schreibt es in die Antwort:
"prima": {
"alias": "prima-deep",
"request_id": "primaapi_5202820bd9214f56a10a344b6064bf3b",
"max_tokens_floor_applied": true,
"requested_max_tokens": 1000,
"effective_max_tokens": 8000
}
Was das für die Rechnung bedeutet, steht unter
Tokens & Abrechnung — mit gemessenen Zahlen.
Embeddings
POST https://api.prima.li/api/prima/v1/embeddings — input ist ein String oder ein
Array von Strings.
curl https://api.prima.li/api/prima/v1/embeddings \
-H "X-API-Key: $PRIMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "prima-embed",
"input": ["Vertragsklausel A", "Vertragsklausel B"]
}'
{
"object": "list",
"model": "prima-embed",
"data": [
{ "object": "embedding", "index": 0, "embedding": [1.359375, -1.84375, … 3584 Werte] },
{ "object": "embedding", "index": 1, "embedding": [0.76953125, -2.15625, … 3584 Werte] }
],
"prima": {
"alias": "prima-embed",
"request_id": "primaapi_38d2ac0d2c1840dab8ba20d453d63b84",
"request_count": 2
}
}
Die Vektoren haben 3584 Dimensionen. Embeddings werden pro Anfrage
gezählt, nicht pro Token — ein Array mit zwei Strings sind zwei
Anfragen, wie request_count in der Antwort zeigt. Der Zähler
spiegelt damit exakt, wie unser Vorlieferant abrechnet; eine eigene
Kunstwährung gibt es nicht.
Modelle auflisten
curl https://api.prima.li/api/prima/v1/models -H "X-API-Key: $PRIMA_API_KEY"
Acht Einträge: vier gleitende Aliase und zu jedem ein festgeschriebenes
Gegenstück. Jeder Eintrag beschreibt sich selbst über
prima_kind, prima_floating und
prima_pinned_variant — bauen Sie Ihre Auswahl auf diesen Feldern
auf, nicht auf einer Liste von Namen in Ihrem Code.
Zur Modellreferenz.
Tokens & Abrechnung
Bitte einmal lesen, bevor Sie hochskalieren
Bei prima-deep begrenzt max_tokens Ihre Kosten
nicht — der Gateway hebt den Wert selbst an.
Bei prima-quick und prima-core tut er das nicht.
Der Unterschied ist gross genug, um ihn nicht zu raten.
prima-deep denkt, bevor es antwortet. Diese Denkschritte sind
Tokens, sie werden abgerechnet, und sie stehen nicht in der Antwort. Damit das
Modell nicht mitten im Denken abgeschnitten wird und Sie für eine unbrauchbare
Antwort zahlen, hebt der Gateway max_tokens auf einen Mindestwert
an — und sagt Ihnen das im prima-Block.
Sechs Aufrufe vom 3. August 2026, alle mit derselben Frage „Antworte nur mit:
ja“:
Alias max_tokens sichtbare Antwort abgerechnete completion_tokens effective_max_tokens prima-quick16"ja"2— prima-quick256"ja"2— prima-core16"ja"2— prima-core256"ja"2— prima-deep16" ja"366 8000 prima-deep256" ja"308 8000
Zwei Tokens gegen dreihundert, für dieselbe Antwort. Wenn Sie
prima-deep einsetzen, dann für Aufgaben, bei denen das Nachdenken
den Preis wert ist — nicht als Standardmodell. Wofür welcher Alias gedacht ist,
steht in der Modellreferenz.
Ob der Gateway eingegriffen hat, steht in jeder Antwort — im
prima-Block als max_tokens_floor_applied. Prüfen Sie
im Zweifel den, statt aus max_tokens auf die Kosten zu schliessen;
das Feld ist oben unter OpenAI-Kompatibilität abgedruckt.
Was daraus folgt, ganz nüchtern:
-
max_tokens ist keine Kostenbremse. Es begrenzt
die sichtbare Ausgabe, nicht das Denken davor. Im Beispiel oben werden bei
einem Limit von 16 gemessene 115 Tokens abgerechnet.
- Rechnen Sie mit dem, was
usage zurückgibt, nicht
mit einer Schätzung aus Ihrem Prompt. Der Wert steht in jeder Antwort.
- Kurze Antworten sind nicht billig. Ein Klassifikator, der
ein Wort zurückgibt, kostet dreistellig Tokens pro Aufruf. Bei
zehntausend Aufrufen am Tag ist das die Zahl, die zählt.
- Die harte Grenze ist Ihr Guthaben, nicht ein Tarif. Ist es
aufgebraucht, lehnt der Gateway neue Arbeit ab, statt weiterzurechnen und
hinterher zu belasten. Sie können zusätzlich ein eigenes Monatslimit setzen —
Ausgabenlimit.
Was gezählt wird — und was nicht
Der Zähler kennt Zeitpunkt, Alias, internes Modell, Token- und Anfragezahlen
sowie die request_id. Inhalte kennt er nicht. Es
gibt in der Zählertabelle keine Spalte, in der ein Prompt oder eine Antwort
landen könnte — auch nicht versehentlich. Deshalb kann Ihr
Verbrauch Ihnen zeigen, wie viel Sie verbraucht
haben, und nicht, was Sie geschrieben haben. Das ist keine fehlende Funktion,
das ist die Zusage.
Fehler & Grenzen
Form einer Fehlerantwort
Fehler sind OpenAI-förmig: ein Objekt unter error, nicht ein
String und nicht detail. Wer die Meldung auslesen will, liest
error.message; wer verzweigen will, verzweigt auf
error.code.
{
"error": {
"message": "Missing credentials",
"type": "authentication_error",
"param": null,
"code": "AUTH_001",
"request_id": "6e80a491-8385-46c6-85d5-48663b76af4c"
}
}
request_id ist in jeder Antwort enthalten, auch im Fehlerfall.
Nennen Sie sie, wenn Sie uns schreiben.
Leeres input
{
"error": {
"message": "`input` must be non-empty",
"type": "invalid_request_error",
"param": null,
"code": "SRV_001",
"request_id": "723bf49f-dd28-479c-bec0-bcdace8ba229"
}
}
Statuscodes
Code Bedeutung 200Antwort da. Mit stream: true als SSE-Strom, sonst als ein Objekt. 400Unbekannter Alias oder leeres input. Die Meldung nennt den Grund und listet bei einem Alias-Fehler die gültigen Werte auf. 401Kein oder falsches Credential. Ein zusätzlich mitgeschickter Authorization-Header ist kein Grund — der wird ignoriert. 402Guthaben aufgebraucht (code: insufficient_credit). Aufladen auf prima.li. Greift nur, wenn die Guthabenprüfung aktiv ist — heute ist sie es nicht. 403Der Schlüssel existiert, trägt aber nicht den ai-Scope, oder er wird ausserhalb von /api/prima/v1/ verwendet. 429Entweder gewöhnliche Drosselung, oder ein Verbrauchslimit ist erreicht (code: spend_cap_exceeded). Im zweiten Fall hilft Warten nicht. Geprüft wird vor dem Modellaufruf — eine abgelehnte Anfrage kostet nichts. 502Der Modellanbieter hat nicht geliefert. Wiederholen. 503Der Gateway ist nicht konfiguriert, oder die Guthabenverwaltung antwortet nicht (code: credits_unavailable). Beides unser Fehler, nicht Ihrer.
Unbekannter Alias
Der Fehler listet auf, was gültig gewesen wäre:
{
"error": {
"message": "Unknown PrimaAPI model alias 'prima-turbo'. Valid: ['prima-core', 'prima-core-2026-08', 'prima-deep', 'prima-deep-2026-08', 'prima-quick', 'prima-quick-2026-08']",
"type": "invalid_request_error",
"param": null,
"code": "SRV_001",
"request_id": "c8a7303a-c65a-498a-9353-28c6e513634c"
}
}
Streaming
stream: true wird unterstützt. Der Gateway antwortet mit einem
gewöhnlichen SSE-Strom aus chat.completion.chunk-Objekten und
schliesst mit data: [DONE] ab. Das offizielle OpenAI-SDK
iteriert ihn ohne Sonderbehandlung — dieselben zwei Zeilen Konfiguration wie
oben genügen.
const stream = await client.chat.completions.create({
model: "prima-core",
messages: [{ role: "user", content: "Zaehle von 1 bis 5." }],
max_tokens: 100,
stream: true,
});
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content;
if (delta) process.stdout.write(delta);
}
ausgeführt gegen die Live-API, openai 7.3.0 auf Node v22.22.2
Hier ist die Zählung von 1 bis 5:
1. eins
2. zwei
3. drei
4. vier
5. fünf
Wo der usage-Block bleibt: im letzten Chunk
vor [DONE], zusammen mit dem prima-Block. Die
Chunks davor tragen nur delta. Wer die Tokenzahl braucht, muss
den Strom also zu Ende lesen und darf nicht beim ersten
finish_reason aussteigen.
Korrektur
Frühere Fassungen dieser Seite behaupteten, stream: true werde
mit 400 abgelehnt. Das galt einmal und gilt nicht mehr;
nachgemessen am 3. August 2026 gegen die Live-API. Falls Sie Code haben, der
deshalb stream: false erzwingt: die Einschränkung ist weg.
Weitere Grenzen, offen benannt
- Early Access. PrimaAPI läuft, ist aber nicht allgemein
verfügbar. Zugang bekommt man auf Anfrage.
- Kein Requests-pro-Sekunde-Limit. Verbrauchsgrenzen sind
derzeit die einzige Verkehrssteuerung. Bauen Sie in Ihrem Client trotzdem ein
Backoff ein.
- Keine ISO-27001-Zertifizierung. Wir arbeiten darauf hin,
halten sie aber nicht. Was wir zusagen, ist der Ort der Verarbeitung und ein
unterschreibbarer Auftragsverarbeitungsvertrag — nicht ein Zertifikat, das
wir nicht haben.
Wenn etwas fehlt
Schreiben Sie an prima@alchemy.zuerich und nennen Sie die
request_id. Wir sehen damit den Aufruf im Zähler — Zeitpunkt,
Alias, Grösse. Ihren Prompt sehen wir nicht, und das können wir auch dann nicht
ändern, wenn Sie uns darum bitten.
Alle Beispiele und Zahlen auf dieser Seite gegen die Live-API geprüft am 3. August 2026.