Chat completions
POST https://api.getnodea.com/openai/v1/chat/completionsAuthorization: Bearer <your API key>Content-Type: application/jsonThis 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
400error rather than silently doing the wrong thing.
A field set to null counts as not sent. Unknown fields are ignored.
Supported
Section titled “Supported”| 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. |
Depends on the device
Section titled “Depends on the device”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. |
Ignored
Section titled “Ignored”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. |
Rejected
Section titled “Rejected”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.
Messages
Section titled “Messages”| 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.
Response
Section titled “Response”Non-streaming responses are a chat.completion object:
idischatcmpl-followed by 24 hex characters.modelechoes the model you asked for.choices[].message.refusalis alwaysnull.choices[].logprobsisnullunless you asked for log probabilities.system_fingerprintis alwaysfp_nodea_local. It doesn’t mean output is reproducible.usagehasprompt_tokens,completion_tokensandtotal_tokens, as reported by the device. It’s left out if the device doesn’t report it. Withn> 1,completion_tokenscounts one choice, not the total.
finish_reason is "stop", "length" or "tool_calls".
Streaming responses
Section titled “Streaming responses”With stream: true, the response is text/event-stream. Each event is a
chat.completion.chunk:
- The first chunk for each choice has
delta: {"role": "assistant", "content": ""}. - The following chunks carry
delta.content, withfinish_reason: null. - Each choice ends with a chunk that carries its
finish_reason. - With
stream_options.include_usage, a chunk withchoices: []andusagecomes next. - The stream ends with
data: [DONE].
Tool calls arrive complete in a single chunk rather than in pieces.
Models endpoints
Section titled “Models endpoints”| 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.