Referencia de la API de IA
Todos los endpoints de api.nodion.ai/v1, con límites y errores.
URL base: https://api.nodion.ai/v1. La API sigue el formato de OpenAI, así que los SDK de OpenAI funcionan
si los apuntas a esta URL base. Para las claves, el saldo y las pestañas del dashboard, consulta
AI Inference. Los modelos, proveedores y precios están en el 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) Autenticación
Envía una clave de inferencia (nodion_ai_…) como bearer token en cada petición. Las claves de la plataforma
(nodion_…) no funcionan aquí. GET /v1/models es la única llamada que no necesita clave.
httpAuthorization: Bearer nodion_ai_… Si la clave se rechaza, la respuesta es 401 con uno de estos mensajes:
missing bearer tokeninvalid api keyapi key expiredaccount disabledaccount under review
Cada respuesta lleva una cabecera X-Request-ID. Indícala cuando contactes con soporte.
Los cuerpos JSON de las peticiones pueden ocupar hasta 25 MiB (herramientas 1 MiB, System One 512 KiB). Base64 añade un tercio, así que un archivo enviado
inline en el JSON, como una imagen, un PDF o un documento OCR, puede ocupar unos 18 MiB. Las subidas multipart a
/v1/audio/transcriptions y /v1/audio/voices pueden ocupar hasta 25 MiB, con
archivos de transcripción de hasta 20 MiB y archivos de muestra de voz de hasta 10 MiB (11 MiB para todo el
formulario).
Endpoints
| Endpoint | Qué hace | Se factura por |
|---|---|---|
GET /v1/models | Lista los modelos con precio por token | Gratis |
POST /v1/chat/completions | Chat, herramientas, salida estructurada | Tokens de entrada y de salida |
POST /v1/responses | OpenAI Responses API, por ejemplo para Codex | Tokens de entrada y de salida |
POST /v1/embeddings | Embeddings vectoriales | Tokens de entrada |
POST /v1/rerank | Ordena documentos según una consulta | Tokens de entrada |
POST /v1/systemone | System One: decisiones tipadas con probabilidades | Tokens de entrada |
POST /v1/ocr | OCR de documentos e imágenes | Páginas |
POST /v1/audio/transcriptions | Voz a texto | Segundos de audio |
GET /v1/audio/transcriptions/realtime (WebSocket) | Voz a texto en tiempo real | Segundos de audio |
POST /v1/audio/speech | Texto a voz | Caracteres |
GET, POST /v1/audio/voices | Lista y crea voces clonadas | Gratis |
GET, DELETE /v1/audio/voices/{id} | Lee o elimina una voz clonada | Gratis |
POST /v1/images/generations | Generación de imágenes | Imágenes |
POST /v1/tools/web_search, web_news, web_fetch, web_images, web_videos, web_places, web_maps, web_shopping, web_lens | Herramientas web | Llamadas, más cada página que descarga un web_search |
Audio, imágenes y herramientas se describen con ejemplos en AI Inference. El resto está a continuación.
Antes de cada llamada, se reserva del saldo un importe que cubre el coste máximo de la petición. Después, se liquida según el uso indicado,
nunca por encima de la reserva, y el resto se libera. Si una respuesta correcta no indica el uso, se cobra la reserva
completa. Una sesión de transcripción en tiempo real reserva el max_audio_seconds del modelo (1.800 segundos
si el modelo no lo define), así que el saldo tiene que cubrir una sesión completa por adelantado.
Modelos
GET /v1/models devuelve {"object": "list", "data": [...]} y lista los modelos de chat,
embeddings y rerank. Los modelos de OCR, voz, imagen y herramientas no aparecen; el catálogo
público en https://api.nodion.com/v2/public/ai/models lista todos los tipos. Campos útiles de cada modelo:
id: el valor demodelen las peticiones.kind:chat,embeddingsorerank.context_lengthymax_output_lengthen tokens.pricing: precios en USD por token expresados como cadenas decimales.pricing_eurtiene los precios en EUR.supported_sampling_parametersysupported_features(por ejemplotools,json_mode,structured_outputs,reasoning).reasoning_efforts: los valores dereasoning_effortque acepta este modelo (por ejemplonone,low,high). Vacío cuando los niveles no son configurables.is_ready:falsesignifica que ahora mismo ninguna ruta está operativa. El modelo sigue en la lista.lifecycle:gaopreview.serving:hosted(los pesos se ejecutan en Nodion) orouted(reenviado a un proveedor).supports_decisions: el modelo responde a System One.coding_plan: Codion puede ofrecer este modelo de chat. Siempretrueofalse. No es el coding plan de facturación.free_until: presente mientras hay una ventana gratuita activa en un modelo servido solo por Nodion. Durante ese tiempo, los precios por token son 0.
Chat completions
POST /v1/chat/completions acepta el cuerpo de OpenAI Chat Completions: model,
messages y los campos opcionales que el modelo lista en supported_sampling_parameters
y supported_features, como tools o response_format.
Envía reasoning_effort solo cuando reasoning_efforts no esté vacío, y solo con un valor de esa 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?"}
]
}' Qué hace el gateway con la petición y la respuesta:
- Sin
max_tokens(omax_completion_tokens), el gateway fijamax_tokensen elmax_output_lengthdel modelo. Los valores mayores se reducen a ese límite. - Con
"stream": true, la respuesta llega como server-sent events (líneasdata: {...}y despuésdata: [DONE]). El gateway activastream_options.include_usage, así que normalmente el último chunk incluye el uso. Si la conexión upstream se corta a mitad del stream, un último chunk lleva un objetoerroryfinish_reason: "error", seguido dedata: [DONE]. - El campo
modelde la respuesta es el id que enviaste. El texto de reasoning, cuando un modelo lo devuelve, está enreasoning_content.
Los PDF se pueden enviar inline como bloque de contenido file con una data URI en base64. El gateway convierte las primeras
20 páginas en imágenes antes de la llamada, así que esto solo resulta útil con modelos que aceptan imágenes como entrada. Las referencias
a file_id se rechazan.
json{
"role": "user",
"content": [
{"type": "text", "text": "Summarize this contract."},
{"type": "file", "file": {"file_data": "data:application/pdf;base64,JVBERi0..."}}
]
}
Facturación: tokens de entrada y de salida al precio del modelo, y la entrada en caché al precio de caché cuando la ruta
lo reporta. La reserva cuenta cada byte de la petición como un token de entrada, más max_tokens. En peticiones
con imágenes o PDF, la parte de entrada se eleva a la longitud de contexto del modelo, o al menos a 128.000 tokens
si la petición es mayor que el contexto. Dentro de la ventana gratuita de un modelo
(free_until), las chat completions en rutas alojadas son gratuitas.
Responses API
POST /v1/responses acepta el cuerpo de la OpenAI Responses API: model, input
(texto o una lista de elementos) y los campos opcionales instructions, tools,
tool_choice, parallel_tool_calls, text.format, reasoning.effort,
max_output_tokens, max_tool_calls, temperature, top_p,
top_logprobs, include y stream. El gateway
traduce la petición a una chat completion, así que todo lo de la sección de chat completions también se aplica aquí:
el límite de salida, los reasoning_efforts permitidos, los PDF y la facturación.
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 respuesta es el stream de eventos de la Responses API, como response.created,
response.output_text.delta y response.function_call_arguments.delta, y termina con
response.completed y su usage. Si el stream se corta, el último evento es
response.failed. El texto de razonamiento llega en un elemento reasoning como reasoning_text.
Devuelve ese elemento en las peticiones siguientes: el razonamiento desde el último mensaje del usuario vuelve al modelo;
el más antiguo, solo con reasoning.context: "all_turns".
El gateway ejecuta web_search por sí mismo, mediante la búsqueda web de Nodion. Cuando el
modelo busca, el gateway obtiene los resultados, se los pasa al modelo y lo vuelve a llamar. La respuesta incluye un
elemento web_search_call con la consulta y las URL de las fuentes, emitido en streaming con los eventos
response.web_search_call.in_progress, searching y completed.
Facturación: cada búsqueda como una llamada a /v1/tools/web_search, cada ronda del modelo como una chat completion,
y usage es la suma de todas las rondas. Una Response cuenta una sola vez para el límite de peticiones de la clave. Como máximo
max_tool_calls búsquedas por Response (10 por defecto, 20 como máximo); max_output_tokens cubre
todas las rondas juntas. Se aplican filters.allowed_domains, user_location (ciudad, región, país) y
search_context_size (5, 10 o 20 resultados). La búsqueda solo devuelve resultados del índice de búsqueda (título,
URL, snippet) y no abre ninguna página, tampoco con external_web_access: true.
Logprobs: con top_logprobs (hasta 20) o include: ["message.output_text.logprobs"]
aparecen en output_text cuando el modelo los devuelve.
Con esta configuración, Codex CLI funciona con Nodion, búsqueda web incluida:
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" Diferencias con OpenAI:
- Nodion no guarda respuestas.
storese ignora y la respuesta indicastore: false. No existenprevious_response_id,conversation,item_referenceniGET /v1/responses/{id}. Envía la conversación completa eninput, como hace Codex. - Herramientas:
function,custom,namespaceyweb_search. Otras herramientas alojadas, comofile_searchocode_interpreter, se rechazan con 400. - Los resultados de búsqueda no se guardan. Un
web_search_callen la conversación llega al modelo como la llamada con una nota, no con los resultados antiguos. El campoannotations(citas) queda vacío; las fuentes están en elweb_search_call. - Las imágenes y los archivos en las salidas de las herramientas no llegan al modelo; una nota en el texto los sustituye.
- No admitidos (400):
background,prompt,truncation: "auto",file_idyfile_url. Envía las imágenes comoimage_url(una URL o una data URI) y los PDF comoinput_fileconfile_data.
Embeddings
POST /v1/embeddings acepta el cuerpo de OpenAI (model, input como string o
array) y devuelve la respuesta de embeddings de OpenAI. Sin streaming. Se factura según usage.prompt_tokens.
Usa un modelo 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 puntúa documents frente a una query. El parámetro opcional
top_n limita los resultados. La respuesta incluye results con index (posición
en documents) y relevance_score, más usage.prompt_tokens, que es
lo que se factura. Usa un modelo 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 responde a preguntas tipadas sobre un estado. El modelo puntúa cada
respuesta posible en lugar de escribir texto, así que recibes probabilidades, no prosa. Úsalo para routing,
triaje, moderación o como control previo antes de que un agente ejecute una herramienta. Una llamada responde hasta 16 preguntas sobre el
mismo estado.
Lo sirven los modelos con supports_decisions: true en /v1/models. System One se ejecuta en
rutas alojadas en Nodion y en proveedores que ofrecen System One directamente. Si una ruta falla antes de procesar la
petición (rate limit, caída), la misma petición pasa a la siguiente ruta. La pestaña Decisions del
Playground tiene ejemplos listos para 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"
]
}
}
}' Petición
model(obligatorio): un modelo consupports_decisions.state(obligatorio): aquello sobre lo que tratan las preguntas. Un string, un objeto, un array onull.questions(obligatorio): un objeto con entre 1 y 16 entradas. La clave es el nombre que le das a la pregunta (hasta 128 caracteres) y vuelve como clave enanswers.
Cada pregunta tiene un type, unas instructions opcionales y unos criteria que
dependen del tipo. Los valores de instructions y criteria pueden ser un string, un objeto o un array;
null se admite en todas partes salvo en los niveles de score.
noul: una pregunta de sí o no.criteriaes opcional y solo puede tener las clavestrueyfalse. Unnoulnecesita unasinstructionsno vacías o al menos un criterio no vacío.choice: elige una etiqueta.criteriaasocia entre 1 y 26 etiquetas a un valor; los strings en blanco se rechazan. Las etiquetas deben ser únicas, sin distinguir mayúsculas de minúsculas, y tener como máximo 256 caracteres.score: puntúa en una escala.criteriaes un array de 2 a 10 niveles no vacíos, del más bajo al más alto. Los índices de nivel empiezan en 0.
Los campos desconocidos se rechazan. El cuerpo puede ocupar hasta 512 KiB, y el estado más la pregunta más grande deben caber en el contexto del modelo.
Respuesta
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 probabilidad de que la respuesta seatrue, de 0 a 1.choice:choicees la etiqueta más probable,probabilitiesincluye todas las etiquetas y suma 1, yconfidencees un valor de 0 a 1.score:scorees la media de los índices de nivel ponderada por probabilidad (de 0 hasta el número de niveles menos 1).probabilitiesylegendusan como clave el índice de nivel;legendasocia cada índice a la descripción de un nivel.confidencees un valor de 0 a 1.modeles el modelo que respondió.usage.output_tokenssiempre es 0.
Los valores de la respuesta de ejemplo son ilustrativos.
Facturación
Solo se facturan los tokens de entrada, al precio de entrada del modelo. El modelo lee el estado una vez por pregunta, así que
usage.input_tokens crece con el número de preguntas. Antes de la llamada, el saldo reserva
(bytes del estado + bytes de todas las preguntas + 4.096) × el número de preguntas como tokens de entrada,
y la petición se liquida según usage.input_tokens, nunca por encima de la reserva. Las peticiones que fallan no se
facturan; si te desconectas después de que el modelo haya respondido, se facturan sus tokens de entrada. Las ventanas gratuitas se aplican
igual que en el chat.
Errores
System One usa su propio cuerpo de error: {"detail": "message"} y, para 422, una lista de
elementos loc / msg / type que señalan el campo.
json{
"detail": [
{"loc": ["body", "questions", "team", "criteria"], "msg": "choice accepts 1 to 26 criteria", "type": "too_long"}
]
} - 401: clave ausente o no válida.
- 402: la facturación rechazó la petición: saldo, límites de gasto o no se pudo calcular el precio de la petición. Los motivos son los de los códigos 402, aquí solo como texto en
detail. - 404:
model not found, también para modelos sinsupports_decisions. - 422: cuerpo no válido, cuerpo de más de 512 KiB, estado y preguntas que superan el contexto, o el modelo rechazó la petición.
- 429: se alcanzó un límite de la clave (
Retry-After: 5), o todas las rutas de proveedor probadas estaban en rate limit (elRetry-Afterdel proveedor, 60 segundos como máximo). - 502: el modelo no respondió.
- 503: ninguna ruta operativa, ninguna que encaje con la configuración de privacidad del proyecto, o no se pudo cargar la configuración.
- 529: todas las rutas del modelo están al límite de capacidad.
Retry-After: 5.
OCR
POST /v1/ocr sigue el formato de Mistral OCR. Envía el archivo inline como data URI en base64;
las URL remotas se rechazan. Se admiten PDF, PNG, JPEG y 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 modelo OCR del catálogo público (kind: "ocr").document:{"type": "document_url", "document_url": "data:..."}o{"type": "image_url", "image_url": "data:..."}.pages(opcional): índices de las páginas que se leen, empezando por 0. No todos los modelos OCR lo admiten; los modelos OCR alojados yfirecrawl/pdf-inspectorresponden 400.include_image_base64(opcional): devuelve las imágenes incrustadas en base64. No todos los modelos OCR devuelven imágenes; algunos responden siempre con una listaimagesvacía.
La respuesta incluye pages (cada una con index, markdown y
images) y usage_info.pages_processed. Se factura por página procesada. La reserva cubre
el documento completo, y los documentos que superan el max_pages del modelo se rechazan.
firecrawl/pdf-inspector solo lee PDF generados digitalmente. Con una imagen responde 422; con un PDF con
páginas escaneadas responde 422 con code: "pages_need_ocr" y las páginas afectadas en
pages_needing_ocr.
Errores y límites
Todos los endpoints, salvo System One, devuelven los errores con la estructura de OpenAI:
json{
"error": {
"message": "insufficient AI balance. Top up in the AI Billing tab.",
"type": "error",
"code": "empty_balance"
}
} message siempre está presente. type, y si se rellena code, varían según el
endpoint, así que decide primero según el estado HTTP. Chat, embeddings, rerank y las herramientas web ponen los
códigos 402 en code. Cuando la ruta del modelo responde a chat, embeddings o
rerank con un error HTTP, el cuerpo también incluye request_id. La cabecera X-Request-ID
siempre está presente.
- 400: JSON no válido, falta
modelo un modelo del tipo incorrecto para el endpoint (por ejemplo, un modelo OCR en chat). Un cuerpo de más de 25 MiB que llega al proceso de la API usarequest body exceeds 25 MiB. - 401: consulta Autenticación.
- 402: el saldo rechazó la petición; consulta los códigos más abajo.
- 404:
model not found, o un endpoint que no existe. - 413: el host público rechazó un cuerpo de más de 25 MiB antes de que se ejecutara la API.
- 429: se alcanzó un límite de la clave o el modelo está sobrecargado. Respeta
Retry-Aftercuando se envíe. - 502: la ruta del modelo falló. Reinténtalo más tarde.
- 503: ninguna ruta operativa para el modelo, ninguna que encaje con la configuración de privacidad del proyecto (pestaña Settings), o no se pudo cargar la configuración.
Códigos 402. Chat, embeddings, rerank y las herramientas web los envían en code. OCR, audio e imagen
solo envían el mensaje, y System One lo envía como detail.
empty_balance: el saldo de IA disponible no cubre la reserva de esta petición. Recarga en la pestaña Billing o activa la recarga automática.daily_quota: el gasto de hoy en esta clave, más sus reservas abiertas, más esta petición superaría el límite de gasto diario de la clave.month_quota: el gasto de este mes, más las reservas abiertas, más esta petición superaría el límite de gasto mensual que fijaste en la pestaña Billing.usage_limit: el gasto de este mes, más las reservas abiertas, más esta petición superaría el tope mensual de tu nivel de uso. La pestaña Billing muestra el nivel y cuándo se aplica el siguiente.pricing_unavailableyreserve_failed: no se pudo calcular el precio de la petición o reservar el importe. Reinténtalo y después contacta con soporte indicando el ID de la petición.
Límites predeterminados por clave:
- 600 peticiones por minuto
- 4.000.000 de tokens por minuto (chat, embeddings, rerank y System One)
- 20 peticiones simultáneas
- 25 MiB de cuerpo de petición en chat, embeddings, rerank, OCR, audio e imágenes. Herramientas: 1 MiB. System One: 512 KiB.
En chat, embeddings y rerank, un 429 envía Retry-After: 5 por la tasa de peticiones y por
sobrecarga, 10 por el límite de tokens por minuto y 2 por concurrencia. System One siempre envía
Retry-After: 5. Al crear una voz se envía Retry-After cuando se alcanzan sus propios límites (demasiadas
subidas en curso, o más de diez intentos de creación por hora). Los demás 429 en OCR, audio, imagen, las herramientas web y
las voces no lo envían; espera unos segundos antes de reintentar. Contacta con soporte si necesitas límites más altos.