DeepSeek API Migration: Replace deepseek-chat and deepseek-reasoner

Replace retired DeepSeek model names, set the intended thinking mode, and update Node.js or Python requests, streaming, tools, and deployment settings.

To replace deepseek-chat, use deepseek-flash and explicitly disable thinking. To replace deepseek-reasoner, use deepseek-flash with thinking enabled. Your existing DeepSeek API key, base URL, and Chat Completions endpoint can stay the same.

The important change is that the model name and the thinking setting are now separate choices. Keeping the same thinking mode helps you preserve the kind of interaction your application expects, but it does not guarantee the same answers, speed, or token usage. Start with the request change, then check the features your application actually uses.

DeepSeek announced the retirement of the two legacy aliases for July 24, 2026 at 15:59 UTC in its V4 release notice. That date has passed. The current official quick start recommends deepseek-flash, which serves V4.1-Flash. This guide covers applications calling DeepSeek’s hosted API; a third-party provider or a locally hosted model may use different names.

Which model name should you use?

What your application sendsReplacement for a Flash migrationWhat to keep explicit
deepseek-chatdeepseek-flashthinking: {"type": "disabled"}
deepseek-reasonerdeepseek-flashthinking: {"type": "enabled"}
deepseek-v4-flashdeepseek-flashKeep your intended thinking mode; the old name no longer selects the old V4-Flash model.

If you already migrated to deepseek-v4-flash, the current documentation says that name is still accepted and routes to V4.1-Flash. The same applies to deepseek-v4-flash-vision-exp. Use deepseek-flash in new configuration rather than relying on those compatibility names. The original deepseek-chat and deepseek-reasoner aliases are a different retirement; do not treat all four names as having the same status.

deepseek-v4-pro remains a separate documented option. DeepSeek’s updated change log confirms continued V4 Pro API service after September 14, superseding the earlier plan to route Pro requests to Flash. Choose Pro because it suits your workload, not because “reasoner” must mean “Pro.” The examples below use Flash so you can complete the migration without also changing model tiers.

In this guide

What stays the same · Find the old settings · First request · Node.js · Python · Thinking and parameters · Streaming and tools · Rollout · Troubleshooting · FAQ

What changes—and what stays the same

For an existing direct DeepSeek Chat Completions integration, keep https://api.deepseek.com as the base URL and POST /chat/completions as the operation. Keep your valid DeepSeek key on the server. A model migration does not, by itself, require a new key or a switch to the Responses or Anthropic API format. DeepSeek documents the current connection settings in its quick start.

Keep the conversation’s supported system, user, assistant, and tool messages, too. The parts that deserve attention are the model setting, thinking controls, response parser, and any assumptions about tools or output length. For example, a parser that only reads the first streamed text fragment may appear broken when the new configuration starts by sending reasoning.

A larger context window is not a reason to remove your existing history management during this change. First get the same application workflow working with the new request. You can review larger inputs, image support, or a different API format separately, when you can tell which change caused any new problem.

Find the old setting in code and connected apps

Search the application and its deployed configuration. The value may live in an environment variable, a worker’s settings, a notebook, a gateway route, or a fallback list even after the main source file has been updated. If you use ripgrep, this command finds the two retired aliases and the earlier V4-Flash names without searching installed packages or Git’s internal files:

rg -n --hidden --glob '!node_modules' --glob '!.git' \
  'deepseek-chat|deepseek-reasoner|deepseek-v4-flash' .

Review each match before replacing it. An archived changelog can legitimately mention an old name; a live fallback configuration should not send it. Restart or redeploy services that read their model setting only at startup, and check background workers as well as the main web application.

In a chat client, automation platform, or coding tool, open its provider settings and check the provider, base URL, model, and thinking option together. For the direct DeepSeek service, enter the documented model ID or update the integration if its picker only offers retired names. If the tool uses a gateway or another provider, use that provider’s documented identifier instead of assuming DeepSeek’s direct API name will work there.

Keep the model and thinking setting together

For an application with both ordinary chat and reasoning tasks, store the two choices in one configuration object. That makes it harder for one deployment setting to change the model while silently changing the mode:

const profiles = {
  chat: {
    model: "deepseek-flash",
    thinking: { type: "disabled" },
  },
  reasoner: {
    model: "deepseek-flash",
    thinking: { type: "enabled" },
    reasoning_effort: "high",
  },
};

const profileName = process.env.DEEPSEEK_PROFILE ?? "chat";
if (!Object.hasOwn(profiles, profileName)) {
  throw new Error("DEEPSEEK_PROFILE must be chat or reasoner");
}
const profile = profiles[profileName];

This is an optional application pattern, not a required DeepSeek feature. If you have one request in one script, changing that request directly is enough. Avoid sending a contradictory reasoning_effort from a shared default alongside your chosen thinking value.

Make one request with the new configuration

With DEEPSEEK_API_KEY already set in a Bash or similar shell, this is a complete non-thinking request. It uses ordinary API credits if you run it. Keep the key out of browser-side code and public files.

curl https://api.deepseek.com/chat/completions   -H "Content-Type: application/json"   -H "Authorization: Bearer ${DEEPSEEK_API_KEY}"   -d '{
    "model": "deepseek-flash",
    "messages": [
      {"role": "user", "content": "Explain what an API does in one sentence."}
    ],
    "thinking": {"type": "disabled"},
    "max_tokens": 512,
    "stream": false
  }'

Look for an assistant answer in choices[0].message.content and inspect choices[0].finish_reason. For this simple text request, stop indicates normal completion; length means generation reached a limit. The exact sentence will vary. To try the reasoning path, enable thinking and give the request a larger output budget, such as 4096, because reasoning also uses generated tokens.

Check the available model IDs

If your client reports that the model is unavailable, compare its configured provider with the documented DeepSeek base URL. You can also use the List Models endpoint with the same key:

curl https://api.deepseek.com/models   -H "Authorization: Bearer ${DEEPSEEK_API_KEY}"

A successful request shows that this connection and configuration work. It does not establish that a longer conversation, streamed reply, or tool workflow has migrated correctly; check the relevant path next.

Update Node.js requests

These examples use the openai JavaScript package against DeepSeek’s API. Install it with npm install openai if it is not already in the project, and keep your existing dependency lockfile under version control. Save the complete example as migrate.mjs and run it with node migrate.mjs after setting the key in the process environment.

Replace a deepseek-chat request

An older request might only specify model: "deepseek-chat" alongside its messages. Use this configuration for a non-thinking replacement:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.DEEPSEEK_API_KEY,
  baseURL: "https://api.deepseek.com",
});

const response = await client.chat.completions.create({
  model: "deepseek-flash",
  messages: [
    { role: "user", content: "Explain what an API does in one sentence." },
  ],
  thinking: { type: "disabled" },
  max_tokens: 512,
  stream: false,
});

const choice = response.choices[0];
if (!choice || choice.finish_reason !== "stop") {
  throw new Error(`Request did not finish normally: ${choice?.finish_reason}`);
}
const answer = choice.message.content;
if (typeof answer !== "string" || !answer.trim()) {
  throw new Error("The response contained no final answer");
}
console.log(answer);

The explicit disabled setting matters: thinking is enabled by default. A model-name-only edit can therefore make an ordinary chat request start reasoning, changing response timing and output usage.

Replace a deepseek-reasoner request

Use the same client, but replace the request object with the following. The answer and normal-completion check above still apply to this text-only example:

const response = await client.chat.completions.create({
  model: "deepseek-flash",
  messages: [
    { role: "user", content: "Compare processing a report now with scheduling it overnight." },
  ],
  thinking: { type: "enabled" },
  reasoning_effort: "high",
  max_tokens: 4096,
  stream: false,
});

The final answer is still message.content. Reasoning is returned separately in message.reasoning_content; do not substitute it for the final answer. In TypeScript, the SDK’s OpenAI types may not declare DeepSeek-specific fields such as thinking. Extend the request type for those fields rather than hiding all checking with any. The Node.js and TypeScript guide covers that setup and complete streaming examples.

Update Python requests

For Python, install the client with python -m pip install openai if needed. DeepSeek’s examples pass its thinking object through the SDK’s extra_body argument. With your existing key in DEEPSEEK_API_KEY, save this as migrate.py and run python migrate.py:

import os
from openai import OpenAI

with OpenAI(
    api_key=os.environ["DEEPSEEK_API_KEY"],
    base_url="https://api.deepseek.com",
) as client:
    response = client.chat.completions.create(
        model="deepseek-flash",
        messages=[{
            "role": "user",
            "content": "Explain what an API does in one sentence.",
        }],
        max_tokens=512,
        stream=False,
        extra_body={"thinking": {"type": "disabled"}},
    )

choice = response.choices[0]
if choice.finish_reason != "stop":
    raise RuntimeError(f"Request did not finish normally: {choice.finish_reason}")
answer = choice.message.content
if not isinstance(answer, str) or not answer.strip():
    raise RuntimeError("The response contained no final answer")
print(answer)

For a former deepseek-reasoner request, replace the call inside the client block with this one. Keep the completion and answer checks after it:

response = client.chat.completions.create(
    model="deepseek-flash",
    messages=[{
        "role": "user",
        "content": "Compare processing a report now with scheduling it overnight.",
    }],
    reasoning_effort="high",
    max_tokens=4096,
    stream=False,
    extra_body={"thinking": {"type": "enabled"}},
)

If you need the separate reasoning field, read it with getattr(choice.message, "reasoning_content", None). Ordinary conversation and tool-enabled history have different replay requirements, explained below. For environment setup, asynchronous requests, and handling client exceptions, use the Python SDK guide.

Review thinking, sampling, and output limits

Old parameter settings can still be accepted without doing what your application expects. Review them against the current Chat Completions reference, especially if an earlier integration used temperature or penalties to control the response.

SettingWhat changes for your application
Thinking modethinking is enabled by default, with high effort. Set enabled or disabled deliberately.
Effortreasoning_effort: "none" disables thinking; low, high, and max enable it. Remove conflicting inherited settings.
Temperaturetemperature works in non-thinking mode and is ignored in thinking mode. Keep a task-appropriate value only where it takes effect.
Top-ptop_p works only in thinking mode, with an effective range of 0.95–1. Values below 0.95 are treated as 0.95; in non-thinking mode it is fixed at 1. Do not expect a carried-over low value to have the same effect.
Penaltiespresence_penalty and frequency_penalty are deprecated and ineffective. Remove them; turning off thinking will not restore them.
Output budgetmax_tokens limits generated tokens; input plus output must fit the context window. Set a budget for the task and handle incomplete output.

The Thinking Mode guide also documents compatibility effort mappings: minimal maps to low, medium and xhigh to high, and ultra to max. For new Chat Completions code, prefer the reference’s direct values: none, low, high, or max. An accepted compatibility label does not create another effort level.

Both listed models have a 1M context window and a maximum output of 384K tokens. That is a ceiling, not the default response length. The Chat Completions reference gives defaults of 8K in non-thinking mode, 64K in thinking mode, and 128K for max effort. A small output cap may be enough for a short answer without thinking but leave too little room for both reasoning and the answer with thinking enabled.

Use the existing task budget as a starting point, then examine incomplete replies before raising it. More output allowance can increase cost and waiting time; it does not force a useful answer. The context and output limits guide explains how to budget input, reasoning, and final output together.

Check the response paths your application uses

Streaming: keep reasoning and the answer separate

In Chat Completions streaming, answer text arrives in delta.content and reasoning in delta.reasoning_content. An early chunk without answer text is not necessarily an empty response. Accumulate the appropriate fields and inspect the terminal finish_reason. If the connection ends without a terminal result, treat the response as incomplete.

The current reference places usage on the last chunk before data: [DONE]. That chunk contains one choice with no new content and a non-null finish reason. There is no separate usage-only chunk with an empty choices array. If you have a custom parser copied from another provider, update that assumption. Also ignore SSE keep-alive comments rather than treating them as JSON errors; DeepSeek describes them in its connection guidance.

Tools: preserve the assistant messages you need to replay

If a request carries tools, DeepSeek requires the complete returned reasoning_content from all previous turns to be passed back, including turns where no tool was called. A migration that strips all reasoning from history can therefore fail on the next request. Without tools, earlier reasoning does not need to be sent back and is ignored if supplied. These rules are documented in the Thinking Mode guide.

In an existing JavaScript tool loop, append the complete assistant message before its tool results. This fragment assumes your application has already validated the function name and arguments and executed the allowed function:

// Append once, before adding results for any returned tool calls.
messages.push(response.choices[0].message);

// Append one result for each tool call after validating and executing it.
messages.push({
  role: "tool",
  tool_call_id: toolCall.id,
  content: JSON.stringify(toolResult),
});

Keep the assistant message even when it has no tool call, and make sure your database or message serializer preserves its reasoning field. Do not blindly replay reasoning produced by a different model or a different API format; begin a fresh conversation if that history is incompatible. The tool-calling guide covers the complete cycle.

Also check tool_choice: the current API rejects required and named-function choices in thinking mode. Disable thinking for those choices, or use an allowed selection mode if it fits the application. A normal tool-call response has finish_reason: "tool_calls"; the simple text-only checks in the examples above should not be copied unchanged into a tool loop.

JSON, completion modes, and cache

For JSON mode, keep response_format: {"type": "json_object"} and an instruction asking for JSON. Parse the returned text and validate the fields your application needs. A response truncated by the output limit may still be incomplete, so check its finish reason before accepting it.

The model feature table lists Chat Prefix Completion and FIM Completion for both current models, with FIM restricted to non-thinking mode. If your application uses either beta completion route, retain that route’s request structure and verify it separately; the Chat Completions examples here are not a replacement for a FIM request.

Context caching is automatic and needs no migration switch. Keep stable shared content at the beginning of requests, then read usage.prompt_cache_hit_tokens and usage.prompt_cache_miss_tokens to see what was actually cached. Do not budget on the assumption that a renamed model inherits every previous cache hit: the official caching guide describes hits as best effort.

Move the updated configuration into production

For a personal script, a representative request and a check of its output may be sufficient. For an application with real users, first run the updated configuration in a test environment, then introduce it to a limited part of your traffic. Keep the prompt and workflow unchanged initially so that you can assess the migration itself.

Choose checks that match the application

  • Text generation: the answer is readable, meets the expected format, and finishes normally within the application’s timeout.
  • Multi-turn chat: send a follow-up that needs the previous answer and confirm that your message history is preserved.
  • Streaming: reasoning and final text reach the intended place; completion and a dropped connection are handled differently.
  • Tools: check a turn with a call and one without a call, then a follow-up. Preserve reasoning history in both paths when tools are present.
  • Structured output: the JSON parses and passes your application’s schema or field checks.
  • Limits and failures: verify how your application handles a short output cap, timeouts, and retriable errors. Never execute a business action twice just because a request was retried.

These are checks for your own deployment, not a requirement to build a benchmark suite. You do not need to add image input or test a feature the application does not use.

Watch cost, timing, and errors

Record the requested model, selected mode, returned model field, finish reason, request timing, and token usage. Compare representative requests against the budget and response time your application can accept. Output usage includes reasoning tokens; do not add them a second time when calculating total output cost. Use the current USD rate sheet, including cache and peak/off-peak distinctions, rather than an old V4 launch price.

Account concurrency also matters: the official limits page lists 2,500 concurrent requests for Flash and 500 for Pro. These are concurrent connections per account and model, not requests per minute and not separate quotas for each key. Pace work and use bounded retries with backoff for temporary failures. Collect useful diagnostics without logging keys or private prompts.

Keep a known working application version and the updated model configuration available for rollback. Reverting code should not restore deepseek-chat or deepseek-reasoner as a fallback. If the new deployment fails, restore a version already checked with a supported model, or pause the affected feature while you fix the issue.

Troubleshoot the migration

What you seeWhat to check
The old model still appears in requestsCheck deployed environment variables, background workers, saved provider profiles, gateways, and fallback lists. Restart services after changing startup settings.
A chat replacement now sends reasoningSet thinking to disabled and remove any shared effort setting that enables it. Do not rely on a model-name-only change.
The reply seems empty or is cut offSeparate reasoning from final content, inspect finish_reason, and check the output budget and timeout. A partial response is not a completed answer.
Sampling settings appear ineffectiveUse temperature in non-thinking mode and top_p only in thinking mode. Remove deprecated penalty parameters.
HTTP 400 after a tool-enabled turnCheck full reasoning history, assistant/tool message order, and whether tool_choice forces a call while thinking is enabled. Read the actual error details.
HTTP 401 or 402Verify the correct server-side key for 401; check the API account balance for 402. Renaming a model does not fix either problem.
HTTP 422Check parameter names, types, values, and the payload that actually reached the provider.
HTTP 429, 500, or 503Reduce concurrency for 429. For temporary server failures, wait and retry within a limit; escalating retries can worsen overload.

DeepSeek’s error reference is the source for the HTTP categories above. If a valid minimal request works but the full application fails, add its extra parameters and history back gradually to find the difference. If the minimal request also fails, keep the error body and a safe request identifier for support. The API error guide provides more detailed fixes.

Frequently asked questions

Is deepseek-chat the same as DeepSeek’s chat website?

No. In this guide, deepseek-chat is an old API model identifier. Its retirement concerns application requests, not the name of the consumer chat service. Changing a setting in a developer integration does not change your account on the chat website.

Can I replace only the model name?

Set the thinking choice as well, particularly when replacing deepseek-chat. The current model defaults to thinking, whereas that legacy alias selected non-thinking mode during the documented V4 transition. Even with the same mode, review any streaming, tool, or structured-output behavior the application depends on.

What if I already use deepseek-v4-flash?

The current quick start says it is accepted as a compatibility name for V4.1-Flash. Change it to deepseek-flash and keep your intended mode explicit. This updates the identifier; it does not bring back the retired V4-Flash model.

Does deepseek-reasoner still mean the original R1 model?

Do not use the old alias as a way to pin R1. DeepSeek’s V4 release notice described it as routing to V4-Flash thinking mode before the retirement cutoff. If you need a particular open-weight model or version, select a deployment that explicitly offers it; migrating to the hosted Flash API is a different choice.

Which error should I expect from a retired alias?

The retirement notice does not promise one specific HTTP status code. Read the actual provider response rather than using an assumed 400 or 404 as your only check. If a gateway still accepts an old name, it may be translating the request; check that provider’s configuration and avoid keeping a retired alias in direct DeepSeek requests.

Official references

The quick start identifies the current connection settings; the Chat Completions reference defines request and response fields; and the change log explains model changes. Use the reference for the API format you actually send, especially if a framework converts requests for you.

Start with one working path

Make the model and thinking choice explicit in the application’s simplest request, then follow that same request through the response parser and any conversation history. Once that path works, check the additional features you already use and roll the configuration out at a pace you can observe. That gives you a clear migration to a supported model—and a useful starting point if something needs fixing.

Privacy and cookie settings