Referência da API de IA
Todos os endpoints de api.nodion.ai/v1, com limites e erros.
URL base: https://api.nodion.ai/v1. A API segue o formato da OpenAI, pelo que os SDKs da OpenAI funcionam
quando configurados com este URL base. Para as chaves, o saldo e os separadores do dashboard, consulte
AI Inference. Os modelos, fornecedores e preços estão no catálogo de modelos.
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) Autenticação
Envie uma chave de inferência (nodion_ai_…) como bearer token em cada pedido. As chaves da plataforma
(nodion_…) não funcionam aqui. GET /v1/models é a única chamada que não precisa de chave.
httpAuthorization: Bearer nodion_ai_… Uma chave recusada recebe a resposta 401 com uma destas mensagens:
missing bearer tokeninvalid api keyapi key expiredaccount disabledaccount under review
Todas as respostas incluem o cabeçalho X-Request-ID. Indique-o quando contactar o suporte.
Os corpos dos pedidos JSON podem ter até 25 MiB (ferramentas 1 MiB, System One 512 KiB). O base64 acrescenta um terço,
pelo que um ficheiro enviado inline no JSON, como uma imagem, um PDF ou um documento para OCR, pode ter cerca de 18 MiB. Os envios
multipart para /v1/audio/transcriptions e /v1/audio/voices podem ter até 25 MiB, com
ficheiros de transcrição até 20 MiB e ficheiros de amostra de voz até 10 MiB (11 MiB para o formulário
inteiro).
Endpoints
| Endpoint | O que faz | Faturado por |
|---|---|---|
GET /v1/models | Lista os modelos com preço por token | Gratuito |
POST /v1/chat/completions | Chat, ferramentas, saída estruturada | Tokens de entrada e de saída |
POST /v1/responses | OpenAI Responses API, por exemplo para o Codex | Tokens de entrada e de saída |
POST /v1/embeddings | Embeddings vetoriais | Tokens de entrada |
POST /v1/rerank | Ordena documentos em relação a uma consulta | Tokens de entrada |
POST /v1/systemone | System One: decisões tipadas com probabilidades | Tokens de entrada |
POST /v1/ocr | OCR de documentos e imagens | Páginas |
POST /v1/audio/transcriptions | Voz para texto | Segundos de áudio |
GET /v1/audio/transcriptions/realtime (WebSocket) | Voz para texto em tempo real | Segundos de áudio |
POST /v1/audio/speech | Texto para voz | Caracteres |
GET, POST /v1/audio/voices | Lista e cria vozes clonadas | Gratuito |
GET, DELETE /v1/audio/voices/{id} | Lê ou elimina uma voz clonada | Gratuito |
POST /v1/images/generations | Geração de imagens | Imagens |
POST /v1/tools/web_search, web_news, web_fetch, web_images, web_videos, web_places, web_maps, web_shopping, web_lens | Ferramentas web | Chamadas, mais cada página obtida por um web_search |
O áudio, as imagens e as ferramentas estão descritos com exemplos em AI Inference. O resto está abaixo.
Antes de cada chamada, é reservado no saldo o valor máximo possível para o custo do pedido. O valor final é calculado com base na utilização
comunicada, nunca acima da reserva, e o restante é libertado. Se uma resposta bem-sucedida não reportar utilização, é cobrada a
reserva completa. Uma sessão de transcrição em tempo real reserva o max_audio_seconds do modelo (1 800 segundos
se o modelo não definir nenhum), pelo que o saldo tem de cobrir uma sessão completa à partida.
Modelos
GET /v1/models devolve {"object": "list", "data": [...]} e lista modelos de chat,
embeddings e rerank. Os modelos de OCR, voz, imagem e ferramentas não estão incluídos; o catálogo público em
https://api.nodion.com/v2/public/ai/models lista todos os tipos. Campos úteis por modelo:
id: o valor demodelnos pedidos.kind:chat,embeddingsourerank.context_lengthemax_output_lengthem tokens.pricing: USD por token como strings decimais.pricing_eurtem os preços em EUR.supported_sampling_parametersesupported_features(por exemplotools,json_mode,structured_outputs,reasoning).reasoning_efforts: os valores dereasoning_effortque este modelo aceita (por exemplonone,low,high). Vazio quando os níveis não são configuráveis.is_ready:falsesignifica que, neste momento, nenhuma rota está operacional. O modelo continua listado.lifecycle:gaoupreview.serving:hosted(os pesos do modelo correm na Nodion) ourouted(encaminhado para um fornecedor).supports_decisions: o modelo responde ao System One.coding_plan: o Codion pode oferecer este modelo de chat. Sempretrueoufalse. Não corresponde ao plano de programação com IA usado na faturação.free_until: definido enquanto estiver ativo um período gratuito num modelo servido apenas pela Nodion. Os preços por token mostram então 0.
Chat completions
POST /v1/chat/completions aceita o corpo da OpenAI Chat Completions: model,
messages e os campos opcionais que o modelo indica em supported_sampling_parameters
e supported_features, como tools ou response_format.
Envie reasoning_effort apenas quando reasoning_efforts não estiver vazio, e apenas com um valor dessa 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?"}
]
}' O que o gateway faz ao pedido e à resposta:
- Sem
max_tokens(oumax_completion_tokens), o gateway definemax_tokenscom omax_output_lengthdo modelo. Valores superiores são reduzidos a esse limite. - Com
"stream": true, a resposta chega como server-sent events (linhasdata: {...}, depoisdata: [DONE]). O gateway definestream_options.include_usage, pelo que o último chunk inclui normalmente a utilização. Se a ligação upstream cair a meio do stream, um último chunk traz um objetoerrorefinish_reason: "error", seguido dedata: [DONE]. - O campo
modelna resposta é o id enviado no pedido. O texto de raciocínio, quando um modelo o devolve, está emreasoning_content.
Os ficheiros PDF podem ser enviados inline como bloco de conteúdo file com um data URI em base64. Antes da chamada, o gateway
converte as primeiras 20 páginas em imagens, pelo que isto só ajuda em modelos com entrada de imagem. As referências
file_id são recusadas.
json{
"role": "user",
"content": [
{"type": "text", "text": "Summarize this contract."},
{"type": "file", "file": {"file_data": "data:application/pdf;base64,JVBERi0..."}}
]
}
Faturação: tokens de entrada e de saída ao preço do modelo, entrada em cache ao preço de cache quando a rota o
reporta. A reserva conta cada byte do pedido como um token de entrada, mais max_tokens. Em pedidos
com imagens ou PDF, a parte de entrada sobe para o comprimento de contexto do modelo, ou para pelo menos 128 000 tokens
quando o pedido é maior do que o contexto. Durante o período gratuito de um modelo
(free_until), as chat completions em rotas alojadas são gratuitas.
Responses API
POST /v1/responses aceita o corpo da OpenAI Responses API: model, input
(texto ou uma lista de itens) e os campos opcionais 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. O gateway
traduz o pedido para uma chat completion, pelo que tudo o que consta da secção de chat completions também se aplica aqui:
o limite de saída, os reasoning_efforts permitidos, os PDF e a faturação.
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?"
}'
Com "stream": true, a resposta é o stream de eventos da Responses API, como response.created,
response.output_text.delta e response.function_call_arguments.delta, terminando com
response.completed e o respetivo usage. Se o stream for interrompido, o último evento é
response.failed. O texto de raciocínio chega num item reasoning como reasoning_text.
Devolva esse item nos pedidos seguintes: o raciocínio desde a última mensagem do utilizador volta ao modelo,
o raciocínio mais antigo só com reasoning.context: "all_turns".
O gateway executa ele próprio o web_search, através da pesquisa web da Nodion. Quando o
modelo pesquisa, o gateway obtém os resultados, entrega-os ao modelo e volta a chamá-lo. A resposta inclui um
item web_search_call com a consulta e os URL das fontes, transmitido em stream com os eventos
response.web_search_call.in_progress, searching e completed.
Faturação: cada pesquisa como uma chamada a /v1/tools/web_search, cada ronda do modelo como uma chat completion,
e usage é a soma de todas as rondas. Uma Response conta uma vez para o limite de pedidos da chave. No máximo
max_tool_calls pesquisas por Response (10 por omissão, 20 no máximo); max_output_tokens abrange
todas as rondas em conjunto. filters.allowed_domains, user_location (cidade, região, país) e
search_context_size (5, 10 ou 20 resultados) são aplicados. A pesquisa devolve apenas resultados do índice de pesquisa (título,
URL, excerto) e não abre páginas, mesmo com external_web_access: true.
Logprobs: com top_logprobs (até 20) ou include: ["message.output_text.logprobs"],
aparecem em output_text quando o modelo os devolve.
Com esta configuração, o Codex CLI funciona com a Nodion, incluindo a pesquisa web:
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" Diferenças em relação à OpenAI:
- A Nodion não guarda respostas.
storeé ignorado e a resposta indicastore: false. Não existeprevious_response_id,conversation,item_referencenemGET /v1/responses/{id}. Envie a conversa completa eminput, como faz o Codex. - Ferramentas:
function,custom,namespaceeweb_search. Outras ferramentas alojadas, comofile_searchoucode_interpreter, são recusadas com 400. - Os resultados de pesquisa não são guardados. Um
web_search_callna conversa chega ao modelo como a chamada acompanhada de uma nota, sem os resultados antigos.annotations(citações) fica vazio; as fontes estão noweb_search_call. - As imagens e os ficheiros nos resultados das ferramentas não chegam ao modelo; uma nota no texto substitui-os.
- Não suportado (400):
background,prompt,truncation: "auto",file_idefile_url. Envie as imagens comoimage_url(um URL ou data URI) e os PDF comoinput_filecomfile_data.
Embeddings
POST /v1/embeddings aceita o corpo da OpenAI (model, input como string ou
array) e devolve a resposta de embeddings da OpenAI. Sem streaming. Faturado com base em usage.prompt_tokens.
Use um modelo com 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 pontua documents em relação a uma query. O campo opcional
top_n limita os resultados. A resposta tem results com index (posição
em documents) e relevance_score, mais usage.prompt_tokens, que é a base
da faturação. Use um modelo com 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 responde a perguntas tipadas sobre um estado. Em vez de escrever texto, o modelo pontua
cada resposta possível, pelo que recebe probabilidades e não prosa. Use-o para encaminhamento, triagem, moderação ou
como ponto de controlo antes de um agente executar uma ferramenta. Uma chamada responde a até 16 perguntas sobre o
mesmo estado.
Os modelos com supports_decisions: true em /v1/models servem o System One. O System One corre em
rotas alojadas pela Nodion e em fornecedores que oferecem eles próprios o System One. Se uma rota falhar antes de executar o
pedido (rate limit, falha de serviço), o mesmo pedido passa para a rota seguinte. O separador Decisions no
Playground tem exemplos prontos a usar.
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"
]
}
}
}' Pedido
model(obrigatório): um modelo comsupports_decisions.state(obrigatório): aquilo a que as perguntas se referem. Uma string, um objeto, um array ounull.questions(obrigatório): um objeto com 1 a 16 entradas. A chave é o nome que dá à pergunta (até 128 caracteres) e volta como chave emanswers.
Cada pergunta tem um type, instructions opcionais e criteria que
dependem do tipo. Os valores de instruções e critérios podem ser uma string, um objeto ou um array;
null é permitido em todo o lado, exceto nos níveis de score.
noul: uma pergunta de sim/não.criteriaé opcional e só pode ter as chavestrueefalse. Umnoulprecisa deinstructionsnão vazias ou de pelo menos um critério não vazio.choice: escolher uma etiqueta.criteriafaz corresponder 1 a 26 etiquetas a um valor; strings em branco são recusadas. As etiquetas têm de ser únicas, sem distinção entre maiúsculas e minúsculas, e ter até 256 caracteres.score: classificar numa escala.criteriaé um array de 2 a 10 níveis não vazios, do mais baixo para o mais alto. Os índices dos níveis começam em 0.
Os campos desconhecidos são recusados. O corpo pode ter até 512 KiB, e o estado mais a maior pergunta têm de caber no contexto do modelo.
Resposta
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: a probabilidade de a resposta sertrue, de 0 a 1.choice:choiceé a etiqueta mais provável,probabilitiestem todas as etiquetas e soma 1, econfidenceé um valor de 0 a 1.score:scoreé a média dos índices dos níveis ponderada pelas probabilidades (de 0 até ao número de níveis menos 1).probabilitieselegendtêm como chave o índice do nível;legendfaz corresponder cada índice a uma descrição de nível.confidenceé um valor de 0 a 1.modelé o modelo que respondeu.usage.output_tokensé sempre 0.
Os valores da resposta de exemplo são ilustrativos.
Faturação
Apenas os tokens de entrada são faturados, ao preço de entrada do modelo. O modelo lê o estado uma vez por pergunta, pelo que
usage.input_tokens cresce com o número de perguntas. Antes da chamada, o saldo reserva
(bytes do estado + bytes de todas as perguntas + 4 096) × o número de perguntas como tokens de entrada,
e o pedido é liquidado com base em usage.input_tokens, nunca acima da reserva. Os pedidos que falham não são
faturados; se fechar a ligação depois de o modelo ter respondido, os tokens de entrada são faturados. Os períodos gratuitos
aplicam-se como no chat.
Erros
O System One usa um formato de erro próprio: {"detail": "message"} e, para 422, uma lista de
itens loc / msg / type que indicam o campo.
json{
"detail": [
{"loc": ["body", "questions", "team", "criteria"], "msg": "choice accepts 1 to 26 criteria", "type": "too_long"}
]
} - 401: chave em falta ou inválida.
- 402: a faturação recusou o pedido: saldo, limites de gastos, ou não foi possível calcular o preço do pedido. Os motivos são os dos códigos 402, aqui apenas como texto em
detail. - 404:
model not found, também para modelos semsupports_decisions. - 422: corpo inválido, corpo acima de 512 KiB, estado e perguntas acima do contexto, ou o modelo recusou o pedido.
- 429: foi atingido um limite da chave (
Retry-After: 5), ou todas as rotas de fornecedor tentadas atingiram o rate limit (oRetry-Afterdo fornecedor, no máximo 60 segundos). - 502: o modelo não conseguiu responder.
- 503: nenhuma rota operacional, nenhuma que corresponda às definições de privacidade do projeto, ou não foi possível carregar as definições.
- 529: todas as rotas do modelo estão no limite da capacidade.
Retry-After: 5.
OCR
POST /v1/ocr segue o formato do Mistral OCR. Envie o ficheiro inline como data URI em base64;
os URL remotos são recusados. Funcionam 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: um modelo de OCR do catálogo público (kind: "ocr").document:{"type": "document_url", "document_url": "data:..."}ou{"type": "image_url", "image_url": "data:..."}.pages(opcional): índices das páginas a ler, a começar em 0. Nem todos os modelos de OCR o suportam; os modelos de OCR alojados efirecrawl/pdf-inspectorrespondem 400.include_image_base64(opcional): devolve as imagens incorporadas em base64. Nem todos os modelos de OCR devolvem imagens; alguns respondem sempre com uma listaimagesvazia.
A resposta tem pages (cada uma com index, markdown e
images) e usage_info.pages_processed. Faturado por página processada. A reserva cobre
o documento inteiro, e os documentos acima do max_pages do modelo são recusados.
firecrawl/pdf-inspector só lê PDF gerados digitalmente. Uma imagem recebe 422; um PDF com páginas
digitalizadas recebe 422 com code: "pages_need_ocr" e as páginas afetadas em
pages_needing_ocr.
Erros e limites
Todos os endpoints, exceto o System One, devolvem os erros no envelope da OpenAI:
json{
"error": {
"message": "insufficient AI balance. Top up in the AI Billing tab.",
"type": "error",
"code": "empty_balance"
}
} message está sempre presente. O valor de type e a presença de code variam consoante o
endpoint. Por isso, verifique primeiro o código de estado HTTP. Chat, embeddings, rerank e as ferramentas web colocam os
códigos 402 em code. Quando a rota do modelo responde a chat, embeddings ou
rerank com um erro HTTP, o corpo inclui também request_id. O cabeçalho X-Request-ID
está sempre presente.
- 400: JSON inválido,
modelem falta, ou um modelo do tipo errado para o endpoint (por exemplo, um modelo de OCR no chat). Um corpo acima de 25 MiB que chegue ao processo da API receberequest body exceeds 25 MiB. - 401: consulte Autenticação.
- 402: o saldo recusou o pedido; consulte os códigos abaixo.
- 404:
model not found, ou um endpoint que não existe. - 413: o host público recusou um corpo acima de 25 MiB antes de a API ser executada.
- 429: foi atingido um limite da chave, ou o modelo está sobrecarregado. Respeite o
Retry-Afterquando for enviado. - 502: a rota do modelo falhou. Tente novamente mais tarde.
- 503: nenhuma rota operacional para o modelo, nenhuma que corresponda às definições de privacidade do projeto (separador Settings), ou não foi possível carregar as definições.
Códigos 402: chat, embeddings, rerank e as ferramentas web enviam-nos em code. OCR, áudio e imagens
enviam apenas a mensagem, e o System One envia-a como detail.
empty_balance: o saldo de IA disponível não cobre a reserva deste pedido. Carregue o saldo no separador Billing ou ative o carregamento automático.daily_quota: os gastos de hoje nesta chave, mais as suas reservas em aberto, mais este pedido ultrapassariam o limite diário de gastos da chave.month_quota: os gastos deste mês, mais as reservas em aberto, mais este pedido ultrapassariam o limite mensal de gastos definido no separador Billing.usage_limit: os gastos deste mês, mais as reservas em aberto, mais este pedido ultrapassariam o teto mensal do seu nível de utilização (usage tier). O separador Billing mostra o nível e quando se aplica o seguinte.pricing_unavailableereserve_failed: não foi possível calcular o preço do pedido ou fazer a reserva. Tente novamente e, depois, contacte o suporte com o id do pedido.
Limites por chave definidos por omissão:
- 600 pedidos por minuto
- 4 000 000 tokens por minuto (chat, embeddings, rerank e System One)
- 20 pedidos em simultâneo
- 25 MiB de corpo de pedido em chat, embeddings, rerank, OCR, áudio e imagens. Ferramentas: 1 MiB. System One: 512 KiB.
Em chat, embeddings e rerank, um 429 envia Retry-After: 5 para a taxa de pedidos e para
sobrecarga, 10 para a taxa de tokens e 2 para a concorrência. O System One envia sempre
Retry-After: 5. A criação de uma voz envia Retry-After quando atinge os seus próprios limites (demasiados
uploads em curso, ou mais de dez tentativas de criação por hora). As restantes respostas 429 em OCR, áudio, imagens, ferramentas web e
vozes não o enviam; aguarde alguns segundos antes de tentar novamente. Contacte o suporte se precisar de limites mais altos.