> ## Documentation Index
> Fetch the complete documentation index at: https://docs.derestricted.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Completions

> Generate text from a message history, with optional streaming and tool calls.

Send the messages needed for the current turn. Conversation history is supplied by your application on every request.

<ParamField header="Authorization" type="string" required>
  `Bearer` followed by your derestricted API key.
</ParamField>

<ParamField body="model" type="string" default="derestricted-llm">
  Use `derestricted-llm`. Omitting this field uses the same deployment.
</ParamField>

<ParamField body="messages" type="array" required>
  Conversation messages, such as `{"role": "user", "content": "Hello"}`. Include prior assistant messages and tool results when continuing a conversation. Maximum 2,000 items.
</ParamField>

<ParamField body="stream" type="boolean" default="false">
  Set to `true` for server-sent events.
</ParamField>

<ParamField body="max_tokens" type="integer">
  Output allowance, capped at 65,536. If omitted, the service chooses an
  affordable allowance up to 32,768. `max_completion_tokens` is also accepted
  and takes precedence when both fields are present.
</ParamField>

<ParamField body="stream_options" type="object">
  With streaming, use `{"include_usage": true}` to request the final usage chunk.
</ParamField>

<ParamField body="tools" type="array">
  Optional client-defined tool schemas. Your application executes calls and
  returns their results. Up to 128 tool definitions are accepted within the
  shared request limits.
</ParamField>

## Example

```bash theme={"system"}
curl https://api.derestricted.ai/v1/chat/completions \
  -H "Authorization: Bearer $DERESTRICTED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "derestricted-llm",
    "messages": [
      {"role": "system", "content": "Answer concisely."},
      {"role": "user", "content": "When should I use a queue instead of a direct function call?"}
    ],
    "max_tokens": 8192
  }'
```

Read answer text from `choices[0].message.content`. A response can also contain `message.tool_calls` or a `message.reasoning_content` extension. Check `finish_reason`; reaching the output limit may leave the answer incomplete.

## Streaming

```python theme={"system"}
import os
from openai import OpenAI

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

with client.chat.completions.create(
    model="derestricted-llm",
    messages=[{"role": "user", "content": "Explain eventual consistency briefly."}],
    max_tokens=8192,
    stream=True,
    stream_options={"include_usage": True},
) as stream:
    for chunk in stream:
        if chunk.choices:
            text = chunk.choices[0].delta.content
            if text:
                print(text, end="", flush=True)
        if chunk.usage:
            print("\nUsage:", chunk.usage)
```

Raw SSE clients receive JSON in `data:` frames followed by `data: [DONE]`. Keepalive comments such as `: ping` contain no generated text. Answer text arrives in `choices[].delta.content`; reasoning may arrive separately in `delta.reasoning_content` or `delta.reasoning`.

When usage is requested, the final usage chunk may have an empty `choices` array. Do not assume every chunk contains a choice. An `error` frame can occur after HTTP `200`; treat it as a failed generation even if some text has already arrived.

## Tool calls

Supply function definitions using the Chat Completions tool shape. If the model returns a tool call, validate its arguments, execute the approved operation in your application, and send the assistant tool call plus a `role: "tool"` result with the matching `tool_call_id` in the next request.

The API does not run functions or enforce a strict JSON Schema contract for arguments. See [compatibility limits](/api/openai-compatibility#fields-with-different-behavior) and [errors](/api/errors).
