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

# Chat Completions

> POST /v1/chat/completions — the main, OpenAI-compatible inference endpoint.

<Note>
  Base URL: `https://api.orbitrage.ai/v1` · Auth: `Authorization: Bearer orb_…`
</Note>

```
POST /v1/chat/completions
```

This is the OpenAI Chat Completions API. The only Orbitrage-specific behavior is
the `model` field: pass `auto` to route, or a concrete id to pin.

## Request

<ParamField body="model" type="string" required>
  `auto` (or `router` / `default` / `orbitrage`) to let Orbitrage pick the
  cheapest capable model, or any model id (e.g. `glm-5.2`, `gpt-5.4`,
  `DeepSeek-V4-Flash`) to pin one. See [Models](/concepts/models).
</ParamField>

<ParamField body="messages" type="array" required>
  The conversation, in OpenAI format (`role` + `content`). Supports text, image
  content blocks (for vision models), and tool/assistant messages.
</ParamField>

<ParamField body="stream" type="boolean" default="false">
  Stream the response as server-sent events.
</ParamField>

<ParamField body="tools" type="array">
  Tool/function definitions, OpenAI format. Routed to a tool-capable model.
</ParamField>

<ParamField body="temperature" type="number">
  Standard sampling controls (`temperature`, `top_p`, `max_tokens`, etc.) pass
  through to the provider.
</ParamField>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.orbitrage.ai/v1/chat/completions \
    -H "Authorization: Bearer $ORBITRAGE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "auto",
      "messages": [
        {"role": "system", "content": "You are concise."},
        {"role": "user", "content": "Name three uses for a router."}
      ]
    }'
  ```

  ```python Python theme={null}
  from openai import OpenAI            # after orbitrage.init(...)
  client = OpenAI()
  resp = client.chat.completions.create(
      model="auto",
      messages=[{"role": "user", "content": "Name three uses for a router."}],
  )
  print(resp.choices[0].message.content)
  ```

  ```typescript Node.js theme={null}
  const resp = await client.chat.completions.create({   // after orbitrage.init(...)
    model: "auto",
    messages: [{ role: "user", content: "Name three uses for a router." }],
  });
  console.log(resp.choices[0].message.content);
  ```
</CodeGroup>

## Response

A standard OpenAI `chat.completion` object. The model that actually served the
request is in the `model` field; the routing decision, cost, and savings are
recorded to your telemetry and visible in the dashboard.

```json theme={null}
{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "model": "DeepSeek-V4-Flash",
  "choices": [
    { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" }
  ],
  "usage": { "prompt_tokens": 24, "completion_tokens": 38, "total_tokens": 62 }
}
```

## Streaming

With `stream: true` you receive the usual OpenAI `chat.completion.chunk` events.
Orbitrage transforms the stream so your SDK gets a clean OpenAI feed:

* internal routing/summary events are captured and **stripped** (the SDK never
  sees unknown event types), and
* provider frames with empty `choices` (e.g. content-filter pre-frames) are
  rewritten so SDKs don't crash on `choices[0]`.

Read `X-Orbitrage-Overhead-Ms` and `X-Orbitrage-BYOK` from the response headers
to see routing overhead and whether your own key was used.
