AI-API-Referenz
Jeder Endpoint auf api.nodion.ai/v1, mit Limits und Fehlern.
Basis-URL: https://api.nodion.ai/v1. Die API folgt der OpenAI-Form, OpenAI-SDKs funktionieren
also, wenn du sie auf diese Basis-URL zeigst. Keys, Wallet und Dashboard-Tabs stehen unter
AI Inference.
pythonimport os
from openai import OpenAI
client = OpenAI(
base_url="https://api.nodion.ai/v1",
api_key=os.environ["NODION_AI_KEY"],
)
reply = client.chat.completions.create(
model="<model>",
messages=[{"role": "user", "content": "Hello"}],
)
print(reply.choices[0].message.content) Authentifizierung
Einen Inference-Key (nodion_ai_…) als Bearer-Token auf jedem Request schicken. Plattform-Keys
(nodion_…) funktionieren hier nicht. GET /v1/models ist der einzige Call, der keinen Key braucht.
httpAuthorization: Bearer nodion_ai_… Ein abgelehnter Key antwortet 401 mit einer dieser Messages:
missing bearer tokeninvalid api keyapi key expiredaccount disabledaccount under review
Jede Antwort trägt einen Header X-Request-ID. Den dem Support nennen.
JSON-Request-Bodies dürfen bis 1 MiB groß sein (System One 512 KiB). Base64 macht ein Drittel extra, eine Datei
inline in JSON, etwa ein Bild, ein PDF oder ein OCR-Dokument, kann also etwa 750 KB sein. Multipart-Uploads an
/v1/audio/transcriptions und /v1/audio/voices dürfen bis 25 MiB sein, mit
Transkriptionsdateien bis 20 MiB und Voice-Sample-Dateien bis 10 MiB (11 MiB für das ganze
Formular).
Endpoints
| Endpoint | Was es tut | Abrechnung nach |
|---|---|---|
GET /v1/models | Token-bezahlte Modelle listen | Kostenlos |
POST /v1/chat/completions | Chat, Tools, Structured Output | Input- und Output-Tokens |
POST /v1/embeddings | Vektor-Embeddings | Input-Tokens |
POST /v1/rerank | Dokumente gegen eine Query ranken | Input-Tokens |
POST /v1/systemone | System One: typisierte Entscheidungen mit Wahrscheinlichkeiten | Input-Tokens |
POST /v1/ocr | Dokument- und Bild-OCR | Seiten |
POST /v1/audio/transcriptions | Sprache zu Text | Audio-Sekunden |
GET /v1/audio/transcriptions/realtime (WebSocket) | Echtzeit Sprache zu Text | Audio-Sekunden |
POST /v1/audio/speech | Text zu Sprache | Zeichen |
GET, POST /v1/audio/voices | Geklonte Voices listen und anlegen | Kostenlos |
GET, DELETE /v1/audio/voices/{id} | Eine geklonte Voice lesen oder löschen | Kostenlos |
POST /v1/images/generations | Bildgenerierung | Bilder |
POST /v1/tools/web_search, web_news, web_fetch, web_images, web_videos, web_places, web_maps, web_shopping, web_lens | Web-Tools | Calls, plus jede Seite, die ein web_search fetcht |
Audio, Bilder und Tools stehen mit Beispielen unter AI Inference. Der Rest folgt hier.
Vor einem Call hält das Wallet eine Obergrenze der Kosten. Der Request wird dann auf den gemeldeten Usage abgerechnet,
nie über dem Hold, der Rest wird freigegeben. Meldet eine erfolgreiche Antwort keinen Usage, wird der volle Hold
berechnet. Eine Realtime-Transkription-Session hält max_audio_seconds des Modells (1.800 Sekunden,
wenn das Modell keins setzt), das Wallet muss also eine volle Session im Voraus decken.
Modelle
GET /v1/models gibt {"object": "list", "data": [...]} zurück und listet Chat-,
Embeddings- und Rerank-Modelle. OCR, Speech, Bild und Tool-Modelle stehen nicht darin; der öffentliche
Katalog unter https://api.nodion.com/v2/public/ai/models listet jede Art. Nützliche Felder pro Modell:
id: der Wert fürmodelin Requests.kind:chat,embeddingsoderrerank.context_lengthundmax_output_lengthin Tokens.pricing: USD pro Token als Dezimalstrings.pricing_eurhat die EUR-Preise.supported_sampling_parametersundsupported_features(zum Beispieltools,json_mode,structured_outputs,reasoning).reasoning_efforts: die Werte fürreasoning_effort, die dieses Modell akzeptiert (zum Beispielnone,low,high). Leer, wenn Stages nicht konfigurierbar sind.is_ready:falseheißt, gerade ist keine Route healthy. Das Modell bleibt gelistet.lifecycle:gaoderpreview.serving:hosted(die Weights laufen auf Nodion) oderrouted(an einen Provider weitergeleitet).supports_decisions: das Modell beantwortet System One.coding_plan: Codion kann dieses Chat-Modell anbieten. Immertrueoderfalse. Das ist nicht der Abrechnungs-Coding-Plan.free_until: gesetzt, solange ein Free-Fenster auf einem nur von Nodion bedienten Modell aktiv ist. Die Token-Preise lesen dann 0.
Chat Completions
POST /v1/chat/completions nimmt den OpenAI-Chat-Completions-Body: model,
messages und die optionalen Felder, die das Modell in supported_sampling_parameters
und supported_features listet, etwa tools oder response_format.
reasoning_effort nur schicken, wenn reasoning_efforts nicht leer ist, und nur einen Wert aus dieser Liste.
bashcurl https://api.nodion.ai/v1/chat/completions \
-H "Authorization: Bearer $NODION_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<model>",
"stream": true,
"max_tokens": 512,
"messages": [
{"role": "system", "content": "Answer in one sentence."},
{"role": "user", "content": "What is an embedding?"}
]
}' Was das Gateway mit Request und Antwort macht:
- Ohne
max_tokens(odermax_completion_tokens) setzt das Gatewaymax_tokensaufmax_output_lengthdes Modells. Größere Werte werden darauf gesenkt. - Mit
"stream": trueist die Antwort Server-Sent Events (Zeilendata: {...}, danndata: [DONE]). Das Gateway setztstream_options.include_usage, der letzte Chunk trägt also normalerweise Usage. Bricht die Upstream-Verbindung mitten im Stream, trägt ein letzter Chunk ein Objekterrorundfinish_reason: "error", gefolgt vondata: [DONE]. - Das Feld
modelin der Antwort ist die ID, die du geschickt hast. Reasoning-Text, wenn ein Modell ihn zurückgibt, steht inreasoning_content.
PDFs können inline als file-Content-Block mit einer Base64-Data-URI kommen. Das Gateway rendert die ersten
20 Seiten zu Bildern vor dem Call, das hilft also nur bei Modellen mit Bild-Input. Referenzen auf file_id
werden abgelehnt.
json{
"role": "user",
"content": [
{"type": "text", "text": "Summarize this contract."},
{"type": "file", "file": {"file_data": "data:application/pdf;base64,JVBERi0..."}}
]
}
Abrechnung: Input- und Output-Tokens zum Modellpreis, gecachter Input zum Cache-Preis, wo die Route
ihn meldet. Der Hold zählt jedes Request-Byte als Input-Token, plus max_tokens. Bei Requests
mit Bildern oder PDFs wird der Input-Teil auf die Context-Length des Modells angehoben, oder auf mindestens 128.000 Tokens,
wenn der Request größer als der Context ist. Im Free-Fenster eines Modells
(free_until) sind Chat Completions auf gehosteten Routes kostenlos.
Embeddings
POST /v1/embeddings nimmt den OpenAI-Body (model, input als String oder
Array) und gibt die OpenAI-Embeddings-Antwort zurück. Kein Streaming. Abrechnung über usage.prompt_tokens.
Ein Modell mit kind: "embeddings" nutzen.
bashcurl https://api.nodion.ai/v1/embeddings \
-H "Authorization: Bearer $NODION_AI_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "<embeddings-model>", "input": ["first text", "second text"]}' Rerank
POST /v1/rerank scored documents gegen eine query. Optionales
top_n begrenzt die Ergebnisse. Die Antwort hat results mit index (Position
in documents) und relevance_score, plus usage.prompt_tokens, worüber
abgerechnet wird. Ein Modell mit kind: "rerank" nutzen.
bashcurl https://api.nodion.ai/v1/rerank \
-H "Authorization: Bearer $NODION_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<rerank-model>",
"query": "How do I reset my password?",
"documents": ["Billing FAQ", "Account recovery guide", "Release notes"],
"top_n": 2
}' System One
POST /v1/systemone beantwortet typisierte Fragen zu einem Stück State. Das Modell scored jede
mögliche Antwort statt Text zu schreiben, du bekommst also Wahrscheinlichkeiten zurück, keinen Prosa. Nutz es für Routing,
Triage, Moderation oder als Gate, bevor ein Agent ein Tool ausführt. Ein Call beantwortet bis zu 16 Fragen zum
selben State.
Modelle mit supports_decisions: true auf /v1/models bedienen es. System One läuft nur auf
Nodion-gehosteten Routes, nie auf gerouteten Providern. Der Tab Decisions im Playground hat
fertige Beispiele.
bashcurl https://api.nodion.ai/v1/systemone \
-H "Authorization: Bearer $NODION_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "aleph-alpha/kolibri-1",
"state": {
"customer_tier": "enterprise",
"ticket": "My checkout page shows a blank screen after I click Pay."
},
"questions": {
"is_bug": {
"type": "noul",
"instructions": "Is the customer reporting a software defect?"
},
"team": {
"type": "choice",
"instructions": "Which team should own this ticket?",
"criteria": {
"payments": "Checkout, billing, or payment processing issues.",
"frontend": "Rendering, layout, or browser issues.",
"account": "Login, permissions, or profile issues."
}
},
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": [
"Can wait for the next release",
"Should be fixed this week",
"Blocking revenue right now"
]
}
}
}' Request
model(pflicht): ein Modell mitsupports_decisions.state(pflicht): worum die Fragen gehen. Ein String, Objekt, Array odernull.questions(pflicht): ein Objekt mit 1 bis 16 Einträgen. Der Key ist dein Name für die Frage (bis 128 Zeichen) und kommt als Key inanswerszurück.
Jede Frage hat einen type, optionale instructions und criteria, die
vom Type abhängen. Instructions und Criteria-Werte können String, Objekt oder Array sein;
null ist überall erlaubt außer bei Score-Levels.
noul: eine Ja/Nein-Frage.criteriaist optional und darf nur die Keystrueundfalsehaben. Einnoulbraucht nicht-leereinstructionsoder mindestens ein nicht-leeres Criterion.choice: ein Label wählen.criteriamappt 1 bis 26 Labels auf einen Wert; leere Strings werden abgelehnt. Labels müssen unique sein, ohne Groß/Klein, und bis 256 Zeichen.score: auf einer Skala bewerten.criteriaist ein Array von 2 bis 10 nicht-leeren Levels, niedrigstes zuerst. Level-Indexes starten bei 0.
Unbekannte Felder werden abgelehnt. Der Body darf bis 512 KiB sein, und State plus die größte Frage müssen in den Context des Modells passen.
Response
json{
"model": "aleph-alpha/kolibri-1",
"answers": {
"is_bug": {"type": "noul", "noul": 0.91},
"team": {
"type": "choice",
"choice": "payments",
"confidence": 0.78,
"probabilities": {"payments": 0.82, "frontend": 0.15, "account": 0.03}
},
"urgency": {
"type": "score",
"score": 1.5,
"confidence": 0.6,
"legend": {
"0": "Can wait for the next release",
"1": "Should be fixed this week",
"2": "Blocking revenue right now"
},
"probabilities": {"0": 0.1, "1": 0.3, "2": 0.6}
}
},
"usage": {"input_tokens": 412, "output_tokens": 0}
} noul: die Wahrscheinlichkeit, dass die Antworttrueist, von 0 bis 1.choice:choiceist das wahrscheinlichste Label,probabilitieshat jedes Label und summiert auf 1,confidenceist ein Wert von 0 bis 1.score:scoreist der wahrscheinlichkeitsgewichtete Mittelwert der Level-Indexes (0 bis Anzahl der Levels minus 1).probabilitiesundlegendsind nach Level-Index keyed;legendmappt jeden Index auf eine Level-Beschreibung.confidenceist ein Wert von 0 bis 1.modelist das Modell, das geantwortet hat.usage.output_tokensist immer 0.
Die Werte in der Beispielantwort sind illustrativ.
Abrechnung
Nur Input-Tokens werden berechnet, zum Input-Preis des Modells. Das Modell liest den State einmal pro Frage, also
wächst usage.input_tokens mit der Zahl der Fragen. Vor dem Call hält das Wallet
(Bytes des State + Bytes aller Fragen + 4.096) × die Zahl der Fragen als Input-Tokens,
und der Request wird auf usage.input_tokens abgerechnet, nie über dem Hold. Requests, die scheitern, werden nicht
berechnet; trennst du nach der Antwort des Modells, werden seine Input-Tokens berechnet. Free-Fenster gelten wie
bei Chat.
Fehler
System One nutzt einen eigenen Error-Body: {"detail": "message"}, und bei 422 eine Liste von
Items loc / msg / type, die auf das Feld zeigen.
json{
"detail": [
{"loc": ["body", "questions", "team", "criteria"], "msg": "choice accepts 1 to 26 criteria", "type": "too_long"}
]
} - 401: fehlender oder ungültiger Key.
- 402: Billing hat den Request abgelehnt: Balance, Spend-Limits oder der Request ließ sich nicht preisen. Die Gründe sind die der 402-Codes, hier nur als
detail-Text. - 404:
model not found, auch für Modelle ohnesupports_decisions. - 422: ungültiger Body, Body über 512 KiB, State und Fragen über dem Context, oder das Modell hat den Request abgelehnt.
- 429: ein Key-Limit wurde getroffen.
Retry-After: 5. - 502: das Modell hat nicht geantwortet.
- 503: keine healthy Route, keine die zu den Privacy-Settings des Projekts passt, oder die Settings ließen sich nicht laden.
- 529: jede Route für das Modell ist voll.
Retry-After: 5.
OCR
POST /v1/ocr folgt der Mistral-OCR-Form. Die Datei inline als Base64-Data-URI schicken;
Remote-URLs werden abgelehnt. PDF, PNG, JPEG und WebP gehen.
bashcurl https://api.nodion.ai/v1/ocr \
-H "Authorization: Bearer $NODION_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "mistral/mistral-ocr-4-1",
"document": {
"type": "document_url",
"document_url": "data:application/pdf;base64,JVBERi0..."
}
}' model: ein OCR-Modell aus dem öffentlichen Katalog (kind: "ocr").document:{"type": "document_url", "document_url": "data:..."}oder{"type": "image_url", "image_url": "data:..."}.pages(optional): zu lesende Seiten-Indexes, startend bei 0. Nicht jedes OCR-Modell unterstützt das; gehostete OCR-Modelle undfirecrawl/pdf-inspectorantworten 400.include_image_base64(optional): eingebettete Bilder als Base64 zurückgeben. Nicht jedes OCR-Modell gibt Bilder zurück; manche antworten immer mit einer leeren Listeimages.
Die Antwort hat pages (jede mit index, markdown und
images) und usage_info.pages_processed. Abrechnung pro verarbeiteter Seite. Der Hold deckt
das ganze Dokument, und Dokumente über max_pages des Modells werden abgelehnt.
firecrawl/pdf-inspector liest nur digital erzeugte PDFs. Ein Bild antwortet 422; ein PDF mit
gescannten Seiten antwortet 422 mit code: "pages_need_ocr" und den betroffenen Seiten in
pages_needing_ocr.
Fehler und Limits
Jeder Endpoint außer System One antwortet Fehler im OpenAI-Envelope:
json{
"error": {
"message": "insufficient AI balance. Top up in the AI Billing tab.",
"type": "error",
"code": "empty_balance"
}
} message ist immer da. type und ob code gesetzt ist, variieren je
Endpoint, also zuerst nach HTTP-Status branchen. Chat, Embeddings, Rerank und die Web-Tools legen die
402-Codes in code. Wenn die Route des Modells Chat, Embeddings oder
Rerank mit einem HTTP-Fehler beantwortet, trägt der Body außerdem request_id. Der Header X-Request-ID
ist immer da.
- 400: ungültiges JSON, fehlendes
modeloder ein Modell der falschen Art für den Endpoint (zum Beispiel ein OCR-Modell auf Chat). Ein Body über 25 MiB, der den API-Prozess erreicht, nutztrequest body exceeds 25 MiB. - 401: siehe Authentifizierung.
- 402: das Wallet hat den Request abgelehnt; siehe die Codes unten.
- 404:
model not found, oder ein Endpoint, der nicht existiert. - 413: der öffentliche Host hat einen Body größer als 25 MiB abgelehnt, bevor die API lief.
- 429: ein Key-Limit wurde getroffen, oder das Modell ist überlastet.
Retry-Afterachten, wo es geschickt wird. - 502: die Route des Modells ist fehlgeschlagen. Später retryen.
- 503: keine healthy Route für das Modell, keine die zu den Privacy-Settings des Projekts passt (Tab Settings), oder die Settings ließen sich nicht laden.
402-Codes. Chat, Embeddings, Rerank und die Web-Tools schicken sie in code. OCR, Audio und Bild
schicken nur die Message, System One als detail.
empty_balance: das verfügbare AI-Guthaben deckt den Hold für diesen Request nicht. Im Tab Billing aufladen oder Auto-Top-up einschalten.daily_quota: der heutige Spend auf diesem Key plus offene Holds plus dieser Request würde das tägliche Spend-Limit des Keys überschreiten.month_quota: der Spend dieses Monats plus offene Holds plus dieser Request würde das monatliche Spend-Limit überschreiten, das du im Tab Billing gesetzt hast.usage_limit: der Spend dieses Monats plus offene Holds plus dieser Request würde die monatliche Cap deiner Usage-Tier überschreiten. Der Tab Billing zeigt die Tier und wann die nächste gilt.pricing_unavailableundreserve_failed: der Request ließ sich nicht preisen oder halten. Retryen, dann Support mit der Request-ID kontaktieren.
Default-Limits pro Key:
- 600 Requests pro Minute
- 4.000.000 Tokens pro Minute (Chat, Embeddings, Rerank und System One)
- 20 gleichzeitige Requests
- 25 MiB Request-Body bei Chat, Embeddings, Rerank, OCR, Audio und Bildern. Tools sind 1 MiB. System One ist 512 KiB.
Bei Chat, Embeddings und Rerank schickt ein 429 Retry-After: 5 für die Request-Rate und für
Overload, 10 für die Token-Rate und 2 für Concurrency. System One schickt immer
Retry-After: 5. Eine Voice anzulegen schickt Retry-After, wenn eigene Limits greifen (zu
viele Uploads parallel, oder mehr als zehn Create-Versuche pro Stunde). Andere 429s bei OCR, Audio, Bild, den Web-Tools und
Voices schicken keins; ein paar Sekunden warten, dann retryen. Support kontaktieren, wenn du höhere Limits brauchst.