Riferimento dell'API AI

Tutti gli endpoint su api.nodion.ai/v1, con limiti ed errori.

URL di base: https://api.nodion.ai/v1. L'API segue il formato OpenAI, quindi gli SDK di OpenAI funzionano se li configuri con questo URL di base. Per chiavi, credito prepagato e schede della dashboard vedi AI Inference. Modelli, provider e prezzi sono nel catalogo dei modelli.

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)

Autenticazione

Invia una chiave di inferenza (nodion_ai_…) come bearer token in ogni richiesta. Le chiavi della piattaforma (nodion_…) qui non funzionano. GET /v1/models è l'unica chiamata che non richiede una chiave.

httpAuthorization: Bearer nodion_ai_…

Se la chiave viene rifiutata, la risposta è 401 con uno di questi messaggi:

  • missing bearer token
  • invalid api key
  • api key expired
  • account disabled
  • account under review

Ogni risposta contiene un header X-Request-ID. Indicalo quando contatti il supporto.

I body JSON delle richieste possono arrivare a 25 MiB (tool 1 MiB, System One 512 KiB). Base64 aggiunge un terzo, quindi un file inviato inline nel JSON, come un'immagine, un PDF o un documento OCR, può pesare circa 18 MiB. Gli upload multipart verso /v1/audio/transcriptions e /v1/audio/voices possono arrivare a 25 MiB, con file di trascrizione fino a 20 MiB e file di campioni vocali fino a 10 MiB (11 MiB per l'intero form).

Endpoint

Endpoint Cosa fa Addebito per
GET /v1/modelsElenca i modelli con prezzo a tokenGratis
POST /v1/chat/completionsChat, tool, output strutturatoToken di input e di output
POST /v1/responsesOpenAI Responses API, ad esempio per CodexToken di input e di output
POST /v1/embeddingsEmbedding vettorialiToken di input
POST /v1/rerankOrdina documenti in base a una queryToken di input
POST /v1/systemoneSystem One: decisioni tipizzate con probabilitàToken di input
POST /v1/ocrOCR di documenti e immaginiPagine
POST /v1/audio/transcriptionsDa voce a testoSecondi di audio
GET /v1/audio/transcriptions/realtime (WebSocket)Da voce a testo in tempo realeSecondi di audio
POST /v1/audio/speechDa testo a voceCaratteri
GET, POST /v1/audio/voicesElenca e crea voci clonateGratis
GET, DELETE /v1/audio/voices/{id}Legge o elimina una voce clonataGratis
POST /v1/images/generationsGenerazione di immaginiImmagini
POST /v1/tools/web_search, web_news, web_fetch, web_images, web_videos, web_places, web_maps, web_shopping, web_lensTool webChiamate, più ogni pagina scaricata da un web_search

Audio, immagini e tool sono descritti con esempi in AI Inference. Il resto è qui sotto.

Prima di ogni chiamata viene riservato sul credito l'importo massimo previsto per la richiesta. Il costo viene poi calcolato in base all'utilizzo riportato, mai oltre l'importo riservato, e il resto viene liberato. Se una risposta andata a buon fine non riporta l'utilizzo, viene addebitato l'intero importo riservato. Una sessione di trascrizione in tempo reale riserva il max_audio_seconds del modello (1.800 secondi se il modello non lo imposta), quindi il credito deve coprire in anticipo una sessione intera.

Modelli

GET /v1/models restituisce {"object": "list", "data": [...]} ed elenca i modelli chat, embeddings e rerank. I modelli OCR, vocali, di immagini e i tool non ci sono; il catalogo pubblico su https://api.nodion.com/v2/public/ai/models elenca tutti i tipi. Campi utili per ogni modello:

  • id: il valore per model nelle richieste.
  • kind: chat, embeddings o rerank.
  • context_length e max_output_length in token.
  • pricing: USD per token come stringhe decimali. pricing_eur contiene i prezzi in EUR.
  • supported_sampling_parameters e supported_features (ad esempio tools, json_mode, structured_outputs, reasoning).
  • reasoning_efforts: i valori di reasoning_effort che questo modello accetta (ad esempio none, low, high). Vuoto quando i livelli non sono configurabili.
  • is_ready: false significa che al momento nessuna route è funzionante. Il modello resta in elenco.
  • lifecycle: ga o preview. serving: hosted (i pesi girano su Nodion) o routed (inoltrato a un provider).
  • supports_decisions: il modello risponde a System One.
  • coding_plan: Codion può offrire questo modello chat. Sempre true o false. Non è il coding plan della fatturazione.
  • free_until: presente durante il periodo gratuito di un modello servito solo da Nodion. In quel periodo i prezzi dei token risultano 0.

Chat completions

POST /v1/chat/completions accetta il body di OpenAI Chat Completions: model, messages e i campi facoltativi che il modello elenca in supported_sampling_parameters e supported_features, come tools o response_format. Invia reasoning_effort solo quando reasoning_efforts non è vuoto, e solo con un valore di quella lista.

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?"}
    ]
  }'

Cosa fa il gateway con la richiesta e la risposta:

  • Senza max_tokens (o max_completion_tokens) il gateway imposta max_tokens al max_output_length del modello. I valori più alti vengono ridotti a quel limite.
  • Con "stream": true la risposta arriva come server-sent events (righe data: {...}, poi data: [DONE]). Il gateway imposta stream_options.include_usage, quindi di norma l'ultimo chunk contiene l'utilizzo. Se la connessione upstream si interrompe a metà stream, un ultimo chunk contiene un oggetto error e finish_reason: "error", seguito da data: [DONE].
  • Il campo model nella risposta è l'id che hai inviato. Il testo di reasoning, quando un modello lo restituisce, si trova in reasoning_content.

Puoi inviare i PDF direttamente nella richiesta come blocchi di contenuto file con una data URI in base64. Il gateway converte le prime 20 pagine in immagini prima della chiamata, quindi serve solo con i modelli che accettano immagini in input. I riferimenti file_id vengono rifiutati.

json{
  "role": "user",
  "content": [
    {"type": "text", "text": "Summarize this contract."},
    {"type": "file", "file": {"file_data": "data:application/pdf;base64,JVBERi0..."}}
  ]
}

Addebito: token di input e di output al prezzo del modello, input in cache al relativo prezzo dove la route lo riporta. L'importo riservato conta ogni byte della richiesta come un token di input, più max_tokens. Per le richieste con immagini o PDF la parte di input viene portata alla context length del modello, o ad almeno 128.000 token se la richiesta supera il contesto. Durante la finestra gratuita di un modello (free_until), le chat completions sulle route ospitate sono gratuite.

Responses API

POST /v1/responses accetta il body della OpenAI Responses API: model, input (testo o una lista di item) e i campi facoltativi instructions, tools, tool_choice, parallel_tool_calls, text.format, reasoning.effort, max_output_tokens, max_tool_calls, temperature, top_p, top_logprobs, include e stream. Il gateway traduce la richiesta in una chat completion, quindi valgono anche qui le regole della sezione chat completions: il limite di output, i reasoning_efforts consentiti, i PDF e l'addebito.

bashcurl https://api.nodion.ai/v1/responses \
  -H "Authorization: Bearer $NODION_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "instructions": "Answer in one sentence.",
    "input": "What is an embedding?"
  }'

Con "stream": true la risposta è lo stream di eventi della Responses API, come response.created, response.output_text.delta e response.function_call_arguments.delta, che termina con response.completed e il relativo usage. Se lo stream si interrompe, l'ultimo evento è response.failed. Il testo di reasoning arriva in un item reasoning come reasoning_text. Rimanda quell'item nelle richieste successive: il reasoning dall'ultimo messaggio dell'utente torna al modello, quello più vecchio solo con reasoning.context: "all_turns".

Il gateway esegue web_search da solo, tramite la ricerca web di Nodion. Quando il modello cerca, il gateway recupera i risultati, li passa al modello e lo richiama. La risposta contiene un item web_search_call con la query e gli URL delle fonti, trasmesso in streaming con gli eventi response.web_search_call.in_progress, searching e completed. Addebito: ogni ricerca come una chiamata a /v1/tools/web_search, ogni passaggio del modello come una chat completion, e usage è la somma di tutti i giri. Una Response conta una sola volta per il limite di richieste della chiave. Al massimo max_tool_calls ricerche per Response (valore predefinito 10, massimo 20); max_output_tokens vale per tutti i giri insieme. filters.allowed_domains, user_location (città, regione, paese) e search_context_size (5, 10 o 20 risultati) vengono applicati. La ricerca restituisce solo risultati dell'indice di ricerca (titolo, URL, snippet) e non apre pagine, nemmeno con external_web_access: true.

Le logprob sono disponibili in output_text con top_logprobs (fino a 20) o include: ["message.output_text.logprobs"], se il modello le restituisce.

Con questa configurazione Codex CLI funziona con Nodion, ricerca web inclusa:

toml# ~/.codex/config.toml
model = "<model>"
model_provider = "nodion"

[model_providers.nodion]
name = "Nodion"
base_url = "https://api.nodion.ai/v1"
env_key = "NODION_AI_KEY"
wire_api = "responses"

Cosa cambia rispetto a OpenAI:

  • Nodion non salva le risposte. store viene ignorato e la risposta riporta store: false. Non esistono previous_response_id, conversation, item_reference né GET /v1/responses/{id}. Invia l'intera conversazione in input, come fa Codex.
  • Tool: function, custom, namespace e web_search. Gli altri tool ospitati, come file_search o code_interpreter, vengono rifiutati con 400.
  • I risultati della ricerca non vengono salvati. Un web_search_call nella conversazione arriva al modello come chiamata con una nota, non con i vecchi risultati. annotations (citazioni) resta vuoto; le fonti sono nel web_search_call.
  • Immagini e file negli output dei tool non arrivano al modello; al loro posto c'è una nota nel testo.
  • Non supportati (400): background, prompt, truncation: "auto", file_id e file_url. Invia le immagini come image_url (un URL o una data URI) e i PDF come input_file con file_data.

Embeddings

POST /v1/embeddings accetta il body di OpenAI (model, input come stringa o array) e restituisce una risposta per gli embeddings nel formato OpenAI. Niente streaming. Addebito su usage.prompt_tokens. Usa un modello con kind: "embeddings".

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 assegna un punteggio ai documents rispetto a una query. Il parametro facoltativo top_n limita i risultati. La risposta contiene results con index (posizione in documents) e relevance_score, più usage.prompt_tokens, su cui si basa l'addebito. Usa un modello con kind: "rerank".

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 risponde a domande tipizzate su un insieme di dati (lo stato). Il modello assegna un punteggio a ogni risposta possibile invece di scrivere testo, quindi ricevi probabilità, non prosa. Usalo per routing, triage, moderazione o come controllo prima che un agente esegua un tool. Una chiamata risponde fino a 16 domande sullo stesso stato.

System One è disponibile per i modelli con supports_decisions: true su /v1/models. Gira su route ospitate da Nodion e presso i provider che offrono System One direttamente. Se una route fallisce prima di aver eseguito la richiesta (rate limit, disservizio), la stessa richiesta passa alla route successiva. La scheda Decisions nel Playground contiene esempi pronti.

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"
        ]
      }
    }
  }'

Richiesta

  • model (obbligatorio): un modello con supports_decisions.
  • state (obbligatorio): ciò su cui vertono le domande. Una stringa, un oggetto, un array o null.
  • questions (obbligatorio): un oggetto con da 1 a 16 voci. La chiave è il nome che dai alla domanda (fino a 128 caratteri) e torna come chiave in answers.

Ogni domanda ha un type, delle instructions facoltative e dei criteria che dipendono dal tipo. I valori di instructions e criteria possono essere una stringa, un oggetto o un array; null è ammesso ovunque tranne che nei livelli di score.

  • noul: una domanda sì/no. criteria è facoltativo e può avere solo le chiavi true e false. Un noul richiede instructions non vuote o almeno un criterio non vuoto.
  • choice: scegli un'etichetta. criteria associa da 1 a 26 etichette a un valore; le stringhe vuote vengono rifiutate. Le etichette devono essere univoche, senza distinzione tra maiuscole e minuscole, e lunghe al massimo 256 caratteri.
  • score: valuta su una scala. criteria è un array da 2 a 10 livelli non vuoti, dal più basso al più alto. Gli indici dei livelli partono da 0.

I campi sconosciuti vengono rifiutati. Il body può arrivare a 512 KiB, e lo stato più la domanda più grande devono rientrare nel contesto del modello.

Risposta

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: la probabilità che la risposta sia true, da 0 a 1.
  • choice: choice è l'etichetta più probabile, probabilities contiene ogni etichetta e somma a 1, e confidence è un valore da 0 a 1.
  • score: score è la media degli indici dei livelli ponderata per probabilità (da 0 al numero di livelli meno 1). probabilities e legend hanno come chiave l'indice del livello; legend associa ogni indice alla descrizione di un livello. confidence è un valore da 0 a 1.
  • model è il modello che ha risposto. usage.output_tokens è sempre 0.

I valori nella risposta di esempio sono illustrativi.

Addebito

Vengono addebitati solo i token di input, al prezzo di input del modello. Il modello legge lo stato una volta per ogni domanda, quindi usage.input_tokens cresce con il numero di domande. Prima della chiamata viene riservato sul credito (byte dello stato + byte di tutte le domande + 4.096) × il numero di domande come token di input, e la richiesta viene addebitata su usage.input_tokens, mai oltre l'importo riservato. Le richieste che falliscono non vengono addebitate; se ti disconnetti dopo che il modello ha risposto, i suoi token di input vengono addebitati. Le finestre gratuite valgono come per la chat.

Errori

System One usa un proprio body di errore: {"detail": "message"} e, per il 422, una lista di item loc / msg / type che indicano il campo.

json{
  "detail": [
    {"loc": ["body", "questions", "team", "criteria"], "msg": "choice accepts 1 to 26 criteria", "type": "too_long"}
  ]
}
  • 401: chiave mancante o non valida.
  • 402: la fatturazione ha rifiutato la richiesta per saldo, limiti di spesa, o perché non è stato possibile calcolare il prezzo della richiesta. I motivi sono quelli dei codici 402, qui solo come testo in detail.
  • 404: model not found, anche per i modelli senza supports_decisions.
  • 422: body non valido, body oltre 512 KiB, stato e domande oltre il contesto, oppure il modello ha rifiutato la richiesta.
  • 429: è stato raggiunto un limite della chiave (Retry-After: 5), oppure tutte le route dei provider tentate hanno raggiunto il rate limit (Retry-After del provider, al massimo 60 secondi).
  • 502: il modello non è riuscito a rispondere.
  • 503: nessuna route funzionante, nessuna compatibile con le impostazioni privacy del progetto, oppure non è stato possibile caricare le impostazioni.
  • 529: tutte le route del modello sono al limite di capacità. Retry-After: 5.

OCR

POST /v1/ocr segue il formato Mistral OCR. Invia il file inline come data URI in base64; gli URL remoti vengono rifiutati. Sono supportati PDF, PNG, JPEG e WebP.

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: un modello OCR del catalogo pubblico (kind: "ocr").
  • document: {"type": "document_url", "document_url": "data:..."} o {"type": "image_url", "image_url": "data:..."}.
  • pages (facoltativo): gli indici delle pagine da leggere, a partire da 0. Non tutti i modelli OCR lo supportano; i modelli OCR ospitati e firecrawl/pdf-inspector restituiscono un errore 400.
  • include_image_base64 (facoltativo): restituisce le immagini incorporate in base64. Non tutti i modelli OCR restituiscono immagini; alcuni rispondono sempre con una lista images vuota.

La risposta contiene pages (ognuna con index, markdown e images) e usage_info.pages_processed. Addebito per pagina elaborata. L'importo riservato copre l'intero documento, e i documenti oltre il max_pages del modello vengono rifiutati. firecrawl/pdf-inspector legge solo PDF generati digitalmente. Per un'immagine restituisce un errore 422; per un PDF con pagine scansionate restituisce un errore 422 con code: "pages_need_ocr" e le pagine interessate in pages_needing_ocr.

Errori e limiti

Tutti gli endpoint tranne System One restituiscono gli errori nell'envelope di OpenAI:

json{
  "error": {
    "message": "insufficient AI balance. Top up in the AI Billing tab.",
    "type": "error",
    "code": "empty_balance"
  }
}

message c'è sempre. type, e se code è impostato, variano da endpoint a endpoint, quindi gestisci prima lo stato HTTP. Chat, embeddings, rerank e i tool web mettono i codici 402 in code. Quando la route del modello risponde a chat, embeddings o rerank con un errore HTTP, il body contiene anche request_id. L'header X-Request-ID c'è sempre.

  • 400: JSON non valido, model mancante o un modello del tipo sbagliato per l'endpoint (ad esempio un modello OCR su chat). Un body oltre 25 MiB che arriva al processo dell'API usa request body exceeds 25 MiB.
  • 401: vedi Autenticazione.
  • 402: la richiesta è stata rifiutata per un problema con il credito; vedi i codici qui sotto.
  • 404: model not found, oppure un endpoint che non esiste.
  • 413: l'host pubblico ha rifiutato un body più grande di 25 MiB prima che l'API venisse eseguita.
  • 429: è stato raggiunto un limite della chiave, oppure il modello è sovraccarico. Rispetta Retry-After quando viene inviato.
  • 502: la route del modello ha restituito un errore. Riprova più tardi.
  • 503: nessuna route funzionante per il modello, nessuna compatibile con le impostazioni privacy del progetto (scheda Settings), oppure non è stato possibile caricare le impostazioni.

Codici 402. Chat, embeddings, rerank e i tool web li inviano in code. OCR, audio e immagini inviano solo il messaggio, System One lo invia come detail.

  • empty_balance: il saldo AI disponibile non copre l'importo da riservare per questa richiesta. Ricarica nella scheda Billing o attiva la ricarica automatica.
  • daily_quota: la spesa di oggi su questa chiave, più i suoi importi riservati aperti, più questa richiesta supererebbe il limite di spesa giornaliero della chiave.
  • month_quota: la spesa di questo mese, più gli importi riservati aperti, più questa richiesta supererebbe il limite di spesa mensile che hai impostato nella scheda Billing.
  • usage_limit: la spesa di questo mese, più gli importi riservati aperti, più questa richiesta supererebbe il tetto mensile del tuo livello di utilizzo. La scheda Billing mostra il livello e quando si applica il successivo.
  • pricing_unavailable e reserve_failed: non è stato possibile calcolare il prezzo della richiesta o riservare l'importo. Riprova, poi contatta il supporto indicando l'id della richiesta.

Limiti predefiniti per chiave:

  • 600 richieste al minuto
  • 4.000.000 di token al minuto (chat, embeddings, rerank e System One)
  • 20 richieste simultanee
  • 25 MiB di body della richiesta per chat, embeddings, rerank, OCR, audio e immagini. Per i tool è 1 MiB. Per System One è 512 KiB.

Per chat, embeddings e rerank, una risposta 429 include Retry-After: 5 per la frequenza delle richieste e per il sovraccarico, 10 per la frequenza dei token e 2 per la concorrenza. System One invia sempre Retry-After: 5. La creazione di una voce invia Retry-After quando scattano i suoi limiti (troppi upload in corso, o più di dieci tentativi di creazione all'ora). Gli altri 429 su OCR, audio, immagini, tool web e voci non lo inviano; aspetta qualche secondo prima di riprovare. Contatta il supporto se ti servono limiti più alti.

Dai al tuo agente un cloud tutto suo.

Fino a 15 € di credito quando ti registri.

Continua con GitHub

oppure con l'email

Resta aggiornato.

Novità sul prodotto, niente spam. Puoi annullare l'iscrizione quando vuoi.