Quick answer: You can use the OpenAI SDK with DeepSeek by keeping the openai SDK package, changing the API key to a DeepSeek API key, setting the OpenAI-format base URL to https://api.deepseek.com, and using the current DeepSeek API model IDs: deepseek-v4-flash or deepseek-v4-pro.
Use deepseek-v4-flash for fast, economical chat, summaries, extraction, JSON Output, routine coding help, classification, support bots, and high-volume workloads. Use deepseek-v4-pro for harder reasoning, complex coding, long-context analysis, tool planning, agentic workflows, and higher-value production tasks.
Independent note: Chat-Deep.ai is an independent DeepSeek guide and browser access site. It is not affiliated with DeepSeek, DeepSeek.com, the official DeepSeek app, the official DeepSeek developer platform, or OpenAI.
Last verified: April 25, 2026.
Current DeepSeek API snapshot
- Current API model IDs:
deepseek-v4-flashanddeepseek-v4-pro.- Current API generation: DeepSeek-V4.
- OpenAI-format base URL:
https://api.deepseek.com.- Anthropic-format base URL:
https://api.deepseek.com/anthropic. This page focuses on OpenAI SDK usage.- Context length: 1M tokens.
- Maximum output: 384K tokens.
- Thinking mode: supported on both current API models.
- Non-thinking mode: supported on both current API models.
- JSON Output: supported on both current API models.
- Tool Calls: supported on both current API models.
- Chat Prefix Completion is a beta feature.
- FIM Completion is supported in non-thinking mode only.
deepseek-chatanddeepseek-reasonerare legacy compatibility aliases, not recommended model names for new integrations.- DeepSeek states that
deepseek-chatanddeepseek-reasonerwill be retired after July 24, 2026, 15:59 UTC.
Quick migration: what do you change?
For a basic OpenAI SDK to DeepSeek migration, do not rewrite your whole client layer first. Keep the OpenAI SDK package, change the provider configuration, then test DeepSeek-specific behavior such as thinking mode, JSON Output, Tool Calls, streaming usage, pricing, and error handling.
| Item | OpenAI SDK app | DeepSeek API version | What to verify |
|---|---|---|---|
| SDK package | openai | Keep using the OpenAI SDK package for DeepSeek Chat Completions in OpenAI-compatible format. | Install and run the SDK server-side. |
| API key | Usually OPENAI_API_KEY | Use a DeepSeek API key, usually stored as DEEPSEEK_API_KEY. | Do not mix OpenAI and DeepSeek keys. |
| Base URL | Default OpenAI endpoint | https://api.deepseek.com | Confirm your requests are sent to DeepSeek. |
| Model | OpenAI model ID | deepseek-v4-flash or deepseek-v4-pro | Use current DeepSeek API model IDs in new examples. |
| Endpoint style | chat.completions.create | chat.completions.create | DeepSeek currently documents Chat Completions for OpenAI-format calls. |
| Provider-specific fields | OpenAI typed parameters | DeepSeek fields such as thinking may be provider-specific. | In Python, use extra_body. In TypeScript, extra fields may need // @ts-expect-error or a typed wrapper. |
| Streaming | stream=True or stream: true | Supported through streaming chat completions. | Capture the final usage-bearing chunk if you need token accounting. |
| JSON Output | response_format | {"type": "json_object"} | Prompt for JSON explicitly and validate the parsed result. |
| Tool Calls | tools and tool_choice | Supported by current DeepSeek API models. | Your application executes tools; the model only proposes tool calls. |
Compatibility warning: DeepSeek uses an OpenAI-compatible API format, but that does not mean every OpenAI endpoint, product, model, parameter, helper, or platform feature exists in DeepSeek. Treat the OpenAI SDK as the client library and DeepSeek as the API provider.
Table of contents
- Quick migration: what do you change?
- Install the OpenAI SDK
- DeepSeek base URL explained
- Current DeepSeek model selection
- Python example
- Node.js / TypeScript example
- Migration checklist
- Thinking and non-thinking mode
- Streaming responses
- JSON Output
- Tool Calls / function calling
- Tool Calls in thinking mode
- Strict mode for Tool Calls
- Token usage and cost
- Legacy aliases
- Environment variables and security
- Error handling and retries
- Common migration mistakes
- When should you use the OpenAI SDK with DeepSeek?
- Related DeepSeek developer guides
- Official sources
- FAQ
Install the OpenAI SDK
OpenAI provides official SDKs for Python and JavaScript / TypeScript. DeepSeek’s API documentation shows OpenAI-compatible examples using the OpenAI SDK with a DeepSeek API key and the DeepSeek base URL. This makes the SDK useful for provider migration tests, server-side chat apps, and multi-provider applications.
Python install
pip install openai
Node.js / TypeScript install
npm install openai
Keep DeepSeek requests server-side. Do not expose a DeepSeek API key in browser JavaScript, static frontend code, public repositories, mobile bundles, screenshots, or logs.
DeepSeek base URL explained
The base_url or baseURL setting tells the OpenAI SDK where to send requests. For DeepSeek OpenAI-format API calls, set it to https://api.deepseek.com.
| Environment | SDK option | Value | Example |
|---|---|---|---|
| Python | base_url | https://api.deepseek.com | OpenAI(api_key=..., base_url="https://api.deepseek.com") |
| Node.js / TypeScript | baseURL | https://api.deepseek.com | new OpenAI({ apiKey: ..., baseURL: "https://api.deepseek.com" }) |
Common base URL mistakes
- Using a DeepSeek API key with the default OpenAI endpoint.
- Using an OpenAI API key with the DeepSeek base URL.
- Using
base_urlin Node.js instead ofbaseURL. - Using
baseURLin Python instead ofbase_url. - Copying older examples that still present legacy aliases as primary model names.
- Assuming all OpenAI SDK options behave identically with DeepSeek.
Current DeepSeek model selection
For new OpenAI SDK examples with DeepSeek, use deepseek-v4-flash or deepseek-v4-pro. Do not present deepseek-chat or deepseek-reasoner as the current primary model IDs for new integrations.
| Model | Use it for | Recommended mode | Notes |
|---|---|---|---|
deepseek-v4-flash | Fast chat, summaries, extraction, JSON Output, routine coding help, classification, support bots, and cost-sensitive applications. | Usually start with non-thinking mode for simple workloads. | Best first model for most OpenAI SDK migration tests. |
deepseek-v4-pro | Hard reasoning, complex coding, long-context analysis, tool planning, agentic workflows, and high-value production tasks. | Usually use thinking mode for difficult tasks. | Use when quality and reasoning matter more than the lowest token price. |
deepseek-chat | Legacy compatibility only. | Currently maps to non-thinking behavior through the V4-Flash compatibility path. | Scheduled for retirement after July 24, 2026, 15:59 UTC. |
deepseek-reasoner | Legacy compatibility only. | Currently maps to thinking behavior through the V4-Flash compatibility path. | Scheduled for retirement after July 24, 2026, 15:59 UTC. |
Python example: OpenAI SDK with DeepSeek
This minimal Python example uses the OpenAI SDK, a DeepSeek API key, the DeepSeek base URL, and deepseek-v4-flash in non-thinking mode.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "system", "content": "You are a concise developer assistant."},
{
"role": "user",
"content": "Explain how to call DeepSeek with the OpenAI SDK in one paragraph.",
},
],
stream=False,
extra_body={"thinking": {"type": "disabled"}},
)
print(response.choices[0].message.content)
Line-by-line notes
from openai import OpenAIimports the OpenAI Python SDK client.DEEPSEEK_API_KEYis a local environment variable for your DeepSeek API key.base_url="https://api.deepseek.com"sends requests to DeepSeek.model="deepseek-v4-flash"uses the current economical DeepSeek API model.extra_body={"thinking": {"type": "disabled"}}makes the example explicitly non-thinking.stream=Falsereturns one complete response object.
Node.js / TypeScript example
In Node.js and TypeScript, use baseURL with a capital URL. DeepSeek-specific request fields such as thinking are not part of OpenAI’s standard typed parameter set, so TypeScript users may need // @ts-expect-error or a typed wrapper while still sending the field at runtime.
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com",
});
async function main() {
const completion = await client.chat.completions.create({
model: "deepseek-v4-flash",
messages: [
{ role: "system", content: "You are a concise developer assistant." },
{
role: "user",
content: "Show the minimal changes needed to use DeepSeek with the OpenAI SDK.",
},
],
stream: false,
// DeepSeek provider-specific parameter.
// @ts-expect-error OpenAI SDK types may not include DeepSeek-specific fields.
thinking: { type: "disabled" },
});
console.log(completion.choices[0].message.content);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
Node.js notes
- Use
npm install openaibefore running the example. - Use
apiKey, notapi_key, in Node.js. - Use
baseURL, notbase_url, in Node.js. - Keep the call server-side. Do not expose your DeepSeek API key in frontend code.
- For TypeScript, provider-specific DeepSeek fields may need
// @ts-expect-error, a cast, or your own wrapper type.
Migration checklist: OpenAI SDK app to DeepSeek API
Use this table as a practical checklist. Start with the smallest possible change, then test features one by one.
| Migration item | Before: OpenAI-only app | After: DeepSeek with OpenAI SDK | What to test |
|---|---|---|---|
| Client initialization | OpenAI() with the default endpoint. | OpenAI(..., base_url="https://api.deepseek.com") in Python or new OpenAI({ baseURL: "https://api.deepseek.com" }) in Node.js. | Confirm requests hit DeepSeek, not OpenAI. |
| API key | OPENAI_API_KEY | DEEPSEEK_API_KEY | Check for 401 errors caused by the wrong key. |
| Model name | OpenAI model ID. | deepseek-v4-flash or deepseek-v4-pro. | Do not use legacy aliases in new code. |
| Thinking mode | OpenAI-specific reasoning settings may differ. | thinking={"type": "enabled"} or thinking={"type": "disabled"}. | Check output shape, latency, usage, and whether reasoning_content appears. |
| Streaming | stream=True or stream: true. | Same concept, DeepSeek Chat Completions stream chunks. | Handle empty choices and final usage chunk when requested. |
| JSON Output | response_format. | {"type": "json_object"}. | Prompt for JSON, set a sensible max_tokens, parse, and validate. |
| Tool Calls | tools and tool_choice. | Supported by current DeepSeek API models. | Validate tool arguments before executing tools. |
| Pricing | OpenAI pricing. | DeepSeek pricing. | Do not reuse OpenAI cost assumptions. |
| Error handling | OpenAI provider errors. | DeepSeek HTTP status codes surfaced through the SDK. | Handle 400, 401, 402, 422, 429, 500, and 503. |
Thinking and non-thinking mode
DeepSeek supports both thinking and non-thinking modes on the current API models. Thinking mode is useful for harder reasoning, complex coding, tool planning, long-context analysis, and agentic workflows. Non-thinking mode is better for fast chat, extraction, short summaries, JSON-only tasks, classification, and cost-sensitive routes.
Python: thinking mode with deepseek-v4-pro
from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[
{
"role": "user",
"content": "Analyze the tradeoffs of context caching in an AI support chatbot.",
}
],
reasoning_effort="high",
extra_body={"thinking": {"type": "enabled"}},
)
message = response.choices[0].message
print("Reasoning field:", getattr(message, "reasoning_content", None))
print("Final answer:", message.content)
Python: non-thinking mode with deepseek-v4-flash
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "user", "content": "Summarize this support ticket in three bullet points."}
],
extra_body={"thinking": {"type": "disabled"}},
)
print(response.choices[0].message.content)
For user-facing products, usually display message.content. Treat reasoning_content as a separate technical field for debugging, tracing, or advanced internal workflows, not as ordinary end-user copy.
Streaming responses
Use streaming when you want chat UI text to appear incrementally. In DeepSeek Chat Completions, streamed responses are sent as server-sent events and end with data: [DONE]. If you need token accounting during streaming, request usage and capture the final usage-bearing chunk.
Python streaming example
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
stream = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{
"role": "user",
"content": "Write a short checklist for migrating OpenAI SDK code to DeepSeek.",
}
],
stream=True,
stream_options={"include_usage": True},
extra_body={"thinking": {"type": "disabled"}},
)
final_usage = None
for chunk in stream:
if getattr(chunk, "usage", None) is not None:
final_usage = chunk.usage
continue
if not chunk.choices:
continue
delta = chunk.choices[0].delta
if getattr(delta, "content", None):
print(delta.content, end="", flush=True)
if final_usage is not None:
print()
print("Usage:", final_usage)
Node.js streaming example
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com",
});
const stream = await client.chat.completions.create({
model: "deepseek-v4-flash",
messages: [
{
role: "user",
content: "Write a short checklist for migrating OpenAI SDK code to DeepSeek.",
},
],
stream: true,
stream_options: { include_usage: true },
// DeepSeek provider-specific parameter.
// @ts-expect-error OpenAI SDK types may not include DeepSeek-specific fields.
thinking: { type: "disabled" },
});
let finalUsage = null;
for await (const chunk of stream) {
if (chunk.usage) {
finalUsage = chunk.usage;
continue;
}
const content = chunk.choices?.[0]?.delta?.content || "";
process.stdout.write(content);
}
if (finalUsage) {
console.log("\nUsage:", finalUsage);
}
Streaming mistakes to avoid
- Do not assume every chunk contains visible text.
- Do not assume every chunk has
choices[0]. - When using
stream_options={"include_usage": True}, capture the final usage-bearing chunk. - For thinking mode, parse
delta.reasoning_contentanddelta.contentseparately if your workflow needs both.
JSON Output with DeepSeek
Use JSON Output when you need structured data from the model but do not need a real external tool call. Set response_format to {"type": "json_object"}, include the word “json” in the prompt, provide an example JSON shape, set a sensible max_tokens, and validate the parsed result in your application.
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
system_prompt = """
Return only valid json.
Example JSON output:
{
"product_name": "Example Keyboard",
"category": "keyboard",
"price": 49.99,
"currency": "USD"
}
"""
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": "Extract json from this text: The Acme K2 keyboard costs 79.99 USD.",
},
],
response_format={"type": "json_object"},
max_tokens=512,
extra_body={"thinking": {"type": "disabled"}},
)
data = json.loads(response.choices[0].message.content)
print(data)
JSON Output vs Tool Calls
| Use JSON Output when… | Use Tool Calls when… |
|---|---|
| You need classification, extraction, structured summaries, or schema-shaped output. | The model must request a real external function, API, database lookup, or workflow. |
| Your app can continue after parsing one JSON object. | Your app needs a loop: model chooses tool, app runs tool, model sees result, model answers. |
| You want a simpler implementation with no side effects. | You need controlled external actions, trusted data retrieval, or workflow execution. |
Tool Calls / function calling
DeepSeek Tool Calls let the model propose function calls as structured output. Your application executes the function and sends the result back. The model itself does not execute your APIs, database queries, payment operations, shipping actions, or internal workflows.
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
def get_weather(location: str) -> dict:
# Replace this demo result with your real weather API.
return {
"location": location,
"temperature_c": 24,
"condition": "clear"
}
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and region, for example Cairo, Egypt"
}
},
"required": ["location"]
}
}
}
]
messages = [
{"role": "user", "content": "What is the weather in Cairo?"}
]
first_response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=messages,
tools=tools,
tool_choice="auto",
extra_body={"thinking": {"type": "disabled"}},
)
assistant_message = first_response.choices[0].message
messages.append(assistant_message.model_dump(exclude_none=True))
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
if tool_call.function.name == "get_weather":
try:
args = json.loads(tool_call.function.arguments)
except json.JSONDecodeError:
args = {}
location = args.get("location")
if not isinstance(location, str):
tool_result = {"error": "Invalid location"}
else:
tool_result = get_weather(location)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(tool_result),
})
final_response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=messages,
tools=tools,
extra_body={"thinking": {"type": "disabled"}},
)
print(final_response.choices[0].message.content)
else:
print(assistant_message.content)
Tool call flow
- Send the user message and
toolsarray to DeepSeek. - Read
message.tool_callsfrom the assistant response. - Parse and validate the tool arguments.
- Run the matching function in your own application.
- Append the assistant tool-call message to the conversation.
- Append a
toolrole message with the correcttool_call_id. - Send the updated message list back to the model.
- Read the final answer.
Common Tool Calls mistakes
- Expecting the model to execute the function. It only proposes the call.
- Trusting tool arguments without validation.
- Forgetting to append the assistant tool-call message before the tool result.
- Sending a tool result without the matching
tool_call_id. - Using Tool Calls when JSON Output is enough.
- Exposing sensitive write actions without authentication, authorization, and explicit user confirmation.
Tool Calls in thinking mode
For thinking-mode tool workflows, use deepseek-v4-pro when the task needs stronger planning or reasoning. During a thinking + tool-call loop, preserve the full assistant message, including reasoning_content, content, and tool_calls, so the model can continue the same reasoning process after tool results.
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
def run_tool(name: str, arguments: str) -> str:
try:
args = json.loads(arguments or "{}")
except json.JSONDecodeError:
return json.dumps({"error": "Invalid tool arguments"})
if name == "lookup_order_status":
order_id = args.get("order_id")
if not isinstance(order_id, str):
return json.dumps({"error": "Invalid order_id"})
return json.dumps({
"order_id": order_id,
"status": "shipped",
"eta": "2026-04-27"
})
return json.dumps({"error": f"Unknown tool: {name}"})
tools = [
{
"type": "function",
"function": {
"name": "lookup_order_status",
"description": "Look up shipping status for an order ID.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The user's order ID."
}
},
"required": ["order_id"]
}
}
}
]
messages = [
{"role": "user", "content": "Check order A123 and explain whether it will arrive this week."}
]
while True:
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
tool_choice="auto",
reasoning_effort="high",
extra_body={"thinking": {"type": "enabled"}},
)
assistant_message = response.choices[0].message
# Important: append the full assistant message in a thinking + tool-call loop.
messages.append(assistant_message.model_dump(exclude_none=True))
if not assistant_message.tool_calls:
print(assistant_message.content)
break
for tool_call in assistant_message.tool_calls:
tool_result = run_tool(tool_call.function.name, tool_call.function.arguments)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": tool_result,
})
For deeper implementation details, read the DeepSeek Thinking Mode guide and the DeepSeek Tool Calls guide.
Strict mode for Tool Calls
DeepSeek strict mode is a beta Tool Calls feature. Use it when you need tighter schema adherence for function-call arguments. Strict mode requires the beta base URL and strict: true on the function definition.
from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com/beta",
)
tools = [
{
"type": "function",
"function": {
"name": "create_invoice_draft",
"strict": True,
"description": "Create a draft invoice. This does not send the invoice.",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Internal CRM customer ID"
},
"amount_usd": {
"type": "number",
"description": "Invoice amount in USD"
},
"memo": {
"type": "string",
"description": "Short invoice memo"
}
},
"required": ["customer_id", "amount_usd", "memo"],
"additionalProperties": False
}
}
}
]
Even with strict mode, validate every argument in your backend. Strict mode helps with schema shape, but it is not a replacement for authentication, authorization, business rules, rate limits, audit logs, or safety checks.
Token usage and cost with DeepSeek
DeepSeek API pricing is usage-based. Pricing is different for deepseek-v4-flash and deepseek-v4-pro, and deepseek-v4-pro currently has a limited-time discount. Log the model ID with every request and re-check official pricing before production billing decisions.
| Model | Input cache hit | Input cache miss | Output | Important note |
|---|---|---|---|---|
deepseek-v4-flash | $0.028 / 1M tokens | $0.14 / 1M tokens | $0.28 / 1M tokens | Current lower-cost API model for fast and economical workloads. |
deepseek-v4-pro | $0.03625 / 1M tokens | $0.435 / 1M tokens | $0.87 / 1M tokens | Current official limited-time 75% discounted rate, valid until 2026/05/05 15:59 UTC. |
deepseek-v4-pro standard list price | $0.145 / 1M tokens | $1.74 / 1M tokens | $3.48 / 1M tokens | Listed standard price. Re-check the official pricing page after the discount window. |
The request-level formula is:
request_cost =
(prompt_cache_hit_tokens / 1_000_000 * cache_hit_rate) +
(prompt_cache_miss_tokens / 1_000_000 * cache_miss_rate) +
(completion_tokens / 1_000_000 * output_rate)
For production dashboards, log prompt_tokens, completion_tokens, prompt_cache_hit_tokens, prompt_cache_miss_tokens, total_tokens, and completion_tokens_details.reasoning_tokens when present. Read the DeepSeek Token Usage guide for a full accounting workflow.
Legacy aliases: deepseek-chat and deepseek-reasoner
The older names deepseek-chat and deepseek-reasoner are legacy compatibility aliases. They should not be the primary model names in new examples, SDK migration guides, pricing pages, or developer tutorials.
| Legacy alias | Current compatibility behavior | Recommended replacement |
|---|---|---|
deepseek-chat | Currently routes to deepseek-v4-flash non-thinking mode. | deepseek-v4-flash with thinking disabled. |
deepseek-reasoner | Currently routes to deepseek-v4-flash thinking mode. | deepseek-v4-flash or deepseek-v4-pro with thinking enabled. |
Migration rule: replace old examples that use model="deepseek-chat" with model="deepseek-v4-flash", and replace reasoning-heavy examples that use model="deepseek-reasoner" with deepseek-v4-flash or deepseek-v4-pro plus thinking enabled.
Environment variables and security
Store API keys in server-side environment variables, not in client-side code. Secret API credentials should not be exposed in browser JavaScript, mobile app bundles, static pages, public repositories, screenshots, or logs.
Recommended environment variables
# macOS / Linux
export DEEPSEEK_API_KEY="your_deepseek_api_key_here"
# Windows PowerShell
setx DEEPSEEK_API_KEY "your_deepseek_api_key_here"
Security checklist
- Do not place a DeepSeek API key in browser JavaScript.
- Use a backend route, serverless function, or server-side proxy for API calls.
- Use your deployment platform’s secret manager where possible.
- Rotate keys if they are exposed, logged, committed, or shared accidentally.
- Do not log sensitive prompts, uploaded documents, tool arguments, or tool results unless your policy allows it.
- For sensitive use cases, review official DeepSeek terms, privacy, and platform documentation before deployment.
Never ship this in browser-facing code:
new OpenAI({ apiKey: "real_key_here", baseURL: "https://api.deepseek.com" })
Error handling and retries
When using the OpenAI SDK with DeepSeek, the SDK may surface provider HTTP errors from DeepSeek. Handle DeepSeek’s documented error categories and read the error message before retrying.
| Status | Meaning | Likely migration cause | Fix |
|---|---|---|---|
| 400 | Invalid request format | Malformed messages, bad tool order, wrong thinking-mode history, or invalid request body. | Compare your request body with the official Chat Completion schema. |
| 401 | Authentication fails | Wrong API key, missing API key, OpenAI key used against DeepSeek, or DeepSeek key used against OpenAI. | Check DEEPSEEK_API_KEY and provider configuration. |
| 402 | Insufficient balance | DeepSeek account balance is depleted. | Check billing and top up through the official DeepSeek platform. |
| 422 | Invalid parameters | Unsupported or incompatible request parameter. | Remove unsupported parameters and follow the API reference. |
| 429 | Rate limit reached | Requests are being sent too quickly. | Reduce concurrency and use backoff. |
| 500 | Server error | Temporary provider-side issue. | Retry after a short delay. |
| 503 | Server overloaded | High traffic or temporary provider pressure. | Retry after a short delay and use graceful fallback. |
Python retry and timeout example
import os
import openai
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
max_retries=2,
timeout=60.0,
)
try:
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "user", "content": "Return a short migration checklist."}
],
extra_body={"thinking": {"type": "disabled"}},
)
print(response.choices[0].message.content)
except openai.APIStatusError as exc:
print(f"DeepSeek API returned HTTP {exc.status_code}")
print(exc.response)
raise
except openai.APIConnectionError:
print("The SDK could not connect to the API.")
raise
except openai.APITimeoutError:
print("The request timed out.")
raise
Operational retry guidance
- Retry 500 and 503 after a short wait.
- For 429, reduce concurrency and use backoff.
- Do not retry 401 until the API key configuration is fixed.
- Do not retry 402 until the balance issue is resolved.
- For 400 and 422, inspect the request body and API reference before retrying.
Common migration mistakes
- Using old model names: Use
deepseek-v4-flashanddeepseek-v4-proin new code. - Ignoring the legacy-alias retirement date:
deepseek-chatanddeepseek-reasonerare compatibility aliases scheduled for retirement after July 24, 2026, 15:59 UTC. - Using an OpenAI API key with DeepSeek: Create and use a DeepSeek API key.
- Using a DeepSeek API key with the default OpenAI endpoint: Set the DeepSeek base URL.
- Using the wrong SDK option: Python uses
base_url; Node.js usesbaseURL. - Assuming every OpenAI parameter works: Check DeepSeek’s Chat Completion reference for the selected model and mode.
- Ignoring provider-specific TypeScript fields: DeepSeek fields such as
thinkingmay need// @ts-expect-error, a cast, or a wrapper type. - Ignoring thinking-mode output shape: Thinking mode can return
reasoning_contentas well as finalcontent. - Breaking tool-call loops: Preserve full assistant messages during active thinking + tool-call workflows.
- Forgetting streaming usage: Capture the final usage-bearing chunk if you need token accounting.
- Trusting JSON without validation: Always parse and validate JSON Output and tool arguments.
- Exposing API keys in frontend code: Keep all secret-key calls server-side.
- Using only standard Pro pricing while a discount is active: Track the active DeepSeek pricing window and re-check official pricing after it expires.
When should you use the OpenAI SDK with DeepSeek?
Using the OpenAI SDK with DeepSeek is useful when your application already uses OpenAI-compatible Chat Completions and you want to evaluate or add DeepSeek without replacing your entire client layer.
Good fit
- You already have a Python, Node.js, or TypeScript app using the OpenAI SDK.
- You want a quick provider migration test with minimal code changes.
- You are building a multi-provider architecture with a common chat-completions pattern.
- You need to compare cost, latency, and quality using your own prompts.
- You are prototyping chat apps, developer tools, coding assistants, extraction workflows, or internal AI features.
- You need DeepSeek features such as current API models, thinking mode, streaming, JSON Output, or Tool Calls.
Not a good fit
- You need an OpenAI-only endpoint or product feature that DeepSeek does not document.
- Your app relies on undocumented OpenAI model behavior or SDK helpers.
- You cannot safely keep API keys server-side.
- You need legal, compliance, or enterprise approval and have not reviewed DeepSeek’s official terms and documentation.
- You need guaranteed behavior beyond what the official DeepSeek API docs describe.
FAQ
Can I use the OpenAI SDK with DeepSeek?
Yes. DeepSeek documents an OpenAI-compatible API format. Use the OpenAI SDK package, a DeepSeek API key, the DeepSeek base URL, and a current DeepSeek model ID such as deepseek-v4-flash or deepseek-v4-pro.
What base URL should I use for DeepSeek?
Use https://api.deepseek.com for OpenAI-format requests. In Python, pass it as base_url. In Node.js or TypeScript, pass it as baseURL.
Do I need to change my OpenAI SDK package?
Usually no for a basic Chat Completions migration. You can keep the openai SDK package and change the API key, base URL, model name, and provider-specific parameters.
What DeepSeek model name should I use now?
For new integrations, use deepseek-v4-flash for fast and lower-cost workloads, or deepseek-v4-pro for harder reasoning, complex coding, long-context, and agentic workflows.
Should I still use deepseek-chat or deepseek-reasoner?
No for new code. They are legacy compatibility aliases. deepseek-chat currently routes to deepseek-v4-flash non-thinking mode, and deepseek-reasoner currently routes to deepseek-v4-flash thinking mode. DeepSeek states that both aliases will be retired after July 24, 2026, 15:59 UTC.
How do I enable Thinking Mode in Python with the OpenAI SDK?
Use deepseek-v4-flash or deepseek-v4-pro and pass extra_body={"thinking": {"type": "enabled"}}. You can also set reasoning_effort to high or max where appropriate.
How do I pass DeepSeek-specific parameters in TypeScript?
DeepSeek-specific fields such as thinking may not appear in OpenAI’s TypeScript parameter types. You can use // @ts-expect-error, a cast, or your own wrapper type, then test the request against DeepSeek.
Does DeepSeek support streaming with the OpenAI SDK?
Yes. Set stream=True in Python or stream: true in Node.js. If you need usage data, request usage through stream_options and capture the final usage-bearing chunk.
Does DeepSeek support JSON Output?
Yes. Set response_format={"type": "json_object"}, explicitly ask for JSON in the prompt, provide an example JSON shape, set a reasonable max_tokens, and validate the parsed output.
Does DeepSeek support Tool Calls?
Yes. Current DeepSeek API models support Tool Calls. The model proposes the function call, while your application executes the function and sends the result back as a tool message.
Does DeepSeek support strict mode for Tool Calls?
Yes, strict mode is available as a beta Tool Calls feature. It requires the beta base URL and strict: true on the function definition. You should still validate every argument in your backend.
Can I use this directly in the browser?
No. Do not put a DeepSeek API key in browser code. Use a backend route, serverless function, or server-side proxy for any request that requires a secret API key.
Why am I getting 401 errors?
A 401 usually means authentication failed. Check that you are using a valid DeepSeek API key with the DeepSeek base URL, and not an OpenAI key, missing environment variable, or wrong provider configuration.
Why does this page show two prices for deepseek-v4-pro?
The official DeepSeek pricing page currently lists a limited-time 75% discounted rate for deepseek-v4-pro until 2026/05/05 15:59 UTC, plus the standard list price. Re-check official pricing after that date.
Is Chat-Deep.ai the official DeepSeek website?
No. Chat-Deep.ai is an independent DeepSeek guide and browser access site. Use the official DeepSeek platform and documentation for API keys, billing, account management, official limits, and production-critical API information.






