# Chat completions

Generate a model response for a conversation. This endpoint follows the OpenAI Chat Completions format; see [Streaming](https://claudech.com/docs/streaming) and [Tool calling & JSON](https://claudech.com/docs/tools) for the guides.

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

## Request body

- `model` (string, required): A Claudech model slug or alias, for example `claude-opus-5-5`. See [Models](https://claudech.com/docs/models).
- `messages` (array, required): The conversation so far. Each message has a `role` (`system`, `developer`, `user`, `assistant` or `tool`) and `content`, which is a string, `null` (assistant tool-call turns) or an array of `text` / `image_url` parts. Assistant messages may carry `tool_calls` and `reasoning_content`; tool messages must carry `tool_call_id`. `developer` is accepted as an alias of `system`.
- `max_tokens` (integer): Upper bound on generated tokens (including reasoning tokens). Defaults to the model's maximum output. `max_completion_tokens` is accepted as a synonym and takes precedence.
- `temperature` (number, default `model default`): Sampling temperature between `0` and `2`.
- `top_p` (number): Nucleus sampling threshold in `(0, 1]`.
- `frequency_penalty` (number): Between `-2` and `2`.
- `presence_penalty` (number): Between `-2` and `2`.
- `stop` (string | string[]): Up to 16 sequences at which generation halts.
- `stream` (boolean, default `false`): Stream the response as server-sent events. See [Streaming](https://claudech.com/docs/streaming).
- `stream_options` (object): `{ include_usage: boolean }`. Usage chunks are sent by default; set `false` to suppress them.
- `response_format` (object): `{ type: "text" | "json_object" | "json_schema" }`. `json_schema` is treated as `json_object`; include the schema in your prompt. See [JSON output](https://claudech.com/docs/tools#json-output).
- `tools` (array): Function definitions: `{ type: "function", function: { name, description?, parameters? } }`. Up to 128.
- `tool_choice` (string | object): `none`, `auto`, `required`, or `{ type: "function", function: { name } }`.
- `reasoning_effort` (string): `none`, `minimal`, `low`, `medium`, `high`, `xhigh` or `max`. Controls thinking depth on reasoning-capable models; ignored otherwise. `minimal` maps to `low`; `medium`/`xhigh` map to `high`.
- `thinking` (object): `{ type: "enabled" | "disabled" }`. Alternative to `reasoning_effort`.
- `user` (string): Opaque end-user identifier (max 256 chars) recorded on usage records for your own attribution. Never used for billing.
- `n` (integer, default `1`): Only `1` is supported.

Unknown fields such as `metadata`, `store`, `seed` and `logprobs` are accepted and ignored so existing OpenAI-format code does not need to be edited.

## Response

Returns a `chat.completion` object. The `usage` block includes Claudech's billing fields alongside the standard token counts.

```json
{
  "id": "chatcmpl-01J9X3Q5K7M2N8P4R6T0V2W4Y6",
  "object": "chat.completion",
  "created": 1789494225,
  "model": "claude-opus-5-5",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Rivers carve the stone..." },
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 18,
    "completion_tokens": 42,
    "total_tokens": 60,
    "prompt_tokens_details": { "cached_tokens": 0 },
    "completion_tokens_details": { "reasoning_tokens": 0 },
    "prompt_cache_hit_tokens": 0,
    "prompt_cache_miss_tokens": 18,
    "claud_tokens_debited": "102",
    "claud_cost_usd": "0.000204"
  },
  "system_fingerprint": "fp_claud"
}
```

- `choices[].message.content` (string | null): The generated text, or `null` when the model only returned tool calls.
- `choices[].message.reasoning_content` (string): Present on reasoning models: the model's thinking. Pass it back on the next turn during tool use.
- `choices[].message.tool_calls` (array): Function calls the model wants you to run: `{ id, type: "function", function: { name, arguments } }` where `arguments` is a JSON string.
- `choices[].finish_reason` (string): `stop`, `length`, `tool_calls`, `content_filter` or `insufficient_system_resource`.
- `usage.claud_tokens_debited` (string): Claudech tokens charged for this request, as a decimal string.
- `usage.claud_cost_usd` (string): The same charge expressed in USD.

### Response headers

| Header | Meaning |
| --- | --- |
| `x-request-id` | Request identifier; include it in support tickets |
| `x-claud-model` | The model that actually served the request (may differ from `model` if a fallback was used) |
| `x-claud-tokens-debited` | Tokens charged (non-streaming only) |
| `x-claud-balance` | Available balance after this request (non-streaming only) |
| `x-ratelimit-*` | Remaining request and token budget; see [Rate limits](https://claudech.com/docs/rate-limits) |

## Examples

**curl**

```bash
curl https://api.claudech.com/v1/chat/completions \
  -H "Authorization: Bearer $CLAUDECH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "messages": [
      {"role": "system", "content": "You are a concise assistant."},
      {"role": "user", "content": "Write a haiku about rivers."}
    ],
    "max_tokens": 200
  }'
```

**JavaScript**

```javascript
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.CLAUDECH_API_KEY, baseURL: 'https://api.claudech.com/v1' });

const res = await client.chat.completions.create({
  model: 'claude-opus-5-5',
  messages: [
    { role: 'system', content: 'You are a concise assistant.' },
    { role: 'user', content: 'Write a haiku about rivers.' },
  ],
  max_tokens: 200,
});
console.log(res.choices[0].message.content);
```

**Python**

```python
from openai import OpenAI
client = OpenAI(api_key=os.environ["CLAUDECH_API_KEY"], base_url="https://api.claudech.com/v1")

res = client.chat.completions.create(
    model="claude-opus-5-5",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Write a haiku about rivers."},
    ],
    max_tokens=200,
)
print(res.choices[0].message.content)
```

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `invalid_request` | Body fails validation; `param` names the field |
| 400 | `context_length_exceeded` | Prompt plus `max_tokens` exceeds the model's context window or your plan's `max_context_tokens` |
| 401 | `invalid_api_key` | Missing, malformed, revoked or expired key |
| 402 | `insufficient_balance` | Not enough tokens to reserve for the request |
| 403 | `model_not_in_plan` | Your plan does not include this model |
| 404 | `model_not_found` | Unknown slug or alias |
| 413 | `payload_too_large` | Body exceeds the size limit |
| 429 | `rate_limit_exceeded` / `concurrency_limit_exceeded` | Per-minute or concurrent limits hit; check `retry-after` |
| 503 | `provider_unavailable` | Upstream capacity issue after fallbacks were tried; retry with back-off |

See [Errors](https://claudech.com/docs/errors) for the full list.

---

Source: https://claudech.com/docs/api/chat-completions
