Use the OpenAI SDK with DeepSeek: Python, Node.js, Streaming, JSON Output & Tool Calls

Last verified: April 27, 2026.

You can use the OpenAI SDK package as a client library with DeepSeek because DeepSeek documents an OpenAI-compatible API format. For many developers, this is the fastest way to adapt an existing Python, Node.js, or TypeScript app to call the official DeepSeek API without rewriting the entire request layer.

The main changes are simple: use a DeepSeek API key, set the DeepSeek base URL, use current DeepSeek model IDs, and test provider-specific behavior. The SDK is the client library; DeepSeek is the model provider. This is not the same as using OpenAI’s own models or the full OpenAI platform.

This guide focuses on OpenAI-compatible Chat Completions with DeepSeek. It does not assume that DeepSeek supports every OpenAI endpoint, every OpenAI product feature, every SDK helper, or the OpenAI Responses API.

Independent site notice: 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, OpenAI, Anthropic, Ollama, LM Studio, vLLM, SGLang, Hugging Face, ModelScope, or any model/runtime provider.

Quick Answer

To call DeepSeek with the OpenAI SDK, keep the openai package, replace the API key with a DeepSeek API key, set base_url or baseURL to https://api.deepseek.com, and use deepseek-v4-flash or deepseek-v4-pro as the model.

  • Python: use base_url.
  • Node.js / TypeScript: use baseURL.
  • Security: keep requests server-side and store the API key in an environment variable.
  • Model names: use deepseek-v4-flash or deepseek-v4-pro for new code.
  • Legacy aliases: do not use deepseek-chat or deepseek-reasoner as primary model IDs in new integrations.

What Changes When You Switch from OpenAI to DeepSeek?

If your application already uses the OpenAI SDK, the migration can be small at the request level. The important part is not to assume that every OpenAI-specific feature, endpoint, or model behavior carries over automatically.

SettingOpenAI-only appDeepSeek with OpenAI SDKWhat to verify
SDK packageUses the OpenAI SDK package.Can still use the OpenAI SDK package as a compatible client.Confirm the SDK version works with custom base URLs and Chat Completions.
API keyUses an OpenAI API key.Uses a DeepSeek API key.Use a separate environment variable such as DEEPSEEK_API_KEY.
Base URLUses the OpenAI API endpoint by default.Uses https://api.deepseek.com.Do not send a DeepSeek key to the OpenAI endpoint or an OpenAI key to the DeepSeek endpoint.
Model nameUses OpenAI model IDs.Uses deepseek-v4-flash or deepseek-v4-pro.Do not reuse OpenAI model names or legacy DeepSeek aliases as new-code defaults.
Endpoint styleMay use Responses API or Chat Completions depending on the app.This guide uses OpenAI-compatible Chat Completions.Do not copy OpenAI Responses API examples unless official DeepSeek docs support that exact path.
Thinking modeDepends on the OpenAI model and endpoint.Controlled with thinking and reasoning_effort in DeepSeek’s OpenAI-format API.In Python, pass DeepSeek-specific fields such as thinking through extra_body.
JSON OutputUses OpenAI-specific behavior and model support.Uses DeepSeek JSON Output with response_format={"type":"json_object"}.Include the word “json” in the prompt, provide a JSON example, and validate the output.
Tool CallsApp receives tool calls and executes tools.DeepSeek can propose tool calls; your app executes the function and returns tool results.Validate tool arguments and never let the model directly execute sensitive actions.
StreamingUses SDK streaming for supported endpoints.Uses stream=True in Python or stream: true in Node.js / TypeScript.Not every chunk contains visible text; handle empty deltas defensively.
Error handlingHandles OpenAI API and SDK errors.Handles SDK errors plus DeepSeek-specific HTTP status behavior.Check DeepSeek error-code documentation for model, balance, rate-limit, and server errors.
Pricing assumptionsUses OpenAI billing assumptions.Uses DeepSeek billing rules.Do not reuse OpenAI cost assumptions. Verify current DeepSeek billing details on the official Models & Pricing page.

Install the OpenAI SDK

Install the SDK on the server-side environment where your application will call the DeepSeek API. Do not install this with the goal of exposing a DeepSeek API key in browser JavaScript.

Python

pip install openai

Node.js / TypeScript

npm install openai

For more DeepSeek-specific SDK examples, see the DeepSeek Python SDK guide and the DeepSeek Node.js TypeScript guide.

DeepSeek Base URL Explained

The base URL tells the OpenAI SDK where to send requests. If you keep the OpenAI SDK but change the provider to DeepSeek, the base URL must point to DeepSeek.

For DeepSeek OpenAI-format calls, use:

https://api.deepseek.com

Do not use a DeepSeek API key with the default OpenAI endpoint. Do not use an OpenAI API key with the DeepSeek endpoint. Also, do not confuse the option names: Python uses base_url, while Node.js and TypeScript use baseURL.

EnvironmentSDK optionValueExample
Pythonbase_urlhttps://api.deepseek.comOpenAI(api_key=..., base_url="https://api.deepseek.com")
Node.js / TypeScriptbaseURLhttps://api.deepseek.comnew OpenAI({ apiKey: ..., baseURL: "https://api.deepseek.com" })

DeepSeek also documents an Anthropic-format base URL at https://api.deepseek.com/anthropic. This article stays focused on OpenAI SDK usage. For the broader API overview, see the DeepSeek API guide.

Current DeepSeek Model Selection

For new DeepSeek API integrations, use the current hosted V4 API model IDs:

  • deepseek-v4-flash
  • deepseek-v4-pro

DeepSeek-V4 Preview is the current official DeepSeek generation. The official V4 API line is documented with 1M context length, 384K maximum output, thinking and non-thinking modes, JSON Output, Tool Calls, Chat Prefix Completion beta, and FIM Completion beta in non-thinking mode only.

ModelUse it forSuggested starting modeNotes
deepseek-v4-flashFast chat, summaries, extraction, JSON Output, classification, routine coding help, support bots, and high-volume workloads.Start with non-thinking mode for simple tasks.Use when latency, throughput, and routine task handling matter more than maximum reasoning depth.
deepseek-v4-proHarder reasoning, complex coding, long-context analysis, tool planning, agentic workflows, and higher-value production tasks.Use thinking mode when reasoning quality matters.Use when the task requires deeper planning, careful multi-step reasoning, or higher-quality code analysis.

The names deepseek-chat and deepseek-reasoner are legacy compatibility aliases. DeepSeek states that deepseek-chat currently maps to deepseek-v4-flash non-thinking mode, while deepseek-reasoner currently maps to deepseek-v4-flash thinking mode. These aliases are scheduled to be retired after July 24, 2026, 15:59 UTC.

For model background and naming consistency across the site, see the DeepSeek Models hub and the DeepSeek V4 guide.

Python Example: OpenAI SDK with DeepSeek

This is the minimal server-side Python pattern. It uses the OpenAI SDK package, a DeepSeek API key, the DeepSeek base URL, the current deepseek-v4-flash model, and 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 technical assistant."
        },
        {
            "role": "user",
            "content": "Explain the difference between an API client and a model provider in two short paragraphs."
        }
    ],
    stream=False,
    extra_body={
        "thinking": {
            "type": "disabled"
        }
    }
)

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

Line-by-line notes

  • from openai import OpenAI imports the OpenAI SDK client.
  • DEEPSEEK_API_KEY should be stored as a server-side environment variable.
  • base_url="https://api.deepseek.com" routes the SDK request to DeepSeek.
  • model="deepseek-v4-flash" uses the current hosted DeepSeek V4 Flash API model ID.
  • extra_body passes DeepSeek-specific fields that the Python SDK may not expose as first-class OpenAI parameters.
  • stream=False returns the full response after completion instead of streaming chunks.

Node.js / TypeScript Example

In Node.js and TypeScript, the SDK option is baseURL, not base_url. Keep the API key server-side and avoid browser-based examples that expose secrets.

import OpenAI from "openai";

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

const request = {
  model: "deepseek-v4-flash",
  messages: [
    {
      role: "system",
      content: "You are a concise technical assistant."
    },
    {
      role: "user",
      content: "List three migration checks before switching an app to a new model provider."
    }
  ],
  stream: false,
  thinking: {
    type: "disabled"
  }
} as any;

const response = await client.chat.completions.create(request);

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

TypeScript may not know every DeepSeek-specific field, such as thinking. Use a typed wrapper, a narrow provider-specific request type, a cast, or a controlled // @ts-expect-error where appropriate. The important point is to test the final request against DeepSeek, not only against TypeScript’s OpenAI-oriented types.

Thinking and Non-Thinking Mode

Both current V4 API models support thinking and non-thinking modes. Thinking mode is better for hard reasoning, complex coding, agent planning, long-context analysis, and tasks where the model benefits from more deliberate reasoning. Non-thinking mode is better for fast chat, summaries, extraction, simple JSON, classification, and routine outputs.

In OpenAI format, DeepSeek uses:

{"thinking": {"type": "enabled"}}

or:

{"thinking": {"type": "disabled"}}

For Python with the OpenAI SDK, pass thinking through extra_body. When using thinking mode, reasoning_effort can be set to high or max. Do not present temperature, top_p, presence_penalty, or frequency_penalty as reliable controls for thinking-mode behavior.

Python: thinking mode with deepseek-v4-pro

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-pro",
    messages=[
        {
            "role": "user",
            "content": "Design a safe retry strategy for an AI tool that may call external APIs."
        }
    ],
    reasoning_effort="high",
    extra_body={
        "thinking": {
            "type": "enabled"
        }
    }
)

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

Python: non-thinking mode with deepseek-v4-flash

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": "user",
            "content": "Summarize this migration checklist in five bullets."
        }
    ],
    extra_body={
        "thinking": {
            "type": "disabled"
        }
    }
)

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

Streaming Responses

Streaming is useful for chat UIs, long answers, coding assistants, and any workflow where the user should see output before the full response is finished. Python uses stream=True. Node.js and TypeScript use stream: true.

Not every streaming chunk contains visible text. In thinking mode, your workflow may also need to separate reasoning_content from final content. If you request usage information through supported stream options, capture the final usage-bearing chunk rather than assuming every chunk includes usage data.

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": "Give a short checklist for migrating a Python app to DeepSeek."
        }
    ],
    stream=True,
    extra_body={
        "thinking": {
            "type": "disabled"
        }
    }
)

for chunk in stream:
    delta = chunk.choices[0].delta
    text = getattr(delta, "content", None)
    if text:
        print(text, end="", flush=True)

Node.js / TypeScript 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: "Give a short checklist for migrating a Node.js app to DeepSeek."
    }
  ],
  stream: true,
  thinking: {
    type: "disabled"
  }
} as any);

for await (const chunk of stream) {
  const delta = chunk.choices?.[0]?.delta as any;
  if (delta?.content) {
    process.stdout.write(delta.content);
  }
}

JSON Output with DeepSeek

JSON Output is for structured model output. It is not the same as external tool execution. Use it when your app needs the model to return a parseable JSON object for classification, extraction, routing, analysis, or backend processing.

For DeepSeek JSON Output:

  • Set response_format={"type":"json_object"}.
  • Include the word “json” in the system or user prompt.
  • Provide an example JSON shape.
  • Set a reasonable max_tokens value.
  • Parse and validate the output in backend code.
  • Handle empty, truncated, or malformed content defensively.

For a dedicated guide, see DeepSeek JSON Output.

Python JSON Output example

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.

Extract a task from the user's message.

Example JSON shape:
{
  "task": "string",
  "priority": "low | medium | high",
  "owner": "string | null"
}
"""

response = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": "Please ask Maya to review the API migration plan today. This is important."}
    ],
    response_format={
        "type": "json_object"
    },
    max_tokens=500,
    extra_body={
        "thinking": {
            "type": "disabled"
        }
    }
)

raw_content = response.choices[0].message.content or "{}"

try:
    parsed = json.loads(raw_content)
except json.JSONDecodeError as exc:
    raise ValueError("The model did not return valid JSON.") from exc

required_keys = {"task", "priority", "owner"}
if not required_keys.issubset(parsed):
    raise ValueError("The JSON response is missing required keys.")

print(parsed)

Tool Calls / Function Calling

Tool Calls let the model propose a function call. The application executes the function and returns the tool result. The model does not execute external APIs, databases, payments, shell commands, emails, or workflows by itself.

For production use, validate tool arguments before executing anything. Do not allow unrestricted file access, shell commands, database writes, payment actions, email sending, or network requests without authorization and logging.

For a deeper walkthrough, see DeepSeek Tool Calls.

Python Tool Calls example

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_order_status(order_id: str) -> str:
    demo_orders = {
        "ORD-1001": "Processing",
        "ORD-1002": "Shipped",
        "ORD-1003": "Delivered"
    }
    return demo_orders.get(order_id, "Unknown order")

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_order_status",
            "description": "Look up the status of a demo order by order ID.",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID, for example ORD-1002."
                    }
                },
                "required": ["order_id"]
            }
        }
    }
]

messages = [
    {
        "role": "user",
        "content": "What is the status of order ORD-1002?"
    }
]

first_response = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=messages,
    tools=tools,
    extra_body={
        "thinking": {
            "type": "disabled"
        }
    }
)

assistant_message = first_response.choices[0].message
tool_calls = assistant_message.tool_calls or []

messages.append(assistant_message.model_dump(exclude_none=True))

for tool_call in tool_calls:
    if tool_call.function.name != "get_order_status":
        raise ValueError("Unsupported tool call.")

    arguments = json.loads(tool_call.function.arguments)
    order_id = arguments.get("order_id")

    if not isinstance(order_id, str) or not order_id.startswith("ORD-"):
        raise ValueError("Invalid order_id argument.")

    tool_result = get_order_status(order_id)

    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": tool_result
    })

final_response = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=messages,
    extra_body={
        "thinking": {
            "type": "disabled"
        }
    }
)

print(final_response.choices[0].message.content)

Tool Calls in Thinking Mode

DeepSeek supports tool use in thinking mode. When a tool call happens in thinking mode, preserve and return the required reasoning and tool-call fields according to the official documentation. Mishandling reasoning_content in tool-call loops can cause errors because the model may need that reasoning state to continue the tool workflow correctly.

A practical rule is to avoid manually reconstructing assistant messages unless you know exactly which fields must be carried forward. When possible, append the assistant message object or a complete serialized equivalent that includes content, reasoning_content, and tool_calls when they are present.

Strict Mode for Tool Calls

Strict mode for Tool Calls is beta. It helps the model follow the function’s JSON Schema more closely, but it is not a substitute for backend validation or authorization.

To use strict mode, DeepSeek documents three important requirements:

  • Use the beta base URL: https://api.deepseek.com/beta.
  • Set strict: true inside each function definition.
  • Use JSON Schema that follows DeepSeek’s supported schema rules.

Strict mode can reduce schema drift, but your application should still validate tool arguments before running a function. It should also enforce permissions before any sensitive tool action.

Where to Verify Current DeepSeek API Pricing

Because official API prices, billing categories, and promotions can change, this article does not publish static prices. For current public rates, always check the official DeepSeek Models & Pricing page.

For a plain-English site guide that avoids copying live rates into every developer article, see the DeepSeek pricing guide.

Context Caching and Token Usage

DeepSeek documents context caching as enabled by default. This can matter for repeated prompts, repeated system instructions, long-context requests, and workflows where many requests share overlapping prefixes.

Do not promise fixed savings from caching. Inspect usage fields such as cache hit and cache miss tokens, and read the official documentation before making billing or architecture decisions. For supporting material, see DeepSeek Context Caching and DeepSeek Token Usage.

Security and Environment Variables

Use a dedicated environment variable such as DEEPSEEK_API_KEY. Keep API keys server-side and do not expose them in frontend JavaScript, public repositories, screenshots, mobile app bundles, logs, browser extensions, or static pages.

  • Do not commit API keys to Git.
  • Do not log request headers or full prompts when sensitive data is involved.
  • Use a secret manager in production.
  • Rotate keys immediately if they are exposed.
  • Separate OpenAI and DeepSeek keys.
  • Use different environment variables for each provider.
  • Avoid copying .env files into public repositories, build artifacts, Docker images, or deployment logs.

If your organization handles regulated, customer-sensitive, financial, medical, legal, or enterprise data, review vendor approval, privacy rules, logging, retention, and security requirements before sending prompts to any hosted API.

Error Handling, Retries, and Timeouts

The OpenAI SDK may surface provider HTTP errors through SDK error classes. However, DeepSeek-specific status codes and behavior should be checked against the official DeepSeek error-code documentation and tested in your application.

Handle common cases:

  • Wrong API key.
  • Wrong base URL.
  • Wrong model name.
  • Invalid JSON schema.
  • Insufficient balance or account billing state.
  • Rate limits.
  • Timeouts.
  • Temporary server errors.

Add retry logic carefully. Do not blindly retry tool actions with side effects, such as payments, database writes, external API calls, emails, or file operations. For implementation notes, see the DeepSeek Error Codes guide.

When Should You Use the OpenAI SDK with DeepSeek?

Use the OpenAI SDK with DeepSeek when:

  • You already have Python, Node.js, or TypeScript code using the OpenAI SDK.
  • You want a quick DeepSeek migration test.
  • You are building a provider-switching layer.
  • You need Chat Completions-style requests.
  • You want streaming, JSON Output, Tool Calls, or thinking/non-thinking mode with DeepSeek.

This approach may not be a good fit when:

  • You need an OpenAI-only product or endpoint.
  • Your app depends on OpenAI Responses API features.
  • You need unsupported SDK helpers.
  • You cannot keep API keys server-side.
  • Your organization has not approved DeepSeek API usage for sensitive data.

FAQ

Can I use the OpenAI SDK with DeepSeek?

Yes. DeepSeek documents an API format compatible with OpenAI, so you can use the OpenAI SDK as a client library by setting the DeepSeek base URL, using a DeepSeek API key, and selecting a current DeepSeek model ID.

What base URL should I use for DeepSeek?

For OpenAI-format calls, use https://api.deepseek.com. In Python, set it with base_url. In Node.js and TypeScript, set it with baseURL.

Do I need to change my OpenAI SDK package?

Usually no. You can keep the openai package and change the API key, base URL, model name, and provider-specific parameters. You still need to test behavior against DeepSeek.

What DeepSeek model name should I use now?

Use deepseek-v4-flash for fast everyday tasks and deepseek-v4-pro for harder reasoning, complex coding, long-context analysis, and higher-value production workflows.

Should I still use deepseek-chat or deepseek-reasoner?

For new integrations, no. Treat deepseek-chat and deepseek-reasoner as legacy compatibility aliases. Use deepseek-v4-flash or deepseek-v4-pro in new examples.

How do I enable thinking mode with the OpenAI SDK?

Use {"thinking":{"type":"enabled"}}. In Python with the OpenAI SDK, pass this through extra_body. You can also use reasoning_effort="high" or reasoning_effort="max" where appropriate.

How do I disable thinking mode?

Use {"thinking":{"type":"disabled"}}. This is useful for fast chat, extraction, classification, simple JSON, summaries, and routine outputs.

How do I pass DeepSeek-specific parameters in TypeScript?

TypeScript types may not include every DeepSeek-specific field. Use a provider-specific wrapper type, a controlled cast, or // @ts-expect-error where appropriate, then test the request against DeepSeek.

Does DeepSeek support streaming with the OpenAI SDK?

Yes. Use stream=True in Python or stream: true in Node.js / TypeScript. Handle chunks defensively because not every chunk contains visible text.

Does DeepSeek support JSON Output?

Yes. Use response_format={"type":"json_object"}, include the word “json” in the prompt, provide an example JSON shape, set a reasonable output limit, and validate the result in backend code.

Does DeepSeek support Tool Calls?

Yes. Tool Calls let the model propose a function call. Your application executes the function and returns the result. The model does not execute tools by itself.

Can I use this directly in the browser?

No. Do not put DEEPSEEK_API_KEY in browser JavaScript, frontend bundles, public static pages, mobile apps, screenshots, or public repositories. Use a server-side route or backend service.

Where should I check DeepSeek API pricing?

Check the official DeepSeek Models & Pricing page. This article does not publish static prices because official prices, billing categories, and promotions can change.

Is Chat-Deep.ai the official DeepSeek platform?

No. Chat-Deep.ai is an independent DeepSeek guide and browser-access site. It is not the official DeepSeek platform, app, developer console, or API provider.