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

# Extensions and Thinking

> Control reasoning effort and pass provider-specific parameters through Auriko's normalized API

Add `reasoning_effort` to your request. Auriko translates it into each provider's native format. Use `extensions` keyed by provider name to pass through provider-specific parameters like Anthropic's `metadata` or Google's `safety_settings`.

## Prerequisites

* An [Auriko API key](https://auriko.ai/signup?redirectTo=%2Fdashboard%3Ftab%3Dapi-keys)
* Python 3.10+ with the OpenAI SDK (`pip install openai`) or the auriko SDK (`pip install auriko`)
  * OR Node.js 18+ with the OpenAI SDK (`npm install openai`) or `@auriko/sdk` (`npm install @auriko/sdk`)
* A model that supports reasoning (see [provider support table](#check-provider-support))

## Enable thinking

Pass `reasoning_effort` in your request to control extended reasoning:

<CodeGroup>
  ```python Python OpenAI theme={null}
  import os
  from openai import OpenAI

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

  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Solve this step by step: what is 23! / 20!?"}],
      extra_body={"reasoning_effort": "high"}
  )
  print(response.choices[0].message.content)
  ```

  ```typescript TypeScript OpenAI theme={null}
  import OpenAI from "openai";

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

  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Solve this step by step: what is 23! / 20!?" }],
      reasoning_effort: "high",
  });

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

  ```python Python Auriko theme={null}
  import os
  from auriko import Client

  client = Client(
      api_key=os.environ["AURIKO_API_KEY"],
      base_url="https://api.auriko.ai/v1"
  )

  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Solve this step by step: what is 23! / 20!?"}],
      reasoning_effort="high"
  )
  print(response.choices[0].message.content)
  ```

  ```typescript TypeScript Auriko theme={null}
  import { Client } from "@auriko/sdk";

  const client = new Client({
      apiKey: process.env.AURIKO_API_KEY,
      baseUrl: "https://api.auriko.ai/v1",
  });

  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Solve this step by step: what is 23! / 20!?" }],
      reasoning_effort: "high",
  });
  console.log(response.choices[0].message.content);
  ```

  ```bash cURL theme={null}
  curl https://api.auriko.ai/v1/chat/completions \
    -H "Authorization: Bearer $AURIKO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "claude-sonnet-4-6",
      "messages": [{"role": "user", "content": "Solve this step by step: what is 23! / 20!?"}],
      "reasoning_effort": "high"
    }'
  ```
</CodeGroup>

## Check provider support

Auriko translates `reasoning_effort` for each provider:

| Provider  | Models                    | Behavior                                                                                   |
| --------- | ------------------------- | ------------------------------------------------------------------------------------------ |
| Anthropic | Claude 4.6 (Opus, Sonnet) | Adaptive thinking with effort control                                                      |
| Anthropic | Claude 4.5 Opus           | Thinking budget + effort control                                                           |
| Anthropic | Claude 4.5 Sonnet/Haiku   | Thinking budget derived from effort level                                                  |
| OpenAI    | o3, o4-mini, GPT-5        | Native `reasoning_effort` (dropped when `tools` present on GPT-5.4+)                       |
| Google    | Gemini 3.x                | Thinking level (`low`/`medium`/`high`)                                                     |
| Google    | Gemini 2.5 Flash/Pro      | Thinking budget derived from effort level                                                  |
| DeepSeek  | V4 Flash, V4 Pro          | Thinking budget derived from effort level                                                  |
| xAI       | Grok 3 mini, Grok 4.3     | Native `reasoning_effort` (`low`/`high` on Grok 3 mini, `low`/`medium`/`high` on Grok 4.3) |
| MiniMax   | M2 series                 | Built-in reasoning; `reasoning_effort` dropped                                             |
| Moonshot  | Kimi K2.5, Kimi K2.6      | Native `reasoning_effort`                                                                  |

<Note>
  Non-reasoning models (e.g. GPT-4o, GPT-4.1, Llama) reject `reasoning_effort` with 400 `reasoning_not_supported`. The one exception is GPT-5.4+ with `tools`: Auriko drops `reasoning_effort` to prevent an upstream 400.
</Note>

<Note>
  `deepseek-chat` and `deepseek-reasoner` are aliases of `deepseek-v4-flash` — they select the same model, not a thinking vs. non-thinking mode. Through Auriko, thinking behavior follows the serving provider's default and may differ from DeepSeek's direct API. Set `reasoning_effort` to control it explicitly — use `"off"` for non-thinking output.
</Note>

## Read thinking output

Some providers surface the model's reasoning in the `reasoning_content` field on the response message:

<CodeGroup>
  ```python Python OpenAI theme={null}
  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Solve step by step: what is 23! / 20!?"}],
      extra_body={"reasoning_effort": "high"}
  )

  msg = response.choices[0].message
  reasoning = getattr(msg, "reasoning_content", None)
  if reasoning:
      print(f"Reasoning: {reasoning}")
  print(f"Answer: {msg.content}")
  ```

  ```typescript TypeScript OpenAI theme={null}
  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Solve step by step: what is 23! / 20!?" }],
      reasoning_effort: "high",
  });

  const msg = response.choices[0].message;
  const reasoning = (msg as any).reasoning_content;
  if (reasoning) {
      console.log(`Reasoning: ${reasoning}`);
  }
  console.log(`Answer: ${msg.content}`);
  ```

  ```python Python Auriko theme={null}
  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Solve step by step: what is 23! / 20!?"}],
      reasoning_effort="high"
  )

  # Access the reasoning (if the model returns it)
  if response.choices[0].message.reasoning_content:
      print(f"Reasoning: {response.choices[0].message.reasoning_content}")
  print(f"Answer: {response.choices[0].message.content}")
  ```

  ```typescript TypeScript Auriko theme={null}
  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Solve step by step: what is 23! / 20!?" }],
      reasoning_effort: "high",
  });

  if (response.choices[0].message.reasoning_content) {
      console.log(`Reasoning: ${response.choices[0].message.reasoning_content}`);
  }
  console.log(`Answer: ${response.choices[0].message.content}`);
  ```

  ```bash cURL theme={null}
  curl https://api.auriko.ai/v1/chat/completions \
    -H "Authorization: Bearer $AURIKO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "claude-sonnet-4-6",
      "messages": [{"role": "user", "content": "Solve step by step: what is 23! / 20!?"}],
      "reasoning_effort": "high"
    }'
  ```
</CodeGroup>

<Note>
  Not all reasoning models populate `reasoning_content`, so check before accessing. OpenAI keeps reasoning internal, and other providers vary by model.
</Note>

## Preserve reasoning across turns

Some providers return reasoning context you echo back for multi-turn continuity. Anthropic and Google use structured `reasoning` blocks with cryptographic signatures, while DeepSeek uses a plain-text `reasoning_content` field. Include the relevant fields from the assistant response in your next request to preserve context.

### Read structured reasoning

<CodeGroup>
  ```python Python OpenAI theme={null}
  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Analyze this problem step by step."}],
      extra_body={"reasoning_effort": "high"}
  )

  msg = response.choices[0].message
  reasoning = getattr(msg, "reasoning", None)
  if reasoning:
      for block in reasoning:
          if block.get("type") == "thinking":
              print(f"Thinking: {block['thinking'][:80]}...")
              print(f"Signature: {block['signature'][:20]}...")
          elif block.get("type") == "redacted":
              print("Redacted block (encrypted)")
  ```

  ```typescript TypeScript OpenAI theme={null}
  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Analyze this problem step by step." }],
      reasoning_effort: "high",
  });

  const msg = response.choices[0].message;
  const reasoning = (msg as any).reasoning;
  if (reasoning) {
      for (const block of reasoning) {
          if (block.type === "thinking") {
              console.log(`Thinking: ${block.thinking.slice(0, 80)}...`);
              console.log(`Signature: ${block.signature.slice(0, 20)}...`);
          } else if (block.type === "redacted") {
              console.log("Redacted block (encrypted)");
          }
      }
  }
  ```

  ```python Python Auriko theme={null}
  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Analyze this problem step by step."}],
      reasoning_effort="high"
  )

  msg = response.choices[0].message
  if msg.reasoning:
      for block in msg.reasoning:
          if block.type == "thinking":
              print(f"Thinking: {block.thinking[:80]}...")
              print(f"Signature: {block.signature[:20]}...")
          elif block.type == "redacted":
              print(f"Redacted block (encrypted)")
  ```

  ```typescript TypeScript Auriko theme={null}
  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Analyze this problem step by step." }],
      reasoning_effort: "high",
  });

  const msg = response.choices[0].message;
  if (msg.reasoning) {
      for (const block of msg.reasoning) {
          if (block.type === "thinking") {
              console.log(`Thinking: ${block.thinking.slice(0, 80)}...`);
              console.log(`Signature: ${block.signature.slice(0, 20)}...`);
          } else if (block.type === "redacted") {
              console.log("Redacted block (encrypted)");
          }
      }
  }
  ```

  ```bash cURL theme={null}
  curl https://api.auriko.ai/v1/chat/completions \
    -H "Authorization: Bearer $AURIKO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "claude-sonnet-4-6",
      "messages": [{"role": "user", "content": "Analyze this problem step by step."}],
      "reasoning_effort": "high"
    }'
  ```
</CodeGroup>

Each block has a `type`:

* `thinking`: contains `thinking` (the reasoning text) and `signature` (cryptographic signature)
* `redacted`: contains `data` (encrypted, opaque to the client)

### Round-trip reasoning

To continue a multi-turn conversation with reasoning context, include the full assistant message (with `reasoning`) in your next request:

<CodeGroup>
  ```python Python OpenAI theme={null}
  messages = [
      {"role": "user", "content": "What are the trade-offs of microservices vs monoliths?"},
  ]

  first = client.chat.completions.create(
      model="claude-sonnet-4-6", messages=messages,
      extra_body={"reasoning_effort": "high"}
  )

  assistant_msg = first.choices[0].message
  messages.append(assistant_msg.model_dump(exclude_none=True))
  messages.append({"role": "user", "content": "Now apply that analysis to a 5-person startup."})

  second = client.chat.completions.create(
      model="claude-sonnet-4-6", messages=messages,
      extra_body={"reasoning_effort": "high"}
  )
  ```

  ```typescript TypeScript OpenAI theme={null}
  const messages = [
      { role: "user" as const, content: "What are the trade-offs of microservices vs monoliths?" },
  ];

  const first = await client.chat.completions.create({
      model: "claude-sonnet-4-6", messages,
      reasoning_effort: "high",
  });

  const assistantMsg = first.choices[0].message;
  messages.push(assistantMsg);
  messages.push({ role: "user" as const, content: "Now apply that analysis to a 5-person startup." });

  const second = await client.chat.completions.create({
      model: "claude-sonnet-4-6", messages,
      reasoning_effort: "high",
  });
  ```

  ```python Python Auriko theme={null}
  messages = [
      {"role": "user", "content": "What are the trade-offs of microservices vs monoliths?"},
  ]

  first = client.chat.completions.create(
      model="claude-sonnet-4-6", messages=messages, reasoning_effort="high"
  )

  assistant_msg = first.choices[0].message
  messages.append(assistant_msg.model_dump(exclude_none=True))
  messages.append({"role": "user", "content": "Now apply that analysis to a 5-person startup."})

  second = client.chat.completions.create(
      model="claude-sonnet-4-6", messages=messages, reasoning_effort="high"
  )
  ```

  ```typescript TypeScript Auriko theme={null}
  const messages = [
      { role: "user" as const, content: "What are the trade-offs of microservices vs monoliths?" },
  ];

  const first = await client.chat.completions.create({
      model: "claude-sonnet-4-6", messages, reasoning_effort: "high",
  });

  const assistantMsg = first.choices[0].message;
  messages.push(assistantMsg);
  messages.push({ role: "user" as const, content: "Now apply that analysis to a 5-person startup." });

  const second = await client.chat.completions.create({
      model: "claude-sonnet-4-6", messages, reasoning_effort: "high",
  });
  ```
</CodeGroup>

### DeepSeek reasoning content

DeepSeek models return reasoning as a plain `reasoning_content` string instead of structured `reasoning` blocks. For multi-turn conversations with DeepSeek, include `reasoning_content` on assistant messages you send back. To preserve it, serialize the full message object:

<CodeGroup>
  ```python Python OpenAI theme={null}
  first = client.chat.completions.create(
      model="deepseek-v4-flash",
      messages=[{"role": "user", "content": "Explain quantum entanglement step by step."}],
      extra_body={"reasoning_effort": "high"}
  )

  msg = first.choices[0].message
  messages = [
      {"role": "user", "content": "Explain quantum entanglement step by step."},
      msg.model_dump(exclude_none=True),  # preserves reasoning_content
      {"role": "user", "content": "Now explain it to a five-year-old."},
  ]

  second = client.chat.completions.create(
      model="deepseek-v4-flash", messages=messages,
      extra_body={"reasoning_effort": "high"}
  )
  ```

  ```typescript TypeScript OpenAI theme={null}
  const first = await client.chat.completions.create({
      model: "deepseek-v4-flash",
      messages: [{ role: "user", content: "Explain quantum entanglement step by step." }],
      reasoning_effort: "high",
  });

  const msg = first.choices[0].message;
  const messages = [
      { role: "user" as const, content: "Explain quantum entanglement step by step." },
      msg,  // preserves reasoning_content
      { role: "user" as const, content: "Now explain it to a five-year-old." },
  ];

  const second = await client.chat.completions.create({
      model: "deepseek-v4-flash", messages,
      reasoning_effort: "high",
  });
  ```

  ```python Python Auriko theme={null}
  first = client.chat.completions.create(
      model="deepseek-v4-flash",
      messages=[{"role": "user", "content": "Explain quantum entanglement step by step."}],
      reasoning_effort="high"
  )

  msg = first.choices[0].message
  messages = [
      {"role": "user", "content": "Explain quantum entanglement step by step."},
      msg.model_dump(exclude_none=True),  # preserves reasoning_content
      {"role": "user", "content": "Now explain it to a five-year-old."},
  ]

  second = client.chat.completions.create(
      model="deepseek-v4-flash", messages=messages, reasoning_effort="high"
  )
  ```

  ```typescript TypeScript Auriko theme={null}
  const first = await client.chat.completions.create({
      model: "deepseek-v4-flash",
      messages: [{ role: "user", content: "Explain quantum entanglement step by step." }],
      reasoning_effort: "high",
  });

  const msg = first.choices[0].message;
  const messages = [
      { role: "user" as const, content: "Explain quantum entanglement step by step." },
      msg,  // preserves reasoning_content
      { role: "user" as const, content: "Now explain it to a five-year-old." },
  ];

  const second = await client.chat.completions.create({
      model: "deepseek-v4-flash", messages, reasoning_effort: "high",
  });
  ```
</CodeGroup>

If you construct assistant messages manually and omit `reasoning_content`, Auriko sets it to an empty string. Echo back the original value from the response.

### Stream reasoning fields

When streaming with extended thinking, two additional delta fields carry reasoning block data:

* `delta.reasoning_signature`: cryptographic signature for the current thinking block
* `delta.reasoning_redacted_data`: encrypted data for a redacted thinking block (complete in one event)

These appear alongside `delta.reasoning_content` (the incremental reasoning text).

## Use provider passthrough

For provider-specific features beyond reasoning effort, use provider-keyed extensions. Auriko forwards these to the provider:

<CodeGroup>
  ```python Python OpenAI theme={null}
  import os
  from openai import OpenAI

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

  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Hello!"}],
      extra_body={
          "reasoning_effort": "high",
          "extensions": {
              "anthropic": {
                  "metadata": {"user_id": "user-123"}
              }
          }
      }
  )
  ```

  ```typescript TypeScript OpenAI theme={null}
  import OpenAI from "openai";

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

  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Hello!" }],
      reasoning_effort: "high",
      extensions: {
          anthropic: {
              metadata: { user_id: "user-123" },
          },
      },
  });

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

  ```python Python Auriko theme={null}
  import os
  from auriko import Client

  client = Client(
      api_key=os.environ["AURIKO_API_KEY"],
      base_url="https://api.auriko.ai/v1"
  )

  response = client.chat.completions.create(
      model="claude-sonnet-4-6",
      messages=[{"role": "user", "content": "Hello!"}],
      reasoning_effort="high",
      extensions={
          "anthropic": {
              "metadata": {"user_id": "user-123"}
          }
      }
  )
  ```

  ```typescript TypeScript Auriko theme={null}
  import { Client } from "@auriko/sdk";

  const client = new Client({
      apiKey: process.env.AURIKO_API_KEY,
      baseUrl: "https://api.auriko.ai/v1",
  });

  const response = await client.chat.completions.create({
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Hello!" }],
      reasoning_effort: "high",
      extensions: {
          anthropic: {
              metadata: { user_id: "user-123" },
          },
      },
  });
  ```

  ```bash cURL theme={null}
  curl https://api.auriko.ai/v1/chat/completions \
    -H "Authorization: Bearer $AURIKO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "claude-sonnet-4-6",
      "messages": [{"role": "user", "content": "Hello!"}],
      "reasoning_effort": "high",
      "extensions": {"anthropic": {"metadata": {"user_id": "user-123"}}}
    }'
  ```
</CodeGroup>

Auriko normalizes provider aliases. `google`, `google_ai`, `googleai`, and `gemini` are interchangeable.

### Transform-controlled fields

If you set `reasoning_effort`, Auriko controls each provider's thinking budget. Thinking-budget parameters in `extensions` are overwritten. If you don't set `reasoning_effort`, your passthrough values are preserved.

### Passthrough fields

Fields that aren't transform-controlled pass through to the provider unchanged. Examples:

* Anthropic: `metadata`
* OpenAI: `store`, `metadata`
* Google Gemini: `safety_settings`

## Handle sampling constraints

On Anthropic models, `temperature`, `top_p`, and `top_k` are incompatible with active thinking. If you send `reasoning_effort` alongside these parameters, Auriko drops the incompatible values and returns a warning in `routing_metadata.warnings`:

```json theme={null}
{
  "type": "unsupported_parameter",
  "code": "temperature",
  "message": "temperature dropped — incompatible with thinking on anthropic (must be exactly 1 or unset)"
}
```

Anthropic's constraints when thinking is active:

| Parameter     | Constraint                      |
| ------------- | ------------------------------- |
| `temperature` | Must be exactly `1`, or omitted |
| `top_p`       | Must be `>= 0.95`, or omitted   |
| `top_k`       | Must be omitted                 |

Values within these bounds pass through unchanged. Other providers don't enforce these constraints.

## Check effort normalization

Some models support only a subset of `reasoning_effort` levels. If you request a level above the model's maximum, Auriko normalizes it to the highest supported value and includes a warning in `routing_metadata.warnings`:

```json theme={null}
{
  "type": "unsupported_parameter",
  "code": "reasoning_effort",
  "message": "reasoning_effort adjusted to 'high' — exceeds model maximum on openai"
}
```

| Provider  | Models affected           | `xhigh`/`max` normalized to |
| --------- | ------------------------- | --------------------------- |
| OpenAI    | GPT-5, GPT-5 mini, o3-pro | `high`                      |
| Anthropic | Claude Opus 4.5           | `high`                      |
| xAI       | Grok 4.3                  | `high`                      |
| xAI       | Grok 3 mini               | `high`                      |
| Google    | Gemini 3.x                | `high`                      |

Models not listed above accept `xhigh` and `max` without a warning. For the full provider support table, see [Check provider support](#check-provider-support).

## Handle `max_tokens` constraints

Anthropic models that use thinking budgets require `max_tokens` above 1024. If you send `reasoning_effort` with `max_tokens` at or below 1024, Auriko skips thinking and returns a warning in `routing_metadata.warnings`:

```json theme={null}
{
  "type": "unsupported_parameter",
  "code": "reasoning_effort",
  "message": "reasoning_effort dropped — max_tokens (200) is below the 1025 minimum required for thinking on anthropic"
}
```

Claude 4.6+ models use adaptive thinking rather than thinking budgets. For the full model list, see [Check provider support](#check-provider-support).

## Estimate cost and latency

The `reasoning_effort` level (low/medium/high/xhigh/max) determines the thinking budget per provider. Exact token budgets aren't guaranteed; `reasoning_effort="off"` disables thinking on supported models. See [Check reasoning token availability](#check-reasoning-token-availability) for which providers report a breakdown.

## Check reasoning token availability

The `completion_tokens_details.reasoning_tokens` field reports how many tokens the model spent on reasoning. Auriko passes through what the upstream provider reports.

| Provider  | Model examples                           | `reasoning_tokens` reported? | Notes                                          |
| --------- | ---------------------------------------- | ---------------------------- | ---------------------------------------------- |
| OpenAI    | o1, o3, o4-mini                          | Yes                          | Native field                                   |
| DeepSeek  | deepseek-v4-flash, deepseek-v4-pro       | Yes                          | Native field                                   |
| xAI       | grok-4-fast-reasoning                    | Yes                          | Native field                                   |
| Google    | Gemini 2.5 Flash                         | Yes                          | Derived from provider token counts             |
| Anthropic | All Claude models                        | No                           | Reports combined output tokens only            |
| Moonshot  | kimi-k2-thinking, kimi-k2-thinking-turbo | No                           | Token breakdown not reported                   |
| Fireworks | deepseek-v3.2                            | No                           | Token breakdown not reported for hosted models |

When the provider doesn't report a reasoning token breakdown, Auriko doesn't include `completion_tokens_details` in the response.

Check for the field before accessing it:

<CodeGroup>
  ```python Python OpenAI theme={null}
  if response.usage.completion_tokens_details:
      print(f"Reasoning: {response.usage.completion_tokens_details.reasoning_tokens}")
  ```

  ```typescript TypeScript OpenAI theme={null}
  if (response.usage?.completion_tokens_details) {
      console.log(`Reasoning: ${(response.usage.completion_tokens_details as any).reasoning_tokens}`);
  }
  ```

  ```python Python Auriko theme={null}
  if response.usage.completion_tokens_details:
      print(f"Reasoning: {response.usage.completion_tokens_details.reasoning_tokens}")
  ```

  ```typescript TypeScript Auriko theme={null}
  if (response.usage?.completion_tokens_details) {
      console.log(`Reasoning: ${response.usage.completion_tokens_details.reasoning_tokens}`);
  }
  ```

  ```bash cURL theme={null}
  curl https://api.auriko.ai/v1/chat/completions \
    -H "Authorization: Bearer $AURIKO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "deepseek-v4-flash",
      "messages": [{"role": "user", "content": "Think about this."}],
      "reasoning_effort": "high"
    }'
  ```
</CodeGroup>

<Note>
  When `completion_tokens_details` isn't available, `completion_tokens` reflects the combined total of reasoning and content tokens. You can still use it for cost tracking.
</Note>
