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 token
  • invalid api key
  • api key expired
  • account disabled
  • account 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/modelsLista los modelos con precio por tokenGratis
POST /v1/chat/completionsChat, herramientas, salida estructuradaTokens de entrada y de salida
POST /v1/responsesOpenAI Responses API, por ejemplo para CodexTokens de entrada y de salida
POST /v1/embeddingsEmbeddings vectorialesTokens de entrada
POST /v1/rerankOrdena documentos según una consultaTokens de entrada
POST /v1/systemoneSystem One: decisiones tipadas con probabilidadesTokens de entrada
POST /v1/ocrOCR de documentos e imágenesPáginas
POST /v1/audio/transcriptionsVoz a textoSegundos de audio
GET /v1/audio/transcriptions/realtime (WebSocket)Voz a texto en tiempo realSegundos de audio
POST /v1/audio/speechTexto a vozCaracteres
GET, POST /v1/audio/voicesLista y crea voces clonadasGratis
GET, DELETE /v1/audio/voices/{id}Lee o elimina una voz clonadaGratis
POST /v1/images/generationsGeneración de imágenesImágenes
POST /v1/tools/web_search, web_news, web_fetch, web_images, web_videos, web_places, web_maps, web_shopping, web_lensHerramientas webLlamadas, 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 de model en las peticiones.
  • kind: chat, embeddings o rerank.
  • context_length y max_output_length en tokens.
  • pricing: precios en USD por token expresados como cadenas decimales. pricing_eur tiene los precios en EUR.
  • supported_sampling_parameters y supported_features (por ejemplo tools, json_mode, structured_outputs, reasoning).
  • reasoning_efforts: los valores de reasoning_effort que acepta este modelo (por ejemplo none, low, high). Vacío cuando los niveles no son configurables.
  • is_ready: false significa que ahora mismo ninguna ruta está operativa. El modelo sigue en la lista.
  • lifecycle: ga o preview. serving: hosted (los pesos se ejecutan en Nodion) o routed (reenviado a un proveedor).
  • supports_decisions: el modelo responde a System One.
  • coding_plan: Codion puede ofrecer este modelo de chat. Siempre true o false. 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 (o max_completion_tokens), el gateway fija max_tokens en el max_output_length del modelo. Los valores mayores se reducen a ese límite.
  • Con "stream": true, la respuesta llega como server-sent events (líneas data: {...} y después data: [DONE]). El gateway activa stream_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 objeto error y finish_reason: "error", seguido de data: [DONE].
  • El campo model de la respuesta es el id que enviaste. El texto de reasoning, cuando un modelo lo devuelve, está en reasoning_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. store se ignora y la respuesta indica store: false. No existen previous_response_id, conversation, item_reference ni GET /v1/responses/{id}. Envía la conversación completa en input, como hace Codex.
  • Herramientas: function, custom, namespace y web_search. Otras herramientas alojadas, como file_search o code_interpreter, se rechazan con 400.
  • Los resultados de búsqueda no se guardan. Un web_search_call en la conversación llega al modelo como la llamada con una nota, no con los resultados antiguos. El campo annotations (citas) queda vacío; las fuentes están en el web_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_id y file_url. Envía las imágenes como image_url (una URL o una data URI) y los PDF como input_file con file_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 con supports_decisions.
  • state (obligatorio): aquello sobre lo que tratan las preguntas. Un string, un objeto, un array o null.
  • 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 en answers.

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. criteria es opcional y solo puede tener las claves true y false. Un noul necesita unas instructions no vacías o al menos un criterio no vacío.
  • choice: elige una etiqueta. criteria asocia 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. criteria es 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 sea true, de 0 a 1.
  • choice: choice es la etiqueta más probable, probabilities incluye todas las etiquetas y suma 1, y confidence es un valor de 0 a 1.
  • score: score es la media de los índices de nivel ponderada por probabilidad (de 0 hasta el número de niveles menos 1). probabilities y legend usan como clave el índice de nivel; legend asocia cada índice a la descripción de un nivel. confidence es un valor de 0 a 1.
  • model es el modelo que respondió. usage.output_tokens siempre 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 sin supports_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 (el Retry-After del 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 y firecrawl/pdf-inspector responden 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 lista images vací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 model o 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 usa request 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-After cuando 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_unavailable y reserve_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.

Dale a tu agente un cloud.

Hasta 15 € de crédito al registrarte.

Continuar con GitHub

o con tu email

Mantente al día.

Novedades del producto, sin spam. Puedes darte de baja cuando quieras.