---
title: "Chat Completions (Electron)"
method: POST
path: "/waves/v1/chat/completions"
tags: ["LLM"]
---

# Chat Completions (Electron)

`POST /waves/v1/chat/completions`

Generate a chat completion with Electron. OpenAI-compatible
request/response shape — point any OpenAI SDK at
`https://api.smallest.ai/waves/v1` and it just works.

Set `stream: true` to receive tokens via Server-Sent Events. With
`stream_options: { include_usage: true }`, the final SSE chunk
carries the `usage` block so token accounting is exact even on
client disconnects.

Tool calling follows OpenAI's `tools` array convention. When you
provide a voice-agent-style system prompt, Electron emits a short
filler phrase in the assistant message `content` field alongside
`tool_calls` — see the [Tool Calling guide](/models/documentation/llm-electron/tool-function-calling)
for the voice-agent pattern.

## Examples

**cURL**
```bash
curl -X POST "https://api.smallest.ai/waves/v1/chat/completions" \
  -H "Authorization: Bearer $SMALLEST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "electron",
    "messages": [
      {"role": "user", "content": "Write one sentence about why the sky is blue."}
    ]
  }'
```

**Python** (`pip install openai`)
```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.smallest.ai/waves/v1",
    api_key=os.environ["SMALLEST_API_KEY"],
)

response = client.chat.completions.create(
    model="electron",
    messages=[
        {"role": "user", "content": "Write one sentence about why the sky is blue."}
    ],
)

print(response.choices[0].message.content)
```

**JavaScript / TypeScript** (`npm install openai`)
```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.smallest.ai/waves/v1",
  apiKey: process.env.SMALLEST_API_KEY,
});

const response = await client.chat.completions.create({
  model: "electron",
  messages: [
    { role: "user", content: "Write one sentence about why the sky is blue." },
  ],
});

console.log(response.choices[0].message.content);
```

**Streaming with usage** (Python)
```python
stream = client.chat.completions.create(
    model="electron",
    messages=[{"role": "user", "content": "Tell me a one-sentence fun fact."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        print(f"\n\nTokens: {chunk.usage.total_tokens}")
```

## Common gotchas

- **Base URL is `/waves/v1`**, not `/v1`. The OpenAI SDK appends `/chat/completions` for you.
- **`stream_options.include_usage: true`** is required for exact token accounting on streaming calls — the final SSE chunk carries the `usage` block.
- **`n > 1` and `prompt_logprobs` are rejected.** Use multiple requests if you need parallel completions.
- **Auth header is `Authorization: Bearer $SMALLEST_API_KEY`** — get the key from the [Smallest AI Console](https://app.smallest.ai/dashboard/api-keys).

## Request body

- ChatCompletionRequest — Most OpenAI Chat Completions request fields are accepted as passthrough. Explicitly rejected: `n > 1`, `prompt_logprobs`.
  - `model` string, required — Model ID. Currently only `"electron"`.
  - `messages` ElectronMessage[], required — Chat history. Standard OpenAI message array.
    - `role` string, required — Message role — one of `system`, `user`, `assistant`, or `tool`. `tool` is used to feed a function-call result back to the model on the next turn.
    - `content` string, nullable — Text content for the message. `null` is permitted on assistant messages that carry only `tool_calls`.
    - `tool_calls` ElectronToolCall[]
      - `id` string, required
      - `type` 'function', required
      - `function` object, required
        - `name` string, required
        - `arguments` string, required — JSON-encoded argument object.
    - `tool_call_id` string — Required when `role` is `"tool"`.
  - `temperature` number — Sampling temperature.
  - `top_p` number — Nucleus sampling.
  - `max_tokens` integer — Maximum output tokens. Combined input + output context ceiling is 32,768.
  - `stream` boolean — When true, response is `text/event-stream`. See the [Streaming guide](/models/documentation/llm-electron/streaming).
  - `stream_options` object
    - `include_usage` boolean — Append a final SSE chunk with the `usage` block. Strongly recommended for any caller that tracks token consumption.
  - `tools` object[] — Tool / function calling definitions. Forwarded verbatim to the OpenAI-compatible upstream, so the standard OpenAI shape (`{type: "function", function: {name, description, parameters}}`) is the recommended form and is what the examples below use. The wire schema is permissive (`array<object>`) — any tools payload the upstream accepts will work. See [Tool Calling](/models/documentation/llm-electron/tool-function-calling) for details.
  - `tool_choice` union
    - 'auto' | 'required' | 'none'
    - object
      - `type` 'function', required
      - `function` object, required
        - `name` string, required
  - `response_format` object — Output shape. `{type: "text"}` (default) or `{type: "json_object"}`.
    - `type` 'text' | 'json_object'
  - `stop` union
    - string
    - string[]
  - `seed` integer — Best-effort determinism.
  - `logit_bias` object
  - `logprobs` boolean
  - `top_logprobs` integer
  - `presence_penalty` number
  - `frequency_penalty` number
  - `user` string — Opaque end-user identifier. Not interpreted by Electron.

## Response `200`

Non-streaming: standard OpenAI `chat.completion` object.

Streaming (`stream: true`): `text/event-stream` SSE — each
event is a `chat.completion.chunk` delta, terminated by
`data: [DONE]`.

- ChatCompletion
  - `id` string
  - `object` 'chat.completion'
  - `created` integer
  - `model` string
  - `choices` object[]
    - `index` integer
    - `message` ElectronMessage
      - `role` string, required — Message role — one of `system`, `user`, `assistant`, or `tool`. `tool` is used to feed a function-call result back to the model on the next turn.
      - `content` string, nullable — Text content for the message. `null` is permitted on assistant messages that carry only `tool_calls`.
      - `tool_calls` ElectronToolCall[]
        - `id` string, required
        - `type` 'function', required
        - `function` object, required
          - `name` string, required
          - `arguments` string, required — JSON-encoded argument object.
      - `tool_call_id` string — Required when `role` is `"tool"`.
    - `finish_reason` 'stop' | 'length' | 'tool_calls' | 'content_filter'
  - `usage` Usage
    - `prompt_tokens` integer — Total input tokens (cached + uncached).
    - `completion_tokens` integer
    - `total_tokens` integer
    - `prompt_tokens_details` object
      - `cached_tokens` integer — Subset of `prompt_tokens` served from prefix cache. Billed at the discounted rate ($0.10 / 1M vs $0.40 / 1M for fresh input).

## Other responses

- `400` — Bad request — schema validation, unsupported parameter (`n > 1`, `prompt_logprobs`), context length exceeded, or invalid field value forwarded by the model.
- `401` — Missing or invalid API key.
- `403` — API key valid but no access to Electron on this plan.
- `429` — Rate limit (RPM) or concurrency cap hit. See [Concurrency and Limits](/models/api-reference/concurrency-and-limits).
- `502` — Upstream model unavailable. Retry with backoff.
- `503` — Endpoint temporarily disabled, or upstream model overloaded.

---

[API](https://skmtc.net/smallest-inc/apis/electron-chat-completions-api.md) · [All operations](https://skmtc.net/smallest-inc/apis/electron-chat-completions-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/smallest-inc/electron-chat-completions-api/revisions/5e96a0cb9289/schema)
