# Chat Completions

> Request fields, response shape and streaming behaviour for POST /v1/chat/completions.

```
POST https://api.tokrouter.dev/v1/chat/completions
Authorization: Bearer sk-…
Content-Type: application/json
```

The most universal entry point: OpenAI protocol, and the default path for most clients and frameworks.

## Request fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `model` | string | Yes | Model id, see [Models](/en/models/) |
| `messages` | array | Yes | Items have `role` (`system` / `user` / `assistant` / `tool`) and `content` |
| `stream` | boolean | No | `true` returns SSE, see [Streaming](/en/guides/streaming/) |
| `max_tokens` | integer | No | Output token cap |
| `temperature` | number | No | Sampling temperature |
| `top_p` | number | No | Nucleus sampling |
| `stop` | string / array | No | Stop sequences |
| `tools` | array | No | Function declarations, see [Tool calling](/en/guides/tool-calling/) |
| `tool_choice` | string / object | No | `auto` / `none` / a named function |
| `response_format` | object | No | Structured output, see [Structured output](/en/guides/structured-output/) |
| `user` | string | No | Caller-defined end-user identifier |

<Callout type="info" title="A subset of the OpenAI protocol">
The gateway interprets requests as OpenAI Chat Completions and maps them to the target vendor.
Vendor-exclusive fields are not guaranteed — see [Protocol bridging](/en/guides/protocol-interop/).
</Callout>

## Response

```json
{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1793000000,
  "model": "gpt-5.4-mini",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "Hello"},
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 3,
    "total_tokens": 15
  }
}
```

`usage.prompt_tokens_details.cached_tokens` (when present) corresponds to the cache-read billed portion.

## Streaming

With `stream: true` each chunk carries `choices[0].delta` and the stream ends with `data: [DONE]`.
`usage` usually appears only in the final chunk, and some upstreams omit it entirely.

## Status codes

| Status | Meaning |
| --- | --- |
| `200` | Success (streaming also starts with 200; errors after the stream opens arrive as events) |
| `400` | Invalid body, e.g. unknown `model` |
| `401` | Authentication failure, see [Authentication](/en/authentication/) |
| `429` | Rate limit or quota cap |
| `5xx` | Upstream vendor error |

Specific `type` / `code` values come from the upstream and are not enumerated here.
