Skip to content

Chat completions

POST https://api.getnodea.com/openai/v1/chat/completions
Authorization: Bearer <your API key>
Content-Type: application/json

This endpoint follows OpenAI’s Create chat completion request and response format. This page lists what Nodea does with each field.

Nodea treats every field in one of four ways:

  • Supported. Always works.
  • Depends on the device. Works when the device serving your request runs a recent enough version of the Nodea app.
  • Ignored. Accepted, but has no effect.
  • Rejected. Returns a 400 error rather than silently doing the wrong thing.

A field set to null counts as not sent. Unknown fields are ignored.

Field Notes
model Required. A model name from your Models page, such as bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M.
messages Required, at least one message. See Messages.
stream true streams the response as server-sent events.
temperature 0 to 2. 0 is greedy decoding and gives repeatable output.
top_p 0 to 1.
max_completion_tokens, max_tokens Integer ≥ 1. If you send both, max_completion_tokens wins. When the limit is hit, finish_reason is "length".
stop A string or up to 4 strings. Unlike OpenAI, the stop text is included at the end of the output.
frequency_penalty, presence_penalty -2 to 2.

These fields work only if the device serving the request supports them. Devices running an older version of the Nodea app may not. If none of the devices serving the model support a field, you get unsupported_by_node. Updating the desktop app on those devices fixes it.

Field Notes
stream_options {"include_usage": true} adds a final chunk with token usage and no choices. Needs stream: true.
response_format {"type": "text"}, {"type": "json_object"} or {"type": "json_schema", "json_schema": {...}}. JSON Schema output is enforced during generation, so it always matches the schema. See Differences.
tools, tool_choice Function calling. tool_choice can be "auto" or "none"; "required" and naming a specific function aren’t supported. Whether a model calls tools well depends on the model.
functions, function_call Deprecated by OpenAI. Converted to tools / tool_choice.
logprobs, top_logprobs top_logprobs is 0–20 and needs logprobs: true.
n 1–8 choices per request.
logit_bias Token ids → bias (-100 to 100). Token ids come from the model’s own tokenizer, not OpenAI’s.
reasoning_effort "low", "medium" or "high". Only affects models trained for reasoning.
web_search_options Only on devices set up for web search.

Accepted with no effect. Ignored fields that you sent are listed in the x-nodea-ignored-params response header.

Field Why
seed Not supported by the inference engine. Use temperature: 0 for repeatable output.
user, safety_identifier Requests are already identified by your API key.
store, metadata Nodea doesn’t store completions.
service_tier There’s a single service tier.
prompt_cache_key, prompt_cache_retention, prompt_cache_options There’s no prompt cache.

These return 400 with code unsupported_parameter:

prediction, parallel_tool_calls: false, verbosity, moderation, modalities, audio.

n: 1 and parallel_tool_calls: true are allowed, because they’re OpenAI’s defaults.

Role Notes
system Instructions for the model.
developer Treated the same as system.
user Your input.
assistant Earlier model replies, including tool_calls.
tool A tool result. Needs tool_call_id, and a device that supports tools.
function Deprecated tool result. Needs a device that supports tools.

content can be a string or an array of {"type": "text", "text": "..."} parts. Text only: image, audio and file parts are rejected with unsupported_content_part.

Non-streaming responses are a chat.completion object:

  • id is chatcmpl- followed by 24 hex characters.
  • model echoes the model you asked for.
  • choices[].message.refusal is always null.
  • choices[].logprobs is null unless you asked for log probabilities.
  • system_fingerprint is always fp_nodea_local. It doesn’t mean output is reproducible.
  • usage has prompt_tokens, completion_tokens and total_tokens, as reported by the device. It’s left out if the device doesn’t report it. With n > 1, completion_tokens counts one choice, not the total.

finish_reason is "stop", "length" or "tool_calls".

With stream: true, the response is text/event-stream. Each event is a chat.completion.chunk:

  1. The first chunk for each choice has delta: {"role": "assistant", "content": ""}.
  2. The following chunks carry delta.content, with finish_reason: null.
  3. Each choice ends with a chunk that carries its finish_reason.
  4. With stream_options.include_usage, a chunk with choices: [] and usage comes next.
  5. The stream ends with data: [DONE].

Tool calls arrive complete in a single chunk rather than in pieces.

Endpoint Returns
GET /models {"object": "list", "data": [...]} with every model enabled for your organization, whether or not a device is serving it right now.
GET /models/{model} One model object. URL-encode / in the name as %2F. Returns 404 model_not_found if the model isn’t enabled for your organization.

Each model object is {"id", "object": "model", "created", "owned_by"}.

Any other path returns 404 with code unknown_url.