> This page is for Model APIs.

> Sarvam Voice Agents (Samvaad) is a voice AI agent platform for Indian languages: build, test and deploy AI calling agents on your own phone numbers, from ₹3 a minute. Start here: https://docs.sarvam.ai/voice-agents/why-voice-agents.
> For clean Markdown of any page, append `.md` to the page URL.
> For a complete documentation index, see https://docs.sarvam.ai/llms.txt. For a section index, append `/llms.txt` to any section URL (for example https://docs.sarvam.ai/voice-agents/llms.txt).
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server.

# Migrating Chat Completion from Fireworks AI to Sarvam

> Request fields, reasoning, Responses API, and Fireworks-only features to change when moving chat traffic from Fireworks AI to Sarvam's /v2 API, with before/after code.

*Last updated: October 23, 2026*

This guide covers moving Fireworks AI Chat Completions and Responses calls for open-weight
models to Sarvam's [`/v2` API](/api/token-factory/chat-completions).

> **Tip**
>
> **In short:** change `base_url`, `api_key`, and `model`. Reasoning comes back in
> `reasoning_content` on both platforms. Remove Fireworks-only fields such as
> `prompt_truncate_len` and `perf_metrics_in_response`, because Sarvam returns `400` for
> request fields it doesn't support. Set `max_tokens` explicitly, and send the full history
> on every Responses call.

## Migration checklist

1. Create an API key in the [Sarvam dashboard](https://indus.sarvam.ai/key-management?ref=docs).
2. Change `base_url` to `https://api.sarvam.ai/v2` and `api_key` to your Sarvam key.
3. Replace each model ID using the [model ID table](/api/token-factory/migrations/from-fireworks/overview#model-ids). Fast, US, and deployment IDs map to the same Sarvam ID.
4. Use string values for `reasoning_effort` (`low`, `high`, `max`, or `none`) ([Reasoning](#reasoning)).
5. Remove Fireworks-only fields: `prompt_truncate_len`, `context_length_exceeded_behavior`, `perf_metrics_in_response`, and others ([list](#fireworks-only-fields-to-remove)).
6. Set `max_tokens` explicitly: only `glm5.3` defaults to `2048` on Sarvam.
7. Trim long conversations yourself: Sarvam doesn't truncate prompts.
8. If you use the Responses API, follow [Migrating the Responses API](/api/token-factory/migrations/from-fireworks/responses-api).
9. Run your tests and watch for `400` responses that name a field.

## Quick start

|             | Fireworks AI                            | Sarvam                                                                                                |
| ----------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Base URL    | `https://api.fireworks.ai/inference/v1` | `https://api.sarvam.ai/v2`                                                                            |
| Auth header | `Authorization: Bearer <key>`           | `api-subscription-key: <key>` or `Authorization: Bearer <key>`                                        |
| Model ID    | `accounts/fireworks/models/kimi-k3`     | `kimi-k3` (see the [model ID table](/api/token-factory/migrations/from-fireworks/overview#model-ids)) |

#### Before (Fireworks)

#### Python (OpenAI SDK)

```python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_FIREWORKS_API_KEY",
    base_url="https://api.fireworks.ai/inference/v1",
)

response = client.chat.completions.create(
    model="accounts/fireworks/models/kimi-k3",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Suggest a name for a coffee shop in Bengaluru."},
    ],
    reasoning_effort="low",
    extra_body={"prompt_truncate_len": 100000},
)

print(response.choices[0].message.content)
```

#### JavaScript (OpenAI SDK)

```javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "YOUR_FIREWORKS_API_KEY",
  baseURL: "https://api.fireworks.ai/inference/v1",
});

const response = await client.chat.completions.create({
  model: "accounts/fireworks/models/kimi-k3",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Suggest a name for a coffee shop in Bengaluru." },
  ],
  reasoning_effort: "low",
  prompt_truncate_len: 100000,
});

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

#### cURL

```bash
curl https://api.fireworks.ai/inference/v1/chat/completions \
  -H "Authorization: Bearer YOUR_FIREWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "accounts/fireworks/models/kimi-k3",
    "messages": [{"role": "user", "content": "Suggest a name for a coffee shop in Bengaluru."}],
    "reasoning_effort": "low",
    "prompt_truncate_len": 100000
  }'
```

#### After (Sarvam)

#### Python (OpenAI SDK)

```python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_SARVAM_API_KEY",
    base_url="https://api.sarvam.ai/v2",
)

response = client.chat.completions.create(
    model="kimi-k3",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Suggest a name for a coffee shop in Bengaluru."},
    ],
    reasoning_effort="low",
    max_tokens=2000,
)

print(response.choices[0].message.content)
```

#### JavaScript (OpenAI SDK)

```javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "YOUR_SARVAM_API_KEY",
  baseURL: "https://api.sarvam.ai/v2",
});

const response = await client.chat.completions.create({
  model: "kimi-k3",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Suggest a name for a coffee shop in Bengaluru." },
  ],
  reasoning_effort: "low",
  max_tokens: 2000,
});

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

#### Python (Sarvam SDK)

```python
from sarvamai import SarvamAI

client = SarvamAI(api_subscription_key="YOUR_SARVAM_API_KEY")

response = client.chat.completions_v2(
    model="kimi-k3",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Suggest a name for a coffee shop in Bengaluru."},
    ],
    reasoning_effort="low",
    max_tokens=2000,
)

print(response.choices[0].message.content)
```

#### JavaScript (Sarvam SDK)

```javascript
import { SarvamAIClient } from "sarvamai";

const client = new SarvamAIClient({ apiSubscriptionKey: "YOUR_SARVAM_API_KEY" });

const response = await client.chat.completionsV2({
  model: "kimi-k3",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Suggest a name for a coffee shop in Bengaluru." },
  ],
  max_tokens: 2000,
  reasoning_effort: "low",
});

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

#### cURL

```bash
curl https://api.sarvam.ai/v2/chat/completions \
  -H "api-subscription-key: YOUR_SARVAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kimi-k3",
    "messages": [{"role": "user", "content": "Suggest a name for a coffee shop in Bengaluru."}],
    "reasoning_effort": "low",
    "max_tokens": 2000
  }'
```

## Reasoning

| Fireworks                                             | Sarvam                            | Note                                                                                                                       |
| ----------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `reasoning_effort: "low"` / `"high"` / `"max"`        | Same                              | Each model's default is listed under [Reasoning](/api/token-factory/models#reasoning).                                     |
| `reasoning_effort: "medium"` / `"xhigh"`              | Use `"low"`, `"high"`, or `"max"` | Accepted on some models and returns `400` on others, such as `glm5.3`.                                                     |
| `reasoning_effort: "none"` or `false`                 | `reasoning_effort: "none"`        | Turns thinking off on `deepseekv4-pro`, `mimo-v2.6-flash`, and `mimo-v2.6-pro`. `kimi-k3` and `glm5.3-flash` always think. |
| `reasoning_effort` as a token budget (`1024` or more) | Use an effort level               | Integer budgets above `100` return `400`.                                                                                  |
| `thinking: {"type": "disabled"}`                      | Same, via `extra_body`            | Works on the models that can turn thinking off. To control depth, use `reasoning_effort`.                                  |
| `reasoning_history`                                   | Remove                            | To keep reasoning across turns, send the earlier assistant `reasoning_content` back in `messages`.                         |
| `choices[].message.reasoning_content`                 | Same                              | Also `delta.reasoning_content` when streaming.                                                                             |

> **Note**
>
> On Fireworks, a `json_schema` response format turns reasoning off. On Sarvam, reasoning
> models keep reasoning when you use `response_format`, so leave room in `max_tokens`, or
> turn thinking off on models that support it.

## Fireworks-only fields to remove

Sarvam validates request fields and returns `400 invalid_request_error` with
`Unsupported parameter(s)` for fields it doesn't support, so leftover Fireworks options fail
loudly instead of being ignored.

| Fireworks field                                                                   | What to do on Sarvam                                                                                                        |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `prompt_truncate_len`                                                             | Remove. Trim old messages yourself before sending.                                                                          |
| `context_length_exceeded_behavior`                                                | Remove. Sarvam returns an error when the prompt plus `max_tokens` is longer than the context window, instead of truncating. |
| `perf_metrics_in_response`                                                        | Remove. Measure latency on your side. Sarvam returns token counts in `usage`.                                               |
| `response_format: {"type": "grammar"}`                                            | Use `response_format` with a `json_schema`. Sarvam supports `text`, `json_object`, and `json_schema`.                       |
| `typical_p`, `mirostat_target`, `mirostat_lr`                                     | Remove. Use `temperature`, `top_p`, or `top_k`.                                                                             |
| `raw_output`, `echo`, `return_token_ids`, `prompt_token_ids`, `safe_tokenization` | Remove. Not available.                                                                                                      |
| `prediction`, `logit_bias`                                                        | Remove. Not supported.                                                                                                      |
| `reasoning_history`                                                               | Remove (see [Reasoning](#reasoning)).                                                                                       |
| Model IDs with `accounts/.../deployments/...`                                     | Use the Sarvam model ID. There are no deployments to manage.                                                                |

## Parameter concept map

| Fireworks                                                     | Sarvam                                                               | Note                                                                                                                                                                                     |
| ------------------------------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `messages`, `temperature`, `top_p`, `top_k`, `stop`, `seed`   | Same                                                                 |                                                                                                                                                                                          |
| `max_tokens` (defaults to `2048`)                             | `max_tokens`                                                         | Set it explicitly. When it's omitted on Sarvam, generation isn't capped at `2048` (except on `glm5.3`).                                                                                  |
| `frequency_penalty`, `presence_penalty`, `repetition_penalty` | Same                                                                 |                                                                                                                                                                                          |
| `min_p`                                                       | Not supported                                                        | Remove it. The open-weight models accept only `0`, which is the same as leaving it out.                                                                                                  |
| `tools`, `tool_choice`, `parallel_tool_calls`                 | Same                                                                 | `tool_choice: "any"` is Fireworks-only; use `"required"`.                                                                                                                                |
| `response_format` (`json_object`, `json_schema`)              | Same                                                                 |                                                                                                                                                                                          |
| `logprobs`, `top_logprobs`                                    | Same                                                                 | `logprobs` must be `true` or `false`. Not supported on `glm5.3`.                                                                                                                         |
| `n`                                                           | Same                                                                 | Supported on most models. `temperature` must be above `0` when `n` > 1.                                                                                                                  |
| `prompt_cache_key`, `user`                                    | Accepted, except `prompt_cache_key` on `gemma4`, which returns `400` | For multi-turn caching on `gemma4`, send the [`x-session-affinity`](/api/token-factory/chat-completions#session-affinity-for-multi-turn-conversations) header.                           |
| `service_tier: "priority"`, Fast routers                      | Not needed                                                           | Sarvam has a single tier per model.                                                                                                                                                      |
| `stream: true`                                                | Same                                                                 | Usage arrives in the final chunk.                                                                                                                                                        |
| `image_url` content parts                                     | Same                                                                 | Inline base64 data URIs only, on models with image input. See each [model page](/api/token-factory/models).                                                                              |
| `input_audio` content parts                                   | Same, on the MiMo models                                             | `wav` or `mp3`. For FLAC, OGG, or Opus, send an `audio_url` part with a data URI. See [Media input](/api/token-factory/migrations/from-fireworks/overview#media-input-and-request-size). |
| `video_url` content parts                                     | Same, as a base64 data URI                                           | On the MiMo models and `kimi-k3` (beta, short clips). Sarvam doesn't fetch video URLs.                                                                                                   |

## Responses API

Fireworks stores responses and chains them with `previous_response_id`; Sarvam's Responses API is stateless, so you send the history in `input` instead. For base URL and field changes, reasoning items, function tools, and server-side tools, see [Migrating the Responses API from Fireworks](/api/token-factory/migrations/from-fireworks/responses-api).

## What's different by design

* **No deployments to manage.** Models that need an on-demand deployment on Fireworks, such
  as Gemma 4 31B and DeepSeek V4 Pro, are called by model ID on Sarvam.
* **Strict request validation.** Unsupported fields return `400` with the field named,
  instead of being dropped silently. `gemma4` is less strict: it accepts some fields, such as
  `prediction` and `logit_bias`, and ignores them.
* **No silent truncation.** Sarvam rejects a prompt that doesn't fit, rather than cutting
  old messages or lowering `max_tokens` for you.
* **Stateless Responses.** Your app keeps the conversation history, as with Chat
  Completions.

## Platform features without a direct equivalent

| Fireworks feature          | On Sarvam                                                                                                      |
| -------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Batch inference jobs       | Not available. Send requests concurrently within your [rate limits](/api/getting-started/pricing#rate-limits). |
| Fine-tuned and LoRA models | Not available on the `/v2` API.                                                                                |
| On-demand deployments      | Not needed. Every model is served by ID.                                                                       |
| US-only endpoint           | Not available.                                                                                                 |

## Full example

A wrapper with retries on `429` and `503`, which Fireworks returns when it sheds load and
Sarvam returns when a model is overloaded:

#### Before (Fireworks)

```python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_FIREWORKS_API_KEY",
    base_url="https://api.fireworks.ai/inference/v1",
)

def ask(prompt: str) -> str:
    response = client.chat.completions.create(
        model="accounts/fireworks/models/deepseek-v4p1-flash",
        messages=[{"role": "user", "content": prompt}],
        reasoning_effort="low",
        extra_body={"context_length_exceeded_behavior": "truncate"},
    )
    return response.choices[0].message.content
```

#### After (OpenAI SDK)

```python
import time
from openai import OpenAI, APIStatusError

client = OpenAI(
    api_key="YOUR_SARVAM_API_KEY",
    base_url="https://api.sarvam.ai/v2",
)

def ask(prompt: str) -> str:
    for attempt in range(3):
        try:
            response = client.chat.completions.create(
                model="deepseekv4.1-flash-1017",
                messages=[{"role": "user", "content": prompt}],
                reasoning_effort="low",
                max_tokens=2000,
            )
            return response.choices[0].message.content
        except APIStatusError as e:
            if e.status_code in (429, 503):
                time.sleep(2 ** attempt)  # back off, then retry
                continue
            raise  # 400, 402, 403 and 404 won't succeed on retry
    raise RuntimeError("Model is busy. Try again later.")
```

#### After (Sarvam SDK)

```python
import time
from sarvamai import SarvamAI
from sarvamai.core.api_error import ApiError

client = SarvamAI(api_subscription_key="YOUR_SARVAM_API_KEY")

def ask(prompt: str) -> str:
    for attempt in range(3):
        try:
            response = client.chat.completions_v2(
                model="deepseekv4.1-flash-1017",
                messages=[{"role": "user", "content": prompt}],
                reasoning_effort="low",
                max_tokens=2000,
            )
            return response.choices[0].message.content
        except ApiError as e:
            if e.status_code in (429, 503):
                time.sleep(2 ** attempt)  # back off, then retry
                continue
            raise  # 400, 402, 403 and 404 won't succeed on retry
    raise RuntimeError("Model is busy. Try again later.")
```

## Common mistakes

#### Keeping the accounts/fireworks/models/ prefix

`accounts/fireworks/models/kimi-k3` returns `404` on Sarvam. Use `kimi-k3`. See the
[model ID table](/api/token-factory/migrations/from-fireworks/overview#model-ids).

#### Relying on the 2048-token max_tokens default

Fireworks caps output at `2048` tokens when `max_tokens` is omitted. On Sarvam only `glm5.3` does, so
long answers can run much longer. Set `max_tokens` explicitly, leaving room for reasoning
tokens.

#### Expecting long prompts to be truncated

Sarvam returns an error instead of truncating. Trim the conversation before sending.

#### Chaining Responses calls with previous_response_id

Sarvam doesn't store responses. Keep the history in your app and send it in `input`, as
in the [Responses example](#responses-api).

#### Leaving Fireworks fields in extra_body

Fields like `prompt_truncate_len` and `perf_metrics_in_response` are often passed
through `extra_body`. Sarvam returns `400` with the field name; remove each one it names.

## See also

* [Migration overview](/api/token-factory/migrations/from-fireworks/overview): base URL, auth, and model IDs
* [Chat Completion overview](/api/token-factory/chat-completions)
* [Responses API guide](/api/token-factory/responses-api)
* [Open-Weight Models](/api/token-factory/models)
* [Errors & Troubleshooting](/api/getting-started/errors-troubleshooting)